APP-2975: Fix Fabric focus navigation use-after-free (#11583)

This commit is contained in:
Samuel Newman
2026-08-31 16:45:03 +03:00
committed by GitHub
parent 5fabad1b5d
commit 80d09a242d
3 changed files with 373 additions and 326 deletions
+32
View File
@@ -371,3 +371,35 @@ index 60160efb163d91813fa2ca7ca758b51afcf261e1..fb646fe945ffe4aa4a386f80a1e42a90
}
}
diff --git a/ReactCommon/react/renderer/uimanager/UIManager.cpp b/ReactCommon/react/renderer/uimanager/UIManager.cpp
index 3e48dabc6fffc246fd0517ef5f3f2b7721115511..ea4ba5fdf359c513a5ca4f0e94492facf4ead221 100644
--- a/ReactCommon/react/renderer/uimanager/UIManager.cpp
+++ b/ReactCommon/react/renderer/uimanager/UIManager.cpp
@@ -532,25 +532,3 @@ std::shared_ptr<const ShadowNode> UIManager::findShadowNodeByTag_DEPRECATED(
shadowTreeRegistry_.enumerate([&](const ShadowTree& shadowTree, bool& stop) {
- // Obtain a pointer to the root node. The flag-gated path uses
- // getCurrentRevision() which keeps the root alive via shared_ptr for
- // the entire traversal, fixing a use-after-free race condition.
- RootShadowNode::Shared rootShadowNodeHolder;
- const RootShadowNode* rootShadowNode = nullptr;
- if (ReactNativeFeatureFlags::fixFindShadowNodeByTagRaceCondition()) {
- rootShadowNodeHolder = shadowTree.getCurrentRevision().rootShadowNode;
- rootShadowNode = rootShadowNodeHolder.get();
- } else {
- // TODO(T257154369): Remove after flag rollout.
- // The public interface of `ShadowTree` discourages accessing a stored
- // pointer to a root node because of the possible data race.
- // To work around this, we ask for a commit and immediately cancel it
- // returning `nullptr` instead of a new shadow tree.
- // We don't want to add a way to access a stored pointer to a root
- // node because this `findShadowNodeByTag` is deprecated. It is only
- // added to make migration to the new architecture easier.
- shadowTree.tryCommit(
- [&](const RootShadowNode& oldRootShadowNode) {
- rootShadowNode = &oldRootShadowNode;
- return nullptr;
- },
- {/* default commit options */});
- }
+ auto rootShadowNodeHolder = shadowTree.getCurrentRevision().rootShadowNode;
+ const auto* rootShadowNode = rootShadowNodeHolder.get();
+15
View File
@@ -1,5 +1,20 @@
# ***This second part of this patch is load bearing, do not remove.***
## UIManager.cpp Patch - Fabric focus navigation use-after-free
Fixes Sentry issue APP-T4H9: a SIGSEGV in
`FabricUIManagerBinding::findNextFocusableElement` during focus navigation.
React Native 0.86 contains the safe implementation behind
`fixFindShadowNodeByTagRaceCondition`, but the public default is false. The
fallback captures a raw root shadow-node pointer in `tryCommit` and dereferences
it after the lock is released, allowing a concurrent commit or surface stop to
free the node first. This backports the final upstream implementation, which
holds the current revision's `shared_ptr` for the entire traversal.
**TODO: Remove after bumping React Native to a release containing
facebook/react-native#56850.**
## RefreshControl Patch - iOS 17.4 Haptic Regression
Patching `RCTRefreshControl.mm` temporarily to play an impact haptic on refresh when using iOS 17.4 or higher. Since
+326 -326
View File
File diff suppressed because it is too large Load Diff