Branch: refs/heads/main
Home: https://github.com/WebKit/WebKit
Commit: 16b1bde3c1918236d0eefee504bcf4180566087f
https://github.com/WebKit/WebKit/commit/16b1bde3c1918236d0eefee504bcf4180566087f
Author: Zak Ridouh <[email protected]>
Date: 2026-06-30 (Tue, 30 Jun 2026)
Changed paths:
A
LayoutTests/storage/indexeddb/index-cursor-reverse-delete-next-higher-key-private-expected.txt
A
LayoutTests/storage/indexeddb/index-cursor-reverse-delete-next-higher-key-private.html
M Source/WebCore/Modules/indexeddb/server/MemoryIndexCursor.cpp
Log Message:
-----------
[CoreIPC] [NP] Heap UAF in WebCore::IDBServer::MemoryIndexCursor reverse
iterator when a Prev/Prevunique cursor's next-higher index entry is deleted
<https://bugs.webkit.org/show_bug.cgi?id=313818>
<rdar://174678764>
Reviewed by Sihui Liu.
MemoryIndexCursor caches an IndexValueStore::Iterator across IPC messages.
For Prev/Prevunique cursors this wraps std::set<IDBKeyData>::reverse_iterator
objects (one for the outer IndexValueStore::m_orderedKeys set, one nested in
IndexValueEntry::Iterator for the inner per-index-key set). A
std::reverse_iterator stores a forward base() iterator pointing one element
past the logical position; for libc++ std::set that is a raw __tree_node*.
MemoryIndexCursor::indexValueChanged() only invalidates m_currentIterator
when the changed (key, primaryKey) equals the cursor's current logical
position. Deleting the next-higher index key (Variant A, outer set) or the
next-higher primary key under a shared index key (Variant B, inner set)
therefore frees exactly the __tree_node base() references while the guard
early-returns. The next IterateCursor IPC executes ++m_reverseIterator =>
--base() => __tree_prev_iter(freed_node), a heap-use-after-free in
com.apple.WebKit.Networking reachable from a compromised WebContent process
via NetworkStorageManager IPC with WCP-controlled
IDBDatabaseIdentifier.m_isTransient = true forcing MemoryIDBBackingStore.
Fix by gating the equality early-return on info().isDirectionForward(). For
reverse cursors we now invalidate m_currentIterator on any index mutation;
iterate() already re-seeks via reverseFind(m_currentKey, m_currentPrimaryKey)
when the iterator is invalid. Both removeEntriesWithValueKey() erase paths
(outer m_orderedKeys.erase() and inner IndexValueEntry::removeKey()) reach
indexValueChanged() through MemoryIndex::notifyCursorsOfValueChange(), so
both variants are closed.
*
LayoutTests/storage/indexeddb/index-cursor-reverse-delete-next-higher-key-private-expected.txt:
Added.
*
LayoutTests/storage/indexeddb/index-cursor-reverse-delete-next-higher-key-private.html:
Added.
* Source/WebCore/Modules/indexeddb/server/MemoryIndexCursor.cpp:
(WebCore::IDBServer::MemoryIndexCursor::indexValueChanged):
Originally-landed-as: 305413.842@safari-7624-branch (d14d12e915f3).
rdar://180436983
Canonical link: https://commits.webkit.org/316129@main
To unsubscribe from these emails, change your notification settings at
https://github.com/WebKit/WebKit/settings/notifications