-
Notifications
You must be signed in to change notification settings - Fork 272
Description
Hi, I found a potential null pointer dereference while fuzzing libavif. The issue is triggered when decoding a malformed AVIF file using the default decoder configuration created via avifDecoderCreate().
The issue is related to the handling of the Sample Transform (stpe) property. While the metadata is parsed successfully, the decoder proceeds to pixel calculations without ensuring the required image planes have been allocated, leading to a SEGV in the transformation logic.
The segmentation fault occurs in src/sampletransform.c within avifImageApplyExpression32b.
The implementation assumes that if a transform is defined, the necessary image planes for the target channels are present. It calls avifImagePlane(image, c) and immediately performs pointer arithmetic:
const uint8_t * row = avifImagePlane(image, c) + avifImagePlaneRowBytes(image, c) * y;
In the provided sample, avifImagePlane returns NULL. The lack of a null-check before dereferencing or performing arithmetic on this pointer causes the crash.
Reproduction
1.poc.c:
#include <avif/avif.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
if (argc < 2) return 1;
FILE *f = fopen(argv[1], "rb");
if (!f) return 1;
fseek(f, 0, SEEK_END);
size_t size = ftell(f);
fseek(f, 0, SEEK_SET);
uint8_t *data = malloc(size);
fread(data, 1, size, f);
fclose(f);
if (size < 12) return 1;
avifDecoder *decoder = avifDecoderCreate();
avifImage *image = avifImageCreateEmpty();
decoder->ignoreExif = (data[0] & 0x01) ? AVIF_TRUE : AVIF_FALSE;
decoder->ignoreXMP = (data[0] & 0x02) ? AVIF_TRUE : AVIF_FALSE;
decoder->allowProgressive = (data[0] & 0x04) ? AVIF_TRUE : AVIF_FALSE;
decoder->allowIncremental = (data[0] & 0x08) ? AVIF_TRUE : AVIF_FALSE;
decoder->imageContentToDecode = 0;
if (data[1] & 0x01) decoder->imageContentToDecode |= AVIF_IMAGE_CONTENT_COLOR_AND_ALPHA;
if (data[1] & 0x08) decoder->imageContentToDecode |= AVIF_IMAGE_CONTENT_GAIN_MAP;
decoder->requestedSource = (data[2] & 0x03) == 1 ? AVIF_DECODER_SOURCE_PRIMARY_ITEM : AVIF_DECODER_SOURCE_AUTO;
avifDecoderReadMemory(decoder, image, data, size);
avifImageDestroy(image);
avifDecoderDestroy(decoder);
free(data);
return 0;
}2. Compilation and Execution:
# Compile command (with AddressSanitizer)
afl-clang-fast -o poc poc.c -I ./libavif/include ./libavif/build/libavif.a -fsanitize=address
# Execute
./poc seed.avif
ASan Log
AddressSanitizer: DEADLYSIGNAL
=================================================================
==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x5f8e485d3cc1 bp 0x000000000001 sp 0x7ffef9b921c0 T0)
The signal is caused by a READ memory access.
Hint: address points to the zero page.
#0 0x... in avifImageApplyExpression32b src/sampletransform.c:319:72
#1 0x... in avifImageApplyExpression src/sampletransform.c:378:35
#2 0x... in avifDecoderApplySampleTransformForPlanesImpl src/read.c:6810:5
#3 0x... in avifDecoderApplySampleTransformForPlanes src/read.c:6823:31
#4 0x... in avifDecoderApplySampleTransform src/read.c:6857:5
#5 0x... in avifDecoderNextImage src/read.c:6934:9
#6 0x... in avifDecoderRead src/read.c:7136:14
#7 0x... in avifDecoderReadMemory src/read.c:7156:12
#8 0x... in main poc.c:35:5
#9 0x... in (/lib/x86_64-linux-gnu/libc.so.6+0x2a1c9)
#10 0x... in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2a28a)
#11 0x... in _start (poc+0x3eee4)
SUMMARY: AddressSanitizer: SEGV src/sampletransform.c:319:72 in avifImageApplyExpression32b