Remove potential out of bound access to alphaItemIndices
It is possible to craft a file that has more alpha auxiliary items
than color items and trigger an out of bound access into
alphaItemIndices in the for loop.
Fix is to ensure that each color grid item has exactly one alpha
grid item. Also, ensure that there are exactly the same number of
color grids as informed in the grid config before trying to
find the alpha item.
Also, update a diagnostic error message to cover all cases (i.e.)
there can be more grids than necessary as well.
This is a manual cherry-pick of commit `6d62963` (PR #1756) on to
v1.0.x branch.
diff --git a/src/read.c b/src/read.c
index 0fd5d3f..e3bad98 100644
--- a/src/read.c
+++ b/src/read.c
@@ -1419,7 +1419,7 @@
if (tilesAvailable != grid->rows * grid->columns) {
avifDiagnosticsPrintf(&decoder->diag,
- "Grid image of dimensions %ux%u requires %u tiles, and only %u were found",
+ "Grid image of dimensions %ux%u requires %u tiles, but %u were found",
grid->columns,
grid->rows,
grid->rows * grid->columns,
@@ -3664,21 +3664,33 @@
maxItemID = item->id;
}
if (item->dimgForID == colorItem->id) {
+ avifBool seenAlphaForCurrentItem = AVIF_FALSE;
for (uint32_t j = 0; j < colorItem->meta->items.count; ++j) {
avifDecoderItem * auxlItem = &colorItem->meta->items.item[j];
if (avifDecoderItemIsAlphaAux(auxlItem, item->id)) {
+ if (seenAlphaForCurrentItem || auxlItem->dimgForID != 0) {
+ // One of the following invalid cases:
+ // * Multiple items are claiming to be the alpha auxiliary of the current item.
+ // * Alpha auxiliary is dimg for another item.
+ avifFree(alphaItemIndices);
+ *alphaItem = NULL;
+ *isAlphaItemInInput = AVIF_FALSE;
+ return AVIF_RESULT_INVALID_IMAGE_GRID;
+ }
alphaItemIndices[alphaItemCount++] = j;
+ seenAlphaForCurrentItem = AVIF_TRUE;
}
}
+ if (!seenAlphaForCurrentItem) {
+ // No alpha auxiliary item was found for the current item. Treat this as an image without alpha.
+ avifFree(alphaItemIndices);
+ *alphaItem = NULL;
+ *isAlphaItemInInput = AVIF_FALSE;
+ return AVIF_RESULT_OK;
+ }
}
}
- if (alphaItemCount != colorItemCount) {
- // Not all the color items had an alpha auxiliary attached to it. Report this case as an image without alpha channel.
- avifFree(alphaItemIndices);
- *alphaItem = NULL;
- *isAlphaItemInInput = AVIF_FALSE;
- return AVIF_RESULT_OK;
- }
+ assert(alphaItemCount == colorItemCount);
int colorItemIndex = -1;
for (uint32_t i = 0; i < data->meta->items.count; ++i) {
@@ -3937,6 +3949,16 @@
decoder->imageDimensionLimit,
data->diag),
AVIF_RESULT_INVALID_IMAGE_GRID);
+ // Validate that there are exactly the same number of dimg items to form the grid.
+ uint32_t dimgItemCount = 0;
+ for (uint32_t i = 0; i < colorItem->meta->items.count; ++i) {
+ if (colorItem->meta->items.item[i].dimgForID == colorItem->id) {
+ ++dimgItemCount;
+ }
+ }
+ if (dimgItemCount != data->color.grid.rows * data->color.grid.columns) {
+ return AVIF_RESULT_INVALID_IMAGE_GRID;
+ }
colorCodecType = avifDecoderItemGetGridCodecType(colorItem);
if (colorCodecType == AVIF_CODEC_TYPE_UNKNOWN) {
return AVIF_RESULT_INVALID_IMAGE_GRID;