From 3e2e8ec7579fa72af09f016753c167952dffaf43 Mon Sep 17 00:00:00 2001 From: zhongwuzw Date: Mon, 27 Jan 2025 12:15:37 -0800 Subject: [PATCH] Bridge: Fixes HostTarget use after free when deallocated bridge (#48847) Summary: Fixes https://github.com/facebook/react-native/issues/48805 . ## Changelog: [IOS] [FIXED] - Bridge: Fixes HostTarget use after free when deallocated bridge Pull Request resolved: https://github.com/facebook/react-native/pull/48847 Test Plan: Test code: ``` __weak RCTAlertManager *weakModule; autoreleasepool { RCTAlertManager *module = [RCTAlertManager new]; RCTBridge *bridge = [[RCTBridge alloc] initWithBundleURL:[self sourceURLForBridge:nil] moduleProvider:^{ return @[ module ]; } launchOptions:nil]; weakModule = module; (void)bridge; } ``` Reviewed By: realsoelynn Differential Revision: D68495576 Pulled By: huntie fbshipit-source-id: c3086a429f24488ac286ff22d039b8f049ccbffd --- packages/react-native/React/Base/RCTBridge.mm | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/packages/react-native/React/Base/RCTBridge.mm b/packages/react-native/React/Base/RCTBridge.mm index 8a44d2ae748..32000177fcb 100644 --- a/packages/react-native/React/Base/RCTBridge.mm +++ b/packages/react-native/React/Base/RCTBridge.mm @@ -313,6 +313,7 @@ RCT_NOT_IMPLEMENTED(-(instancetype)init) - (void)dealloc { + RCTBridge *batchedBridge = self.batchedBridge; /** * This runs only on the main thread, but crashes the subclass * RCTAssertMainQueue(); @@ -332,7 +333,17 @@ RCT_NOT_IMPLEMENTED(-(instancetype)init) RCTExecuteOnMainQueue(^{ facebook::react::jsinspector_modern::getInspectorInstance().removePage(*inspectorPageId); inspectorPageId.reset(); - inspectorTarget.reset(); + // NOTE: RCTBridgeHostTargetDelegate holds a weak reference to RCTBridge. + // Conditionally call `inspectorTarget.reset()` to avoid a crash. + if (batchedBridge) { + [batchedBridge + dispatchBlock:^{ + inspectorTarget.reset(); + } + queue:RCTJSThread]; + } else { + inspectorTarget.reset(); + } }); } }