← All issues

[AppKit Gestures] Reentrancy UAF in PositionInformationManager pending-handler loop

94c5f97

Source/WebKit/UIProcess/mac/PositionInformationManager.cpp

- for (auto& slot : m_pendingHandlers) {
+ // This is intentionally not a range-based for-loop as doing so can result in a reentrancy UAF due to stale iterator pointers.
+ for (size_t index = 0; index < m_pendingHandlers.size(); ++index) {
+ auto& slot = m_pendingHandlers[index];
if (!slot)
continue;
+
if (!matches(slot->request))
continue;

PositionInformationManager runs in the UIProcess and queues callbacks (m_pendingHandlers) that await position-information updates from AppKit gesture handling. Its design explicitly supports reentrancy: a callback invoked during invokeAndRemovePendingHandlers can call back into doAfterUpdate() and enqueue new handlers via constructAndAppend(), which may grow and reallocate the Vector's backing store. A range-based for loop captures begin()/end() once at loop start, so once a reentrant callback reallocates the buffer mid-iteration, those cached pointers reference freed memory and any further dereference of slot is a use-after-free.

The fix replaces the range-based loop with an index-based one that re-reads size() and re-indexes m_pendingHandlers[index] each iteration, correctly picking up the reallocated buffer.

  Range-based (buggy):                  Index-based (fixed):
  for (auto& slot : m_pendingHandlers)  for (index = 0; index < size(); ++index)
    caches begin/end once                 slot = m_pendingHandlers[index]
    callback() reenters                   callback() reenters
      constructAndAppend() reallocates      may reallocate
    cached ptrs -> freed memory           next iter re-indexes live buffer
    slot-> ...  UAF                       (safe)

A reentrancy-driven UAF in a UIProcess callback queue reachable from AppKit gesture handling, where the buggy pattern is a reusable template likely present in other WebKit callback queues.

The fixed shape — reentrant synchronous callbacks mutating a Vector that is being iterated — recurs across WebKit's UIProcess pending-request/callback queues. Narrow: grep PositionInformationManager and sibling *Manager classes for range-based for loops over m_pending* vectors whose body invokes a callback capable of reentering and calling append/constructAndAppend/insert, especially in UIProcess classes handling gesture, touch, or position-info IPC replies. Wider: any range-based iteration over a Vector/HashMap whose loop body dispatches into client or JS-reachable code that can mutate the same container — the container need not be a callback queue. Widest: the general iterator-invalidation-under-reentrancy class in any container-plus-callback design. The review tell is a range-based for over a member container adjacent to a comment or method name that admits reentrancy (doAfterUpdate, "may reenter") — the presence of both in one function is the signal to switch to index-based iteration or snapshot the container first.