Make image size limit configurable, expose to avifdec
diff --git a/apps/avifdec.c b/apps/avifdec.c index 2e1d7ee..b4aafbd 100644 --- a/apps/avifdec.c +++ b/apps/avifdec.c
@@ -36,6 +36,8 @@ printf(" -u,--upsampling U : Chroma upsampling (for 420/422). automatic (default), fastest, best, nearest, or bilinear\n"); printf(" -i,--info : Decode all frames and display all image information instead of saving to disk\n"); printf(" --ignore-icc : If the input file contains an embedded ICC profile, ignore it (no-op if absent)\n"); + printf(" --size-limit C : Specifies the image size limit (in total pixels) that the AV1 codec should tolerate.\n"); + printf(" Default: %u, set to 0 to disable. Supported codecs: dav1d.\n", AVIF_MAX_IMAGE_SIZE); printf("\n"); avifPrintVersions(); } @@ -91,6 +93,7 @@ avifBool infoOnly = AVIF_FALSE; avifChromaUpsampling chromaUpsampling = AVIF_CHROMA_UPSAMPLING_AUTOMATIC; avifBool ignoreICC = AVIF_FALSE; + uint32_t imageSizeLimit = AVIF_MAX_IMAGE_SIZE; if (argc < 2) { syntax(); @@ -161,6 +164,9 @@ infoOnly = AVIF_TRUE; } else if (!strcmp(arg, "--ignore-icc")) { ignoreICC = AVIF_TRUE; + } else if (!strcmp(arg, "--size-limit")) { + NEXTARG(); + imageSizeLimit = strtoul(arg, NULL, 10); } else { // Positional argument if (!inputFilename) { @@ -205,6 +211,7 @@ avifDecoder * decoder = avifDecoderCreate(); decoder->maxThreads = jobs; decoder->codecChoice = codecChoice; + decoder->imageSizeLimit = imageSizeLimit; avifResult decodeResult = avifDecoderReadFile(decoder, avif, inputFilename); if (decodeResult == AVIF_RESULT_OK) { printf("Image decoded: %s\n", inputFilename);
diff --git a/include/avif/avif.h b/include/avif/avif.h index bb5a598..e8e452a 100644 --- a/include/avif/avif.h +++ b/include/avif/avif.h
@@ -76,6 +76,10 @@ #define AVIF_SPEED_SLOWEST 0 #define AVIF_SPEED_FASTEST 10 +// A maximum image size to avoid out-of-memory errors or integer overflow in +// (32-bit) int or unsigned int arithmetic operations. +#define AVIF_MAX_IMAGE_SIZE (16384 * 16384) + enum avifPlanesFlags { AVIF_PLANES_YUV = (1 << 0), @@ -701,6 +705,11 @@ avifBool ignoreExif; avifBool ignoreXMP; + // This represents the maximum size of a image (in pixel count) that the underlying AV1 decoder + // should attempt to decode. It defaults to AVIF_MAX_IMAGE_SIZE, and can be set to 0 to disable + // the limit. Currently supported codecs: dav1d. + uint32_t imageSizeLimit; + // stats from the most recent read, possibly 0s if reading an image sequence avifIOStats ioStats;
diff --git a/include/avif/internal.h b/include/avif/internal.h index 380081a..5ad5e99 100644 --- a/include/avif/internal.h +++ b/include/avif/internal.h
@@ -330,10 +330,6 @@ } avifSequenceHeader; avifBool avifSequenceHeaderParse(avifSequenceHeader * header, const avifROData * sample); -// A maximum image size to avoid out-of-memory errors or integer overflow in -// (32-bit) int or unsigned int arithmetic operations. -#define AVIF_MAX_IMAGE_SIZE (16384 * 16384) - #ifdef __cplusplus } // extern "C" #endif
diff --git a/src/codec_dav1d.c b/src/codec_dav1d.c index 054f846..65a78be 100644 --- a/src/codec_dav1d.c +++ b/src/codec_dav1d.c
@@ -55,6 +55,7 @@ // Give all available threads to decode a single frame as fast as possible codec->internal->dav1dSettings.n_frame_threads = 1; codec->internal->dav1dSettings.n_tile_threads = AVIF_CLAMP(decoder->maxThreads, 1, DAV1D_MAX_TILE_THREADS); + codec->internal->dav1dSettings.frame_size_limit = decoder->imageSizeLimit; if (dav1d_open(&codec->internal->dav1dContext, &codec->internal->dav1dSettings) != 0) { return AVIF_FALSE; @@ -209,9 +210,6 @@ memset(codec->internal, 0, sizeof(struct avifCodecInternal)); dav1d_default_settings(&codec->internal->dav1dSettings); - // Set a maximum frame size limit to avoid OOM'ing fuzzers. - codec->internal->dav1dSettings.frame_size_limit = AVIF_MAX_IMAGE_SIZE; - // Ensure that we only get the "highest spatial layer" as a single frame // for each input sample, instead of getting each spatial layer as its own // frame one at a time ("all layers").