Reject grids exceeding the 'dimg' reference count limit (#3354) avifEncoderAddImageGrid() now refuses grids with more than 65535 cells (e.g. 256x256 cells) upfront with AVIF_RESULT_INVALID_IMAGE_GRID and a diagnostic: Section 8.11.12.1 of ISO/IEC 14496-12 requires all the references from one item to be collected into a single item type reference box whose reference_count field is unsigned int(16) whatever the 'iref' version, and ISO/IEC 23008-12 (HEIF) Section 6.6.1 forbids more than one 'dimg' box with the same from_item_ID. Such grids therefore cannot be encoded in a conformant way, whatever the item ID width, and used to silently generate a broken file instead. Co-authored-by: krishna28238-arch <319297638+krishna28238-arch@users.noreply.github.com>
diff --git a/src/write.c b/src/write.c index 6980909..50a451e 100644 --- a/src/write.c +++ b/src/write.c
@@ -2154,6 +2154,20 @@ if ((gridCols == 0) || (gridCols > 256) || (gridRows == 0) || (gridRows > 256)) { return AVIF_RESULT_INVALID_IMAGE_GRID; } + if ((uint64_t)gridCols * gridRows > 65535) { + // Section 8.11.12.1 of ISO/IEC 14496-12: "All the references for one item of a specific type + // are collected into a single item type reference box", whose reference_count field is + // unsigned int(16) whatever the 'iref' version (Section 8.11.12.2). Moreover, ISO/IEC 23008-12 + // (HEIF) Section 6.6.1 states that "The number of SingleItemTypeReferenceBoxes with the box + // type 'dimg' and with the same value of from_item_ID shall not be greater than 1". + // A grid item therefore cannot reference more than 65535 cell items, so a 256x256-cell grid + // cannot be encoded in a conformant way, whatever the item ID width. + avifDiagnosticsPrintf(&encoder->diag, + "avifEncoderAddImageGrid() failed because a grid cannot have more than 65535 cells due to the 16-bit 'dimg' reference_count field (%u columns x %u rows)", + gridCols, + gridRows); + return AVIF_RESULT_INVALID_IMAGE_GRID; + } if (encoder->extraLayerCount == 0) { addImageFlags |= AVIF_ADD_IMAGE_FLAG_SINGLE; // image grids cannot be image sequences }
diff --git a/tests/gtest/avifgridapitest.cc b/tests/gtest/avifgridapitest.cc index 26efff0..2168e7a 100644 --- a/tests/gtest/avifgridapitest.cc +++ b/tests/gtest/avifgridapitest.cc
@@ -277,5 +277,29 @@ AVIF_RESULT_INVALID_IMAGE_GRID); } +TEST(GridApiTest, CellsTooManyForDimgReferenceCount) { + // Section 8.11.12.1 of ISO/IEC 14496-12 requires all the references from one + // item to be collected into a single item type reference box, whose + // reference_count field is unsigned int(16) whatever the 'iref' version + // (Section 8.11.12.2). ISO/IEC 23008-12 (HEIF) Section 6.6.1 additionally + // forbids more than one 'dimg' box with the same from_item_ID. A grid item + // therefore cannot have more than 65535 cells, so a 256x256-cell grid is + // rejected upfront instead of silently generating a broken file. + ImagePtr cell = testutil::CreateImage( + /*width=*/64, /*height=*/64, /*depth=*/8, AVIF_PIXEL_FORMAT_YUV400, + AVIF_PLANES_YUV); + ASSERT_NE(cell, nullptr); + testutil::FillImageGradient(cell.get()); + const std::vector<avifImage*> cell_image_ptrs(256 * 256, cell.get()); + + EncoderPtr encoder(avifEncoderCreate()); + ASSERT_NE(encoder, nullptr); + encoder->speed = AVIF_SPEED_FASTEST; + ASSERT_EQ(avifEncoderAddImageGrid(encoder.get(), /*gridCols=*/256, + /*gridRows=*/256, cell_image_ptrs.data(), + AVIF_ADD_IMAGE_FLAG_SINGLE), + AVIF_RESULT_INVALID_IMAGE_GRID); +} + } // namespace } // namespace avif