High chrome UAF 🔧 Commit mapped

Overview

High
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactUse after free in Media
DescriptionUse after free in Media
ComponentMedia
Bug ClassUAF
Tracker566347711
Fix commit79d7e8374c00 (chromium/src) +26/-1
CISA KEVNot listed
CreditedXinyang Ge (Anthropic), assisted by Claude
Disclosed2026-10-06

Changed Functions

FunctionChangeNotes
if
third_party/blink/renderer/platform/media/multi_buffer.cc
modified

Files Changed

  • third_party/blink/renderer/platform/media/resource_multi_buffer_data_provider_unittest.cc
  • third_party/blink/renderer/platform/media/multi_buffer.cc
From 79d7e8374c0056a4e55583ab5b836371cacfb12f Mon Sep 17 00:00:00 2001
From: Dale Curtis <dalecurtis@chromium.org>
Date: Wed, 30 Sep 2026 17:44:21 -0700
Subject: [PATCH] Fix bugs in MultiBuffer::OnDataProviderEvent when Prune empties UrlData

In MultiBuffer::OnDataProviderEvent(), move Prune() after writer_index_
is updated and SuggestProviderState() is evaluated. Previously, Prune()
could empty data_ and call UrlData::OnEmpty(), dropping UrlIndex's last
reference to UrlData and destroying MultiBuffer before
writer_index_.find(pos) was executed.

Fixed: 566347711

Change-Id: I9389d473e0bc3c4523d6132ece32a74633c8cb76
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8489395
Commit-Queue: Eugene Zemtsov <eugene@chromium.org>
Auto-Submit: Dale Curtis <dalecurtis@chromium.org>
Reviewed-by: Eugene Zemtsov <eugene@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1708523}
---
diff --git a/third_party/blink/renderer/platform/media/multi_buffer.cc b/third_party/blink/renderer/platform/media/multi_buffer.cc
index c5cf4b5..1846dce 100644
--- a/third_party/blink/renderer/platform/media/multi_buffer.cc
+++ b/third_party/blink/renderer/platform/media/multi_buffer.cc
@@ -427,7 +427,6 @@
         present_.find(start_pos).interval();
     NotifyAvailableRange(expanded_range, expanded_range);
     lru_->IncrementDataSize(blocks_added);
-    Prune(static_cast<size_t>(blocks_added) * kMaxFreesPerAdd + 1);
   } else {
     // Make sure to give progress reports even when there
     // aren't any new blocks yet.
@@ -454,6 +453,13 @@
         break;
     }
   }
+
+  if (pos > start_pos) {
+    // Prune must run after writer_index_ is updated above, since ReleaseBlocks
+    // may invoke OnEmpty() and drop the UrlIndex reference to the owning
+    // UrlData.
+    Prune(static_cast<size_t>(blocks_added) * kMaxFreesPerAdd + 1);
+  }
 }
 
 void MultiBuffer::MergeFrom(MultiBuffer* other) {
diff --git a/third_party/blink/renderer/platform/media/resource_multi_buffer_data_provider_unittest.cc b/third_party/blink/renderer/platform/media/resource_multi_buffer_data_provider_unittest.cc
index f27bc3a..67b08fdd 100644
--- a/third_party/blink/renderer/platform/media/resource_multi_buffer_data_provider_unittest.cc
+++ b/third_party/blink/renderer/platform/media/resource_multi_buffer_data_provider_unittest.cc
@@ -490,4 +490,23 @@
   StopWhenLoad();
 }
 
+TEST_F(ResourceMultiBufferDataProviderTest,
+       PruneEmptiesUrlDataDuringDidReceiveData) {
+  Initialize(kHttpUrl, 0);
+  url_data_->Use();
+  Start();
+  PartialResponse(0, 100, 1024);
+
+  // Drop the test's reference so `url_index_` holds the sole reference to
+  // `UrlData`. Since there is no active `MultiBufferReader`, `GlobalLRU` max
+  // size is 0 and blocks are unpinned. Receiving a full block will cause
+  // `OnDataProviderEvent` to prune all blocks and invoke `UrlData::OnEmpty()`,
+  // which must not destroy `UrlData` / `MultiBuffer` while still on the stack.
+  ResourceMultiBufferDataProvider* loader = loader_.ExtractAsDangling();
+  url_data_ = nullptr;
+
+  std::string data_str(1, 'a');
+  loader->DidReceiveData(data_str);
+}
+
 }  // namespace blink
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/third_party/blink/renderer/platform/media/resource_multi_buffer_data_provider_unittest.cc b/third_party/blink/renderer/platform/media/resource_multi_buffer_data_provider_unittest.cc
index f27bc3a..67b08fdd 100644
--- a/third_party/blink/renderer/platform/media/resource_multi_buffer_data_provider_unittest.cc
+++ b/third_party/blink/renderer/platform/media/resource_multi_buffer_data_provider_unittest.cc
@@ -490,4 +490,23 @@
   StopWhenLoad();
 }
 
+TEST_F(ResourceMultiBufferDataProviderTest,
+       PruneEmptiesUrlDataDuringDidReceiveData) {
+  Initialize(kHttpUrl, 0);
+  url_data_->Use();
+  Start();
+  PartialResponse(0, 100, 1024);
+
+  // Drop the test's reference so `url_index_` holds the sole reference to
+  // `UrlData`. Since there is no active `MultiBufferReader`, `GlobalLRU` max
+  // size is 0 and blocks are unpinned. Receiving a full block will cause
+  // `OnDataProviderEvent` to prune all blocks and invoke `UrlData::OnEmpty()`,
+  // which must not destroy `UrlData` / `MultiBuffer` while still on the stack.
+  ResourceMultiBufferDataProvider* loader = loader_.ExtractAsDangling();
+  url_data_ = nullptr;
+
+  std::string data_str(1, 'a');
+  loader->DidReceiveData(data_str);
+}
+
 }  // namespace blink
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.