chore: [25-x-y] cherry-pick 2 changes from Release-3-M119 (#40671)

* b2d36b1c3bfc from libavif
* 922fca786b61a from libavif
This commit is contained in:
Keeley Hammond
2023-12-01 09:53:14 -08:00
committed by GitHub
parent 55738ddac3
commit 13d2ab0dff
4 changed files with 310 additions and 0 deletions

View File

@@ -25,6 +25,8 @@
"src/electron/patches/skia": "src/third_party/skia",
"src/electron/patches/libavif": "src/third_party/libavif/src",
"src/electron/patches/libwebp": "src/third_party/libwebp/src",
"src/electron/patches/libvpx": "src/third_party/libvpx/source/libvpx",

2
patches/libavif/.patches Normal file
View File

@@ -0,0 +1,2 @@
remove_potential_out_of_bound_access_to_alphaitemindices.patch
do_not_store_potentially_invalid_pointers.patch

View File

@@ -0,0 +1,79 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: VerteDinde <vertedinde@electronjs.org>
Date: Thu, 30 Nov 2023 20:39:28 -0800
Subject: Do not store potentially invalid pointers
Manual cherry-pick of PR #1757 into the chromium-m118 branch.
diff --git a/src/read.c b/src/read.c
index 756af390f451eb7e7422248ddc0b3e88e1640a94..5f2c527911f0896f78b26c7313db215671c217dd 100644
--- a/src/read.c
+++ b/src/read.c
@@ -752,6 +752,8 @@ static void avifMetaDestroy(avifMeta * meta)
avifFree(meta);
}
+// CAUTION: This function could potentially resize the meta->items array thereby invalidating all existing pointers that are being
+// stored locally. So if this function is being called, exercise caution in the caller to not use invalid pointers.
static avifDecoderItem * avifMetaFindItem(avifMeta * meta, uint32_t itemID)
{
if (itemID == 0) {
@@ -1259,6 +1261,19 @@ static avifResult avifDecoderItemRead(avifDecoderItem * item,
return AVIF_RESULT_OK;
}
+// Returns the avifCodecType of the first tile of the gridItem.
+static avifCodecType avifDecoderItemGetGridCodecType(const avifDecoderItem * gridItem)
+{
+ for (uint32_t i = 0; i < gridItem->meta->items.count; ++i) {
+ avifDecoderItem * item = &gridItem->meta->items.item[i];
+ const avifCodecType tileCodecType = avifGetCodecType(item->type);
+ if ((item->dimgForID == gridItem->id) && (tileCodecType != AVIF_CODEC_TYPE_UNKNOWN)) {
+ return tileCodecType;
+ }
+ }
+ return AVIF_CODEC_TYPE_UNKNOWN;
+}
+
static avifBool avifDecoderGenerateImageGridTiles(avifDecoder * decoder, avifImageGrid * grid, avifDecoderItem * gridItem, avifBool alpha)
{
unsigned int tilesRequested = grid->rows * grid->columns;
@@ -3843,16 +3858,28 @@ avifResult avifDecoderReset(avifDecoder * decoder)
avifBool isAlphaItemInInput;
avifDecoderItem * alphaItem;
AVIF_CHECKRES(avifDecoderDataFindAlphaItem(data, &colorItem, &alphaItem, &isAlphaItemInInput));
- if (alphaItem && !memcmp(alphaItem->type, "grid", 4)) {
- avifROData readData;
- AVIF_CHECKRES(avifDecoderItemRead(alphaItem, decoder->io, &readData, 0, 0, data->diag));
- AVIF_CHECKERR(avifParseImageGridBox(&data->alpha.grid,
- readData.data,
- readData.size,
- decoder->imageSizeLimit,
- decoder->imageDimensionLimit,
- data->diag),
- AVIF_RESULT_INVALID_IMAGE_GRID);
+ avifCodecType alphaCodecType = AVIF_CODEC_TYPE_UNKNOWN;
+ if (alphaItem) {
+ if (!memcmp(alphaItem->type, "grid", 4)) {
+ if (isAlphaItemInInput) {
+ avifROData readData;
+ AVIF_CHECKRES(avifDecoderItemRead(alphaItem, decoder->io, &readData, 0, 0, data->diag));
+ AVIF_CHECKERR(avifParseImageGridBox(&data->alpha.grid,
+ readData.data,
+ readData.size,
+ decoder->imageSizeLimit,
+ decoder->imageDimensionLimit,
+ data->diag),
+ AVIF_RESULT_INVALID_IMAGE_GRID);
+ }
+ alphaCodecType = avifDecoderItemGetGridCodecType(alphaItem);
+ if (alphaCodecType == AVIF_CODEC_TYPE_UNKNOWN) {
+ return AVIF_RESULT_INVALID_IMAGE_GRID;
+ }
+ } else {
+ alphaCodecType = avifGetCodecType(alphaItem->type);
+ assert(alphaCodecType != AVIF_CODEC_TYPE_UNKNOWN);
+ }
}
// Find Exif and/or XMP metadata, if any

View File

@@ -0,0 +1,227 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: VerteDinde <vertedinde@electronjs.org>
Date: Thu, 30 Nov 2023 20:33:02 -0800
Subject: Remove potential out of bound access to alphaItemIndices
Manual cherry-pick of PR #1756 into the chromium-m118 branch.
diff --git a/include/avif/internal.h b/include/avif/internal.h
index 0d3651fb4fb26baafc756b0033141e50495d9127..8562dce8bb93bee9f151b0321d41692f0a62ea9c 100644
--- a/include/avif/internal.h
+++ b/include/avif/internal.h
@@ -397,6 +397,19 @@ __attribute__((__format__(__printf__, 2, 3)))
#endif
void avifDiagnosticsPrintf(avifDiagnostics * diag, const char * format, ...);
+// ---------------------------------------------------------------------------
+// avifCodecType (underlying video format)
+
+// Alliance for Open Media video formats that can be used in the AVIF image format.
+typedef enum avifCodecType
+{
+ AVIF_CODEC_TYPE_UNKNOWN,
+ AVIF_CODEC_TYPE_AV1,
+#if defined(AVIF_CODEC_AVM)
+ AVIF_CODEC_TYPE_AV2, // Experimental.
+#endif
+} avifCodecType;
+
// ---------------------------------------------------------------------------
// avifStream
//
diff --git a/src/read.c b/src/read.c
index 36a9058abfda94b623609e5ffff5fac2e48d8701..756af390f451eb7e7422248ddc0b3e88e1640a94 100644
--- a/src/read.c
+++ b/src/read.c
@@ -37,6 +37,23 @@ static const size_t xmpContentTypeSize = sizeof(xmpContentType);
// can't be more than 4 unique tuples right now.
#define MAX_IPMA_VERSION_AND_FLAGS_SEEN 4
+// ---------------------------------------------------------------------------
+// AVIF codec type (AV1 or AV2)
+
+static avifCodecType avifGetCodecType(const uint8_t * fourcc)
+{
+ if (!memcmp(fourcc, "av01", 4)) {
+ return AVIF_CODEC_TYPE_AV1;
+ }
+#if defined(AVIF_CODEC_AVM)
+ if (!memcmp(fourcc, "av02", 4)) {
+ return AVIF_CODEC_TYPE_AV2;
+ }
+#endif
+ return AVIF_CODEC_TYPE_UNKNOWN;
+}
+
+
// ---------------------------------------------------------------------------
// Box data structures
@@ -1267,7 +1284,7 @@ static avifBool avifDecoderGenerateImageGridTiles(avifDecoder * decoder, avifIma
if (tilesRequested != tilesAvailable) {
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,
tilesRequested,
@@ -3465,6 +3482,135 @@ static avifDecoderItem * avifDecoderDataFindItem(avifDecoderData * data, avifBoo
return NULL;
}
+// Returns AVIF_TRUE if item is an alpha auxiliary item of the parent color
+// item.
+static avifBool avifDecoderItemIsAlphaAux(avifDecoderItem * item, uint32_t colorItemId)
+{
+ if (item->auxForID != colorItemId)
+ return AVIF_FALSE;
+ const avifProperty * auxCProp = avifPropertyArrayFind(&item->properties, "auxC");
+ return auxCProp && isAlphaURN(auxCProp->u.auxC.auxType);
+}
+
+// Returns AVIF_TRUE if the item should be skipped. Items should be skipped for one of the following reasons:
+// * Size is 0.
+// * Has an essential property that isn't supported by libavif.
+// * Item is not a single image or a grid.
+// * Item is a thumbnail.
+static avifBool avifDecoderItemShouldBeSkipped(const avifDecoderItem * item)
+{
+ return !item->size || item->hasUnsupportedEssentialProperty ||
+ (avifGetCodecType(item->type) == AVIF_CODEC_TYPE_UNKNOWN && memcmp(item->type, "grid", 4)) || item->thumbnailForID != 0;
+}
+
+// Finds the alpha item whose parent item is *colorItemPtr and sets it in the alphaItem output parameter. Returns AVIF_RESULT_OK
+// on success. Note that *alphaItem can be NULL even if the return value is AVIF_RESULT_OK. If the *colorItemPtr is a grid and the
+// alpha item is represented as a set of auxl items to each color tile, then a fake item will be created and *isAlphaItemInInput
+// will be set to AVIF_FALSE. In this case, the alpha item merely exists to hold the locations of the alpha tile items. The data
+// of this item need not be read and the pixi property cannot be validated. Otherwise, *isAlphaItemInInput will be set to
+// AVIF_TRUE when *alphaItem is not NULL. If the data->meta->items array is resized, then the value in *colorItemPtr could become
+// invalid. This function also resets *colorItemPtr to the right value if an alpha item was found and added to the data->meta->items
+// array.
+static avifResult avifDecoderDataFindAlphaItem(avifDecoderData * data,
+ avifDecoderItem ** colorItemPtr,
+ avifDecoderItem ** alphaItem,
+ avifBool * isAlphaItemInInput)
+{
+ const avifDecoderItem * colorItem = *colorItemPtr;
+ for (uint32_t itemIndex = 0; itemIndex < data->meta->items.count; ++itemIndex) {
+ avifDecoderItem * item = &data->meta->items.item[itemIndex];
+ if (avifDecoderItemShouldBeSkipped(item)) {
+ continue;
+ }
+ if (avifDecoderItemIsAlphaAux(item, colorItem->id)) {
+ *alphaItem = item;
+ *isAlphaItemInInput = AVIF_TRUE;
+ return AVIF_RESULT_OK;
+ }
+ }
+ if (memcmp(colorItem->type, "grid", 4)) {
+ *alphaItem = NULL;
+ *isAlphaItemInInput = AVIF_FALSE;
+ return AVIF_RESULT_OK;
+ }
+ // If color item is a grid, check if there is an alpha channel which is represented as an auxl item to each color tile
+ // item.
+ uint32_t colorItemCount = data->color.grid.rows * data->color.grid.columns;
+ if (colorItemCount == 0) {
+ *alphaItem = NULL;
+ *isAlphaItemInInput = AVIF_FALSE;
+ return AVIF_RESULT_OK;
+ }
+ 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;
+ }
+ 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;
+ }
+ }
+ }
+ assert(alphaItemCount == colorItemCount);
+
+ int colorItemIndex = -1;
+ for (uint32_t i = 0; i < data->meta->items.count; ++i) {
+ if (colorItem->id == data->meta->items.item[i].id) {
+ colorItemIndex = i;
+ break;
+ }
+ }
+ assert(colorItemIndex >= 0);
+
+ *alphaItem = avifMetaFindItem(colorItem->meta, maxItemID + 1);
+ if (*alphaItem == NULL) {
+ avifFree(alphaItemIndices);
+ *isAlphaItemInInput = AVIF_FALSE;
+ return AVIF_RESULT_OUT_OF_MEMORY;
+ }
+ // avifMetaFindItem() could invalidate all existing item pointers. So reset the colorItem pointers.
+ *colorItemPtr = &data->meta->items.item[colorItemIndex];
+ colorItem = *colorItemPtr;
+
+ memcpy((*alphaItem)->type, "grid", 4);
+ (*alphaItem)->width = colorItem->width;
+ (*alphaItem)->height = colorItem->height;
+ for (uint32_t i = 0; i < alphaItemCount; ++i) {
+ avifDecoderItem * item = &colorItem->meta->items.item[alphaItemIndices[i]];
+ item->dimgForID = (*alphaItem)->id;
+ }
+ avifFree(alphaItemIndices);
+ *isAlphaItemInInput = AVIF_FALSE;
+ data->alpha.grid = data->color.grid;
+ return AVIF_RESULT_OK;
+}
+
static avifResult avifDecoderGenerateImageTiles(avifDecoder * decoder, avifTileInfo * info, avifDecoderItem * item, avifBool alpha)
{
const uint32_t previousTileCount = decoder->data->tiles.count;
@@ -3682,9 +3828,21 @@ avifResult avifDecoderReset(avifDecoder * decoder)
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;
+ }
}
- avifDecoderItem * alphaItem = avifDecoderDataFindItem(data, /*alpha=*/AVIF_TRUE, /*parentItemID=*/colorItem->id);
+ avifBool isAlphaItemInInput;
+ avifDecoderItem * alphaItem;
+ AVIF_CHECKRES(avifDecoderDataFindAlphaItem(data, &colorItem, &alphaItem, &isAlphaItemInInput));
if (alphaItem && !memcmp(alphaItem->type, "grid", 4)) {
avifROData readData;
AVIF_CHECKRES(avifDecoderItemRead(alphaItem, decoder->io, &readData, 0, 0, data->diag));