Better ID choice for new item. This is a manual cherry-pick of commit 59f1c9a. This fixes the case where the maximum ID is UINT32_MAX. BUG=oss-fuzz:65657
diff --git a/src/read.c b/src/read.c index c879024..9a60869 100644 --- a/src/read.c +++ b/src/read.c
@@ -3665,12 +3665,8 @@ uint32_t * alphaItemIndices = avifAlloc(colorItemCount * sizeof(uint32_t)); AVIF_CHECKERR(alphaItemIndices, AVIF_RESULT_OUT_OF_MEMORY); uint32_t alphaItemCount = 0; - uint32_t maxItemID = 0; for (uint32_t i = 0; i < colorItem->meta->items.count; ++i) { - avifDecoderItem * item = colorItem->meta->items.item[i]; - if (item->id > maxItemID) { - maxItemID = item->id; - } + const avifDecoderItem * const item = colorItem->meta->items.item[i]; if (item->dimgForID == colorItem->id) { avifBool seenAlphaForCurrentItem = AVIF_FALSE; for (uint32_t j = 0; j < colorItem->meta->items.count; ++j) { @@ -3699,11 +3695,31 @@ } } assert(alphaItemCount == colorItemCount); - *alphaItem = avifMetaFindItem(colorItem->meta, maxItemID + 1); - if (*alphaItem == NULL) { + // Find an unused ID. + avifResult result; + if (colorItem->meta->items.count >= UINT32_MAX - 1) { + // In the improbable case where all IDs are used. + result = AVIF_RESULT_DECODE_ALPHA_FAILED; + } else { + uint32_t newItemID = 0; + avifBool isUsed; + do { + ++newItemID; + isUsed = AVIF_FALSE; + for (uint32_t i = 0; i < colorItem->meta->items.count; ++i) { + if (colorItem->meta->items.item[i]->id == newItemID) { + isUsed = AVIF_TRUE; + break; + } + } + } while (isUsed && newItemID != 0); + *alphaItem = avifMetaFindItem(colorItem->meta, newItemID); // Create new empty item. + result = (*alphaItem == NULL) ? AVIF_RESULT_OUT_OF_MEMORY : AVIF_RESULT_OK; + } + if (result != AVIF_RESULT_OK) { avifFree(alphaItemIndices); *isAlphaItemInInput = AVIF_FALSE; - return AVIF_RESULT_OUT_OF_MEMORY; + return result; } memcpy((*alphaItem)->type, "grid", 4); (*alphaItem)->width = colorItem->width;