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").