Chrome · SVG
CVE-2026-110148
UAF in SVG
Overview
Critical
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
cache_identifier_third_party/blink/renderer/core/svg/svg_document_resource_tracker.cc |
modified | |
forthird_party/blink/renderer/core/svg/svg_document_resource_tracker.cc |
modified |
Files Changed
third_party/blink/renderer/core/svg/svg_document_resource_tracker.hthird_party/blink/renderer/core/svg/svg_resource_document_content.ccthird_party/blink/renderer/core/svg/svg_document_resource_tracker.cc
Patch
From 1a21dce7357cb20f5b79779f6fd3b3e1c6ec234a Mon Sep 17 00:00:00 2001
From: Fredrik Söderquist <fs@opera.com>
Date: Thu, 08 Oct 2026 07:15:33 -0700
Subject: [PATCH] Fix iteration in SVGDocumentResourceTracker::DisposeUnobserved()
The tracked_resources_ set could potentially be mutated by the disposal
of a SVGResourceDocumentContent, so make a copy before iterating.
Since SVGDocumentResourceTracker::Dispose() could potentially suffer
from a similar issue, adjust it too.
Fixed: 570050934
Change-Id: Iec67ad5ced154acad56a7bb30a2c4edb6fbfb507
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8525706
Auto-Submit: Fredrik Söderquist <fs@opera.com>
Commit-Queue: Philip Rogers <pdr@chromium.org>
Reviewed-by: Philip Rogers <pdr@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1714468}
---
diff --git a/third_party/blink/renderer/core/svg/svg_document_resource_tracker.cc b/third_party/blink/renderer/core/svg/svg_document_resource_tracker.cc
index 26eecce..819d97d 100644
--- a/third_party/blink/renderer/core/svg/svg_document_resource_tracker.cc
+++ b/third_party/blink/renderer/core/svg/svg_document_resource_tracker.cc
@@ -36,11 +36,14 @@
cache_identifier_(cache_identifier) {}
void SVGDocumentResourceTracker::Dispose() {
- for (const auto& resource : tracked_resources_) {
+ is_disposed_ = true;
+
+ HeapHashSet<Member<SVGDocumentResource>> to_dispose;
+ to_dispose.swap(tracked_resources_);
+ for (const auto& resource : to_dispose) {
resource->GetContent()->Dispose();
}
MemoryCache::Get()->EvictResourcesForCacheIdentifier(cache_identifier_);
- tracked_resources_.clear();
}
void SVGDocumentResourceTracker::DisposeUnobserved() {
@@ -49,12 +52,17 @@
HeapVector<Member<SVGDocumentResource>> to_remove;
for (const auto& resource : tracked_resources_) {
if (!resource->GetContent()->HasObservers()) {
- resource->GetContent()->Dispose();
to_remove.push_back(resource);
MemoryCache::Get()->Remove(resource);
}
}
tracked_resources_.RemoveAll(to_remove);
+
+ // Perform disposal from `to_remove` since Dispose() may cause additional
+ // resources to be added (i.e mutate `tracked_resources_`).
+ for (const auto& resource : to_remove) {
+ resource->GetContent()->Dispose();
+ }
}
void SVGDocumentResourceTracker::ProcessCustomWeakness(
@@ -86,6 +94,7 @@
}
void SVGDocumentResourceTracker::AddResource(SVGDocumentResource* resource) {
+ CHECK(!is_disposed_);
tracked_resources_.insert(resource);
}
diff --git a/third_party/blink/renderer/core/svg/svg_document_resource_tracker.h b/third_party/blink/renderer/core/svg/svg_document_resource_tracker.h
index e8d346a..61ccf15 100644
--- a/third_party/blink/renderer/core/svg/svg_document_resource_tracker.h
+++ b/third_party/blink/renderer/core/svg/svg_document_resource_tracker.h
@@ -43,6 +43,7 @@
const String& cache_identifier);
void Dispose();
+ bool IsDisposed() const { return is_disposed_; }
void Trace(Visitor*) const;
@@ -59,6 +60,7 @@
HeapHashSet<Member<SVGDocumentResource>> tracked_resources_;
scoped_refptr<base::SingleThreadTaskRunner> dispose_task_runner_;
bool dispose_task_pending_ = false;
+ bool is_disposed_ = false;
String cache_identifier_;
};
diff --git a/third_party/blink/renderer/core/svg/svg_resource_document_content.cc b/third_party/blink/renderer/core/svg/svg_resource_document_content.cc
index 8ad1a6a..05662b2 100644
--- a/third_party/blink/renderer/core/svg/svg_resource_document_content.cc
+++ b/third_party/blink/renderer/core/svg/svg_resource_document_content.cc
@@ -290,6 +290,9 @@
Page* page = document.GetPage();
auto& cache = page->GetSVGDocumentResourceTracker();
+ if (cache.IsDisposed()) {
+ return nullptr;
+ }
SVGDocumentResource* resource = SVGDocumentResource::Fetch(
params, document.Fetcher(), page->GetAgentGroupScheduler());
Loading diff…
Original Bug Report
The reporter's bug is still restricted on the tracker. Chrome de-restricts security bugs ~30–90 days after the fix ships; a later run will backfill it here.
References
On This Page