Chrome · Media
CVE-2026-110139
UAF in Media
Overview
High
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
ifthird_party/blink/renderer/platform/media/multi_buffer_data_source.cc |
modified | |
TEST_Fthird_party/blink/renderer/platform/media/resource_multi_buffer_data_provider_unittest.cc |
modified |
Files Changed
third_party/blink/renderer/platform/media/resource_multi_buffer_data_provider_unittest.ccthird_party/blink/renderer/platform/media/multi_buffer_data_source.ccthird_party/blink/renderer/platform/media/resource_multi_buffer_data_provider.cc
Patch
From ccb98073b6207c8c4c5e685ee7a7ca95f8e55595 Mon Sep 17 00:00:00 2001
From: Dale Curtis <dalecurtis@chromium.org>
Date: Mon, 05 Oct 2026 16:59:47 -0700
Subject: [PATCH] Fix bugs when ResourceMultiBufferDataProvider::Start fails
When MultiBuffer::AddReader calls ResourceMultiBuffer::CreateWriter,
ResourceMultiBufferDataProvider::Start is invoked synchronously. If
UrlIndex has already been destroyed, Start() previously called
url_data_->Fail() synchronously, which runs
MultiBufferDataSource::OnRedirected(nullptr) -> StopLoader() and
destroys the MultiBufferReader while MultiBuffer::AddReader and
MultiBufferReader::UpdateInternalState are still on the stack.
Post UrlData::Fail asynchronously via task_runner_->PostTask, matching
the existing asynchronous Terminate() path in Start(). Also check
stop_signal_received_ with a scoped lock in
MultiBufferDataSource::SetBitrateTask to match the other posted
MultiBufferDataSource tasks.
Fixed: 568037533
Change-Id: I47984f21cc74c54da8cae6ada583a7fac24ccb51
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8497446
Commit-Queue: Dale Curtis <dalecurtis@chromium.org>
Reviewed-by: Eugene Zemtsov <eugene@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1711814}
---
diff --git a/third_party/blink/renderer/platform/media/multi_buffer_data_source.cc b/third_party/blink/renderer/platform/media/multi_buffer_data_source.cc
index 5d2150e..a6958912 100644
--- a/third_party/blink/renderer/platform/media/multi_buffer_data_source.cc
+++ b/third_party/blink/renderer/platform/media/multi_buffer_data_source.cc
@@ -580,6 +580,12 @@
void MultiBufferDataSource::SetBitrateTask(int bitrate) {
DCHECK(render_task_runner_->BelongsToCurrentThread());
+ {
+ base::AutoLock auto_lock(lock_);
+ if (stop_signal_received_) {
+ return;
+ }
+ }
bitrate_ = bitrate;
UpdateBufferSizes();
diff --git a/third_party/blink/renderer/platform/media/resource_multi_buffer_data_provider.cc b/third_party/blink/renderer/platform/media/resource_multi_buffer_data_provider.cc
index 89ad4ff..0f85bd7 100644
--- a/third_party/blink/renderer/platform/media/resource_multi_buffer_data_provider.cc
+++ b/third_party/blink/renderer/platform/media/resource_multi_buffer_data_provider.cc
@@ -149,7 +149,8 @@
active_loader_ = url_index->fetch_context()->CreateUrlLoader(options);
active_loader_->LoadAsynchronously(request, this);
} else {
- url_data_->Fail();
+ task_runner_->PostTask(FROM_HERE,
+ blink::BindOnce(&UrlData::Fail, url_data_));
}
}
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 ad01eeb..8c857d2f 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
@@ -529,4 +529,41 @@
loader->DidReceiveData(data_str);
}
+TEST_F(ResourceMultiBufferDataProviderTest, DestructedUrlIndexStartViaReader) {
+ url_index_ = std::make_unique<UrlIndex>(
+ &fetch_context_, task_environment_.GetMainThreadTaskRunner());
+ url_ = KURL(kHttpUrl);
+ url_data_ =
+ url_index_->GetByUrl(url_, UrlData::CORS_UNSPECIFIED, UrlData::kNormal);
+
+ std::unique_ptr<MultiBufferReader> reader;
+ url_data_->OnRedirect(blink::BindOnce(
+ [](std::unique_ptr<MultiBufferReader>* reader_ptr,
+ const scoped_refptr<UrlData>& destination) {
+ EXPECT_FALSE(destination);
+ reader_ptr->reset();
+ },
+ Unretained(&reader)));
+
+ url_index_.reset();
+
+ // Creating a reader and calling SetPreload() invokes
+ // MultiBufferReader::UpdateInternalState() -> MultiBuffer::AddReader() ->
+ // ResourceMultiBuffer::CreateWriter() ->
+ // ResourceMultiBufferDataProvider::Start(). When `url_index_` is already
+ // destroyed, `Start()` must not synchronously run `url_data_->Fail()` and
+ // destroy `reader` while `AddReader()` and `UpdateInternalState()` are still
+ // on the stack.
+ reader = std::make_unique<MultiBufferReader>(
+ url_data_->multibuffer(), 0, 1024 * 1024,
+ /*is_client_audio_element=*/false, base::DoNothing(),
+ task_environment_.GetMainThreadTaskRunner());
+ reader->SetPinRange(0, 1024 * 1024);
+ reader->SetPreload(kDataSize, kDataSize);
+ ASSERT_TRUE(reader);
+
+ task_environment_.FastForwardUntilNoTasksRemain();
+ EXPECT_FALSE(reader);
+}
+
} // 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 ad01eeb..8c857d2f 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
@@ -529,4 +529,41 @@
loader->DidReceiveData(data_str);
}
+TEST_F(ResourceMultiBufferDataProviderTest, DestructedUrlIndexStartViaReader) {
+ url_index_ = std::make_unique<UrlIndex>(
+ &fetch_context_, task_environment_.GetMainThreadTaskRunner());
+ url_ = KURL(kHttpUrl);
+ url_data_ =
+ url_index_->GetByUrl(url_, UrlData::CORS_UNSPECIFIED, UrlData::kNormal);
+
+ std::unique_ptr<MultiBufferReader> reader;
+ url_data_->OnRedirect(blink::BindOnce(
+ [](std::unique_ptr<MultiBufferReader>* reader_ptr,
+ const scoped_refptr<UrlData>& destination) {
+ EXPECT_FALSE(destination);
+ reader_ptr->reset();
+ },
+ Unretained(&reader)));
+
+ url_index_.reset();
+
+ // Creating a reader and calling SetPreload() invokes
+ // MultiBufferReader::UpdateInternalState() -> MultiBuffer::AddReader() ->
+ // ResourceMultiBuffer::CreateWriter() ->
+ // ResourceMultiBufferDataProvider::Start(). When `url_index_` is already
+ // destroyed, `Start()` must not synchronously run `url_data_->Fail()` and
+ // destroy `reader` while `AddReader()` and `UpdateInternalState()` are still
+ // on the stack.
+ reader = std::make_unique<MultiBufferReader>(
+ url_data_->multibuffer(), 0, 1024 * 1024,
+ /*is_client_audio_element=*/false, base::DoNothing(),
+ task_environment_.GetMainThreadTaskRunner());
+ reader->SetPinRange(0, 1024 * 1024);
+ reader->SetPreload(kDataSize, kDataSize);
+ ASSERT_TRUE(reader);
+
+ task_environment_.FastForwardUntilNoTasksRemain();
+ EXPECT_FALSE(reader);
+}
+
} // 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.
References
On This Page