From 3ae959c490238064bd8e32e840f0b61eb10cccb0 Mon Sep 17 00:00:00 2001 From: littlepig12345 <333244345+littlepig12345@users.noreply.github.com> Date: Thu, 24 Sep 2026 19:04:52 +0800 Subject: [PATCH 1/4] Bound iloc extent_count to prevent memory amplification --- src/read.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/read.c b/src/read.c index 64640e1584..a9bac396cf 100644 --- a/src/read.c +++ b/src/read.c @@ -2154,6 +2154,10 @@ static avifResult avifParseItemLocationBox(avifMeta * meta, const uint8_t * raw, AVIF_CHECKERR(avifROStreamReadUX8(&s, &baseOffset, baseOffsetSize), AVIF_RESULT_BMFF_PARSE_FAILED); // unsigned int(base_offset_size*8) base_offset; uint16_t extentCount; AVIF_CHECKERR(avifROStreamReadU16(&s, &extentCount), AVIF_RESULT_BMFF_PARSE_FAILED); // unsigned int(16) extent_count; + if (extentCount > 256) { + avifDiagnosticsPrintf(diag, "Item ID [%u] extent count [%u] exceeds the maximum allowed [256]", itemID, extentCount); + return AVIF_RESULT_BMFF_PARSE_FAILED; + } for (int extentIter = 0; extentIter < extentCount; ++extentIter) { if ((version == 1 || version == 2) && indexSize > 0) { // Section 8.11.3.1 of ISO/IEC 14496-12: From 64bae73a6026d5b70c76e9b6c5394f406527fc67 Mon Sep 17 00:00:00 2001 From: littlepig12345 <333244345+littlepig12345@users.noreply.github.com> Date: Thu, 24 Sep 2026 20:58:10 +0800 Subject: [PATCH 2/4] Bound iloc extent_count to prevent memory amplification- #3375 --- src/read.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/read.c b/src/read.c index a9bac396cf..ef48e90fd0 100644 --- a/src/read.c +++ b/src/read.c @@ -2154,9 +2154,8 @@ static avifResult avifParseItemLocationBox(avifMeta * meta, const uint8_t * raw, AVIF_CHECKERR(avifROStreamReadUX8(&s, &baseOffset, baseOffsetSize), AVIF_RESULT_BMFF_PARSE_FAILED); // unsigned int(base_offset_size*8) base_offset; uint16_t extentCount; AVIF_CHECKERR(avifROStreamReadU16(&s, &extentCount), AVIF_RESULT_BMFF_PARSE_FAILED); // unsigned int(16) extent_count; - if (extentCount > 256) { - avifDiagnosticsPrintf(diag, "Item ID [%u] extent count [%u] exceeds the maximum allowed [256]", itemID, extentCount); - return AVIF_RESULT_BMFF_PARSE_FAILED; + if ((version == 0 || indexSize == 0) && offsetSize == 0 && lengthSize == 0) { + extentCount = 0; } for (int extentIter = 0; extentIter < extentCount; ++extentIter) { if ((version == 1 || version == 2) && indexSize > 0) { From 730f2f722687cd26ada4b0ce2a33a14b479da289 Mon Sep 17 00:00:00 2001 From: littlepig12345 <333244345+littlepig12345@users.noreply.github.com> Date: Fri, 25 Sep 2026 22:55:54 +0800 Subject: [PATCH 3/4] Update read.c --- src/read.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/read.c b/src/read.c index ef48e90fd0..6d1cae8d61 100644 --- a/src/read.c +++ b/src/read.c @@ -2154,8 +2154,12 @@ static avifResult avifParseItemLocationBox(avifMeta * meta, const uint8_t * raw, AVIF_CHECKERR(avifROStreamReadUX8(&s, &baseOffset, baseOffsetSize), AVIF_RESULT_BMFF_PARSE_FAILED); // unsigned int(base_offset_size*8) base_offset; uint16_t extentCount; AVIF_CHECKERR(avifROStreamReadU16(&s, &extentCount), AVIF_RESULT_BMFF_PARSE_FAILED); // unsigned int(16) extent_count; - if ((version == 0 || indexSize == 0) && offsetSize == 0 && lengthSize == 0) { - extentCount = 0; + const uint64_t bytesPerExtent = indexSize + offsetSize + lengthSize; + if (extentCount > 0 && bytesPerExtent == 0) { + return AVIF_RESULT_BMFF_PARSE_FAILED; + } + if (bytesPerExtent > 0 && (uint64_t)extentCount * bytesPerExtent > avifROStreamRemainingBytes(&s)) { + return AVIF_RESULT_BMFF_PARSE_FAILED; } for (int extentIter = 0; extentIter < extentCount; ++extentIter) { if ((version == 1 || version == 2) && indexSize > 0) { @@ -2172,7 +2176,9 @@ static avifResult avifParseItemLocationBox(avifMeta * meta, const uint8_t * raw, AVIF_CHECKERR(avifROStreamReadUX8(&s, &extentOffset, offsetSize), AVIF_RESULT_BMFF_PARSE_FAILED); // unsigned int(offset_size*8) extent_offset; uint64_t extentLength; AVIF_CHECKERR(avifROStreamReadUX8(&s, &extentLength, lengthSize), AVIF_RESULT_BMFF_PARSE_FAILED); // unsigned int(length_size*8) extent_length; - + if (lengthSize > 0 && extentLength == 0) { + return AVIF_RESULT_NOT_IMPLEMENTED; + } avifExtent * extent = (avifExtent *)avifArrayPush(&item->extents); AVIF_CHECKERR(extent != NULL, AVIF_RESULT_OUT_OF_MEMORY); if (extentOffset > UINT64_MAX - baseOffset) { From d7ea324445c48eaafd33d16308e62f6aa7f3459d Mon Sep 17 00:00:00 2001 From: littlepig12345 <333244345+littlepig12345@users.noreply.github.com> Date: Sat, 26 Sep 2026 12:56:14 +0800 Subject: [PATCH 4/4] Bound iloc extent_count to prevent memory amplification --- src/read.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/read.c b/src/read.c index 6d1cae8d61..e6078e1362 100644 --- a/src/read.c +++ b/src/read.c @@ -2154,11 +2154,18 @@ static avifResult avifParseItemLocationBox(avifMeta * meta, const uint8_t * raw, AVIF_CHECKERR(avifROStreamReadUX8(&s, &baseOffset, baseOffsetSize), AVIF_RESULT_BMFF_PARSE_FAILED); // unsigned int(base_offset_size*8) base_offset; uint16_t extentCount; AVIF_CHECKERR(avifROStreamReadU16(&s, &extentCount), AVIF_RESULT_BMFF_PARSE_FAILED); // unsigned int(16) extent_count; - const uint64_t bytesPerExtent = indexSize + offsetSize + lengthSize; - if (extentCount > 0 && bytesPerExtent == 0) { + const uint32_t bytesPerExtent = indexSize + offsetSize + lengthSize; + if (bytesPerExtent == 0 && extentCount > 1) { + avifDiagnosticsPrintf(diag, "Item ID [%u] declares %u extents that consume no input bytes", itemID, extentCount); return AVIF_RESULT_BMFF_PARSE_FAILED; } - if (bytesPerExtent > 0 && (uint64_t)extentCount * bytesPerExtent > avifROStreamRemainingBytes(&s)) { + const size_t remainingBytes = avifROStreamRemainingBytes(&s); + if ((uint64_t)extentCount * bytesPerExtent > remainingBytes) { + avifDiagnosticsPrintf(diag, + "Item ID [%u] extent_count [%u] exceeds the remaining %zu bytes of the iloc box", + itemID, + extentCount, + remainingBytes); return AVIF_RESULT_BMFF_PARSE_FAILED; } for (int extentIter = 0; extentIter < extentCount; ++extentIter) { @@ -2176,7 +2183,9 @@ static avifResult avifParseItemLocationBox(avifMeta * meta, const uint8_t * raw, AVIF_CHECKERR(avifROStreamReadUX8(&s, &extentOffset, offsetSize), AVIF_RESULT_BMFF_PARSE_FAILED); // unsigned int(offset_size*8) extent_offset; uint64_t extentLength; AVIF_CHECKERR(avifROStreamReadUX8(&s, &extentLength, lengthSize), AVIF_RESULT_BMFF_PARSE_FAILED); // unsigned int(length_size*8) extent_length; + // ISO/IEC 14496-12, Section 8.11.3.2.4.3: extent_length == 0 is not supported by libavif. if (lengthSize > 0 && extentLength == 0) { + avifDiagnosticsPrintf(diag, "Item ID [%u] uses extent_length = 0, which is not supported", itemID); return AVIF_RESULT_NOT_IMPLEMENTED; } avifExtent * extent = (avifExtent *)avifArrayPush(&item->extents);