Compare commits

..

4 Commits

Author SHA1 Message Date
Keeley Hammond
69fe268d4d chore: [25-x-y] cherry-pick 2 changes from Release-3-M119 (#40671)
* b2d36b1c3bfc from libavif
* 922fca786b61a from libavif
2023-12-01 09:53:14 -08:00
Keeley Hammond
55738ddac3 chore: cherry-pick 3 changes from Release-3-M119 (#40645)
chore: [25-x-y] cherry-pick 3 changes from Release-3-M119

* 3f45b1af5e41 from chromium
* e13061c50998 from chromium
* 6169a1fabae1 from skia
2023-11-30 13:39:38 -08:00
Pedro Pontes
7916733f5f chore: cherry-pick 1 changes from Release-2-M119 (#40538)
* chore: [25-x-y] cherry-pick 1 changes from Release-2-M119

* 9384cddc7705 from chromium

* chore: update patches

---------

Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
2023-11-15 20:11:35 -08:00
Pedro Pontes
6c37483f2c chore: cherry-pick 1 changes from Release-1-M119 (#40519)
* chore: [25-x-y] cherry-pick 1 changes from Release-1-M119

* 3df423a5b8de from chromium

* chore: update patches

---------

Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
2023-11-14 12:54:36 -08:00
11 changed files with 609 additions and 0 deletions

View File

@@ -149,3 +149,7 @@ avoid_allocating_recordid_objects_in_elementtiming_and_lcp.patch
cherry-pick-80106e31c7ea.patch
gpu_use_load_program_shader_shm_count_on_drdc_thread.patch
crash_gpu_process_and_clear_shader_cache_when_skia_reports.patch
cherry-pick-3df423a5b8de.patch
cherry-pick-9384cddc7705.patch
cherry-pick-3f45b1af5e41.patch
cherry-pick-e13061c50998.patch

View File

@@ -0,0 +1,57 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Hongchan Choi <hongchan@chromium.org>
Date: Fri, 3 Nov 2023 16:39:55 +0000
Subject: Check context status before recreating platform destination
Changing the channel count in the RealtimeAudioDestinationHandler will
trigger the recreation of the platform destination. This in turn can
activate the audio rendering thread.
This CL adds a check to prevent this from happening after the handler
is garbage collected.
(cherry picked from commit 4997f2ba263ff7e1dbc7987dd3665459be14dffe)
Bug: 1497859
Test: Locally confirmed with ASAN
Change-Id: I5d2649f3fd3639779ae40b0ca4ef2fe305653421
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4995928
Commit-Queue: Hongchan Choi <hongchan@chromium.org>
Reviewed-by: Michael Wilson <mjwilson@chromium.org>
Cr-Original-Commit-Position: refs/heads/main@{#1217868}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5004961
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
Cr-Commit-Position: refs/branch-heads/5993@{#1520}
Cr-Branched-From: 511350718e646be62331ae9d7213d10ec320d514-refs/heads/main@{#1192594}
diff --git a/third_party/blink/renderer/modules/webaudio/realtime_audio_destination_handler.cc b/third_party/blink/renderer/modules/webaudio/realtime_audio_destination_handler.cc
index 6781dcff462db872d1f5a786aef0c89f43189100..2e4757d155800700b7c6a8b7cbf2e02250cfce65 100644
--- a/third_party/blink/renderer/modules/webaudio/realtime_audio_destination_handler.cc
+++ b/third_party/blink/renderer/modules/webaudio/realtime_audio_destination_handler.cc
@@ -118,12 +118,21 @@ void RealtimeAudioDestinationHandler::SetChannelCount(
uint32_t old_channel_count = ChannelCount();
AudioHandler::SetChannelCount(channel_count, exception_state);
- // Stop, re-create and start the destination to apply the new channel count.
- if (ChannelCount() != old_channel_count && !exception_state.HadException()) {
- StopPlatformDestination();
- CreatePlatformDestination();
- StartPlatformDestination();
+ // After the context is closed, changing channel count will be ignored
+ // because it will trigger the recreation of the platform destination. This
+ // in turn can activate the audio rendering thread.
+ AudioContext* context = static_cast<AudioContext*>(Context());
+ CHECK(context);
+ if (context->ContextState() == AudioContext::kClosed ||
+ ChannelCount() == old_channel_count ||
+ exception_state.HadException()) {
+ return;
}
+
+ // Stop, re-create and start the destination to apply the new channel count.
+ StopPlatformDestination();
+ CreatePlatformDestination();
+ StartPlatformDestination();
}
void RealtimeAudioDestinationHandler::StartRendering() {

View File

@@ -0,0 +1,48 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alvin Ji <alvinji@chromium.org>
Date: Mon, 13 Nov 2023 20:24:24 +0000
Subject: Check context status before creating new platform destination
RealtimeAudioDestinationHandler::SetSinkDescriptor creates new
destination platofrm without validating context status. This can
reactivate the audio rendering thread when AudioContext is already in
closed state.
(cherry picked from commit 0f9bb9a1083865d4e51059e588f27f729ab32753)
Bug: 1500856
Change-Id: If1fd531324b56fcdc38d315fd84d4cec577a14bc
Test: Locally confirmed with ASAN
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5021160
Reviewed-by: Alvin Ji <alvinji@chromium.org>
Commit-Queue: Alvin Ji <alvinji@chromium.org>
Reviewed-by: Hongchan Choi <hongchan@chromium.org>
Cr-Original-Commit-Position: refs/heads/main@{#1223168}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5026373
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
Commit-Queue: Hongchan Choi <hongchan@chromium.org>
Cr-Commit-Position: refs/branch-heads/6099@{#607}
Cr-Branched-From: e6ee4500f7d6549a9ac1354f8d056da49ef406be-refs/heads/main@{#1217362}
diff --git a/third_party/blink/renderer/modules/webaudio/realtime_audio_destination_handler.cc b/third_party/blink/renderer/modules/webaudio/realtime_audio_destination_handler.cc
index 2e4757d155800700b7c6a8b7cbf2e02250cfce65..c27eb3ac07f22a4cd1ae2f86da896d255a761292 100644
--- a/third_party/blink/renderer/modules/webaudio/realtime_audio_destination_handler.cc
+++ b/third_party/blink/renderer/modules/webaudio/realtime_audio_destination_handler.cc
@@ -405,6 +405,17 @@ void RealtimeAudioDestinationHandler::SetSinkDescriptor(
GetCallbackBufferSize()));
DCHECK(IsMainThread());
+ // After the context is closed, `SetSinkDescriptor` request will be ignored
+ // because it will trigger the recreation of the platform destination. This in
+ // turn can activate the audio rendering thread.
+ AudioContext* context = static_cast<AudioContext*>(Context());
+ CHECK(context);
+ if (context->ContextState() == AudioContext::kClosed) {
+ std::move(callback).Run(
+ media::OutputDeviceStatus::OUTPUT_DEVICE_STATUS_ERROR_INTERNAL);
+ return;
+ }
+
// Create a pending AudioDestination to replace the current one.
scoped_refptr<AudioDestination> pending_platform_destination =
AudioDestination::Create(

View File

@@ -0,0 +1,42 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Nidhi Jaju <nidhijaju@chromium.org>
Date: Wed, 8 Nov 2023 04:19:31 +0000
Subject: Make URLSearchParams persistent to avoid UaF
The URLSearchParams::Create() function returns an on-heap object, but it
can be garbage collected, so making it a persistent variable in
DidFetchDataLoadedString() mitigates the issue.
(cherry picked from commit 8b1bd7726a1394e2fe287f6a882822d8ee9d4e96)
Bug: 1497997
Change-Id: I4ae0f93fccc561cd8a088d3fa0bf2968bf298acf
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4996929
Reviewed-by: Adam Rice <ricea@chromium.org>
Commit-Queue: Nidhi Jaju <nidhijaju@chromium.org>
Cr-Original-Commit-Position: refs/heads/main@{#1218682}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5007484
Commit-Queue: Adam Rice <ricea@chromium.org>
Auto-Submit: Nidhi Jaju <nidhijaju@chromium.org>
Cr-Commit-Position: refs/branch-heads/5993@{#1546}
Cr-Branched-From: 511350718e646be62331ae9d7213d10ec320d514-refs/heads/main@{#1192594}
diff --git a/third_party/blink/renderer/core/fetch/body.cc b/third_party/blink/renderer/core/fetch/body.cc
index 1b0ce3c8dceac103c24d513c3c5f4bc3aabcf6b7..5ffef06442a508c4dbf8133d5d20491c159bbfde 100644
--- a/third_party/blink/renderer/core/fetch/body.cc
+++ b/third_party/blink/renderer/core/fetch/body.cc
@@ -135,8 +135,13 @@ class BodyFormDataConsumer final : public BodyConsumerBase {
void DidFetchDataLoadedString(const String& string) override {
auto* formData = MakeGarbageCollected<FormData>();
- for (const auto& pair : URLSearchParams::Create(string)->Params())
+ // URLSearchParams::Create() returns an on-heap object, but it can be
+ // garbage collected, so making it a persistent variable on the stack
+ // mitigates use-after-free scenarios. See crbug.com/1497997.
+ Persistent<URLSearchParams> search_params = URLSearchParams::Create(string);
+ for (const auto& pair : search_params->Params()) {
formData->append(pair.first, pair.second);
+ }
DidFetchDataLoadedFormData(formData);
}
};

View File

@@ -0,0 +1,116 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ken Rockot <rockot@google.com>
Date: Thu, 16 Nov 2023 23:44:43 +0000
Subject: Reland: Fix IPC Channel pipe teardown
This is a reland with the new test temporarily disabled on Android
until it can run without disrupting other tests.
(cherry picked from commit cd4c1f165c16c6d8161b5372ef7f61c715e01a42)
Fixed: 1494461
Change-Id: If1d83c2dce62020f78dd50abc460973759002a1a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5015115
Commit-Queue: Ken Rockot <rockot@google.com>
Reviewed-by: Robert Sesek <rsesek@chromium.org>
Cr-Original-Commit-Position: refs/heads/main@{#1221953}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5037764
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
Auto-Submit: Ken Rockot <rockot@google.com>
Commit-Queue: Daniel Cheng <dcheng@chromium.org>
Cr-Commit-Position: refs/branch-heads/5993@{#1618}
Cr-Branched-From: 511350718e646be62331ae9d7213d10ec320d514-refs/heads/main@{#1192594}
diff --git a/ipc/ipc_mojo_bootstrap.cc b/ipc/ipc_mojo_bootstrap.cc
index 2ab03807d102d8f4e2a22119210d5cb669338c3b..5fa17e2ff108909a8987665dd21bc490118f1147 100644
--- a/ipc/ipc_mojo_bootstrap.cc
+++ b/ipc/ipc_mojo_bootstrap.cc
@@ -787,13 +787,12 @@ class ChannelAssociatedGroupController
// handle.
DCHECK(!endpoint->client());
DCHECK(endpoint->peer_closed());
- MarkClosedAndMaybeRemove(endpoint);
+ MarkClosed(endpoint);
} else {
- MarkPeerClosedAndMaybeRemove(endpoint);
+ MarkPeerClosed(endpoint);
}
}
-
- DCHECK(endpoints_.empty());
+ endpoints_.clear();
GetMemoryDumpProvider().RemoveController(this);
}
@@ -838,15 +837,19 @@ class ChannelAssociatedGroupController
base::AutoLock locker(lock_);
encountered_error_ = true;
+ std::vector<uint32_t> endpoints_to_remove;
std::vector<scoped_refptr<Endpoint>> endpoints_to_notify;
for (auto iter = endpoints_.begin(); iter != endpoints_.end();) {
Endpoint* endpoint = iter->second.get();
++iter;
- if (endpoint->client())
+ if (endpoint->client()) {
endpoints_to_notify.push_back(endpoint);
+ }
- MarkPeerClosedAndMaybeRemove(endpoint);
+ if (MarkPeerClosed(endpoint)) {
+ endpoints_to_remove.push_back(endpoint->id());
+ }
}
for (auto& endpoint : endpoints_to_notify) {
@@ -855,6 +858,10 @@ class ChannelAssociatedGroupController
if (endpoint->client())
NotifyEndpointOfError(endpoint.get(), false /* force_async */);
}
+
+ for (uint32_t id : endpoints_to_remove) {
+ endpoints_.erase(id);
+ }
}
void NotifyEndpointOfError(Endpoint* endpoint, bool force_async) {
@@ -893,19 +900,33 @@ class ChannelAssociatedGroupController
NotifyEndpointOfError(endpoint, false /* force_async */);
}
- void MarkClosedAndMaybeRemove(Endpoint* endpoint) {
+ // Marks `endpoint` as closed and returns true if and only if its peer was
+ // also already closed.
+ bool MarkClosed(Endpoint* endpoint) {
lock_.AssertAcquired();
endpoint->set_closed();
- if (endpoint->closed() && endpoint->peer_closed())
- endpoints_.erase(endpoint->id());
+ return endpoint->peer_closed();
}
- void MarkPeerClosedAndMaybeRemove(Endpoint* endpoint) {
+ // Marks `endpoint` as having a closed peer and returns true if and only if
+ // `endpoint` itself was also already closed.
+ bool MarkPeerClosed(Endpoint* endpoint) {
lock_.AssertAcquired();
endpoint->set_peer_closed();
endpoint->SignalSyncMessageEvent();
- if (endpoint->closed() && endpoint->peer_closed())
+ return endpoint->closed();
+ }
+
+ void MarkClosedAndMaybeRemove(Endpoint* endpoint) {
+ if (MarkClosed(endpoint)) {
endpoints_.erase(endpoint->id());
+ }
+ }
+
+ void MarkPeerClosedAndMaybeRemove(Endpoint* endpoint) {
+ if (MarkPeerClosed(endpoint)) {
+ endpoints_.erase(endpoint->id());
+ }
}
Endpoint* FindOrInsertEndpoint(mojo::InterfaceId id, bool* inserted) {

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));

View File

@@ -1 +1,2 @@
enforce_an_upper_limit_of_715_million_path_verbs_in_skpath.patch
avoid_combining_extremely_large_meshes.patch

View File

@@ -0,0 +1,31 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: John Stiles <johnstiles@google.com>
Date: Fri, 24 Nov 2023 09:40:11 -0500
Subject: Avoid combining extremely large meshes.
Bug: chromium:1505053
Change-Id: I42f2ff872bbf054686ec7af0cc85ff63055fcfbf
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/782936
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
diff --git a/src/gpu/ganesh/ops/DrawMeshOp.cpp b/src/gpu/ganesh/ops/DrawMeshOp.cpp
index b2db7d873a2b2709b474c7a736b3142bc47e1889..fa35a6d72a6600c87ee22ece089c4c631de78ede 100644
--- a/src/gpu/ganesh/ops/DrawMeshOp.cpp
+++ b/src/gpu/ganesh/ops/DrawMeshOp.cpp
@@ -1000,10 +1000,13 @@ GrOp::CombineResult MeshOp::onCombineIfPossible(GrOp* t, SkArenaAlloc*, const Gr
return CombineResult::kCannotCombine;
}
+ if (fVertexCount > INT32_MAX - that->fVertexCount) {
+ return CombineResult::kCannotCombine;
+ }
if (SkToBool(fIndexCount) != SkToBool(that->fIndexCount)) {
return CombineResult::kCannotCombine;
}
- if (SkToBool(fIndexCount) && fVertexCount + that->fVertexCount > SkToInt(UINT16_MAX)) {
+ if (SkToBool(fIndexCount) && fVertexCount > UINT16_MAX - that->fVertexCount) {
return CombineResult::kCannotCombine;
}