Branch: refs/heads/main
  Home:   https://github.com/WebKit/WebKit
  Commit: 2ee2ba7e7a8f142872315fb5b5d8b510c9569f26
      
https://github.com/WebKit/WebKit/commit/2ee2ba7e7a8f142872315fb5b5d8b510c9569f26
  Author: Tyler Wilcock <[email protected]>
  Date:   2025-11-19 (Wed, 19 Nov 2025)

  Changed paths:
    A 
LayoutTests/accessibility/crash-deleting-dynamically-updated-text-input-expected.txt
    A 
LayoutTests/accessibility/crash-deleting-dynamically-updated-text-input.html
    M LayoutTests/platform/glib/TestExpectations
    M Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperBase.mm

  Log Message:
  -----------
  AX: Crash can happen when the parent of a dynamically updated object is 
deleted
https://bugs.webkit.org/show_bug.cgi?id=298463
rdar://158287589

Reviewed by Joshua Hoffman.

A crash can happen in this sequence:

  1. An object that is the child of another object in the isolated tree (it is 
contained within its m_children) receives
     a dynamic update from the DOM that will cause a full node update to run 
for it, creating a whole new AXIsolatedObject.
     An example of this is when the value changes for an input element. We do 
this for certain types of updates where
     the update affects so many properties, we don't bother trying to update 
them all individually.

  2. AXIsolatedTree::applyPendingChanges runs, and we replace the old object in 
AXIsolatedTree::m_readerThreadNodeMap
     with the new one. However, the "old" / stale object is still 
strong-referenced in the parent's m_children.

  3. The parent is deleted, and said deletion is queued up for processing the 
next time AXIsolatedTree::applyPendingChanges runs.

  4. An AT requests an attribute from the fully-updated, stale object. This 
calls -[WebAccessibilityObjectWrapperBase updateObjectBackingStore].
     We create a RefPtr to the fully-updated, stale object near the top of the 
method. Then we run AXIsolatedTree::applyPendingChanges.
     This deletes the parent object, and the parent deletes it's m_children 
too. This means the last strong reference
     to the stale object is in updateObjectBackingStore (remember the stale 
object was removed from m_readerThreadNodeMap in step 2).

  5. As the last step in updateObjectBackingStore, the wrapper returns 
self.axBackingObject, which is critically a raw pointer
     to the stale object.

  6. The RefPtr destructor runs as the last step in the method, deleting the 
stale object. But we've already returned
     a pointer to it, and any subsequent use is an instant use-after-free.

This commit scopes the RefPtr in updateObjectBackingStore, preventing this 
issue from happening. A subsequent PR will
change full-node-updates to not re-create brand new AXIsolatedObject instances, 
just update all the properties of the
existing instance. This will prevent bugs stemming from the parent iterating 
over its children and using stale objects
while doing so.

* 
LayoutTests/accessibility/crash-deleting-dynamically-updated-text-input-expected.txt:
 Added.
* LayoutTests/accessibility/crash-deleting-dynamically-updated-text-input.html: 
Added.
* Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperBase.mm:
(-[WebAccessibilityObjectWrapperBase updateObjectBackingStore]):

Originally-landed-as: 297297.409@safari-7622-branch (0a56f1d9d362). 
rdar://164214646
Canonical link: https://commits.webkit.org/303297@main



To unsubscribe from these emails, change your notification settings at 
https://github.com/WebKit/WebKit/settings/notifications

Reply via email to