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