Skip to content

Commit cc03e41

Browse files
Fix potential race conditions when executing commitHooks
Summary: Recently we saw use-after-free race condition where the ImageFetcher object was being destroyed while still registered as a UIManagerCommitHook. The crash occurred in std::vector::size() at line 635 when accessing corrupted memory. The root cause could be improper lifecycle management between ImageFetcher destruction and commit hook execution. The fix here modifies UIManager::shadowTreeWillCommit() to create a stable snapshot by copying the commitHooks_ vector while holding the lock. Changelog: [Internal] Differential Revision: D82846245
1 parent 2590cd7 commit cc03e41

File tree

1 file changed

+6
-2
lines changed
  • packages/react-native/ReactCommon/react/renderer/uimanager

1 file changed

+6
-2
lines changed

packages/react-native/ReactCommon/react/renderer/uimanager/UIManager.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -615,10 +615,14 @@ RootShadowNode::Unshared UIManager::shadowTreeWillCommit(
615615
const ShadowTree::CommitOptions& commitOptions) const {
616616
TraceSection s("UIManager::shadowTreeWillCommit");
617617

618-
std::shared_lock lock(commitHookMutex_);
618+
std::vector<UIManagerCommitHook*> commitHooks;
619+
{
620+
std::shared_lock lock(commitHookMutex_);
621+
std::swap(commitHooks, commitHooks_);
622+
}
619623

620624
auto resultRootShadowNode = newRootShadowNode;
621-
for (auto* commitHook : commitHooks_) {
625+
for (auto* commitHook : commitHooks) {
622626
resultRootShadowNode = commitHook->shadowTreeWillCommit(
623627
shadowTree, oldRootShadowNode, resultRootShadowNode, commitOptions);
624628
}

0 commit comments

Comments
 (0)