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 <[email protected]> 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 <[email protected]> Reviewed-by: Eugene Zemtsov <[email protected]> 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