Skip to content

Potential null pointer dereference in avifImageApplyExpression32b during Sample Transform handling #2979

@X-ANOY

Description

@X-ANOY

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;
}

seed.avif.zip

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

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions