Skip to content

Commit 671705d

Browse files
1337musmeta-codesync[bot]
authored andcommitted
Fix intermittent CoreServices XPC crash in RCTBlobManager blob name derivation (#58172)
Summary: ### The crash `-[NSURLResponse suggestedFilename]` derives a filename from the response's MIME type. Under the hood, that call makes a CoreServices/UTType **XPC round-trip**, and that XPC call crashes intermittently when invoked off the main thread (`NSXPCEncoder` / `objc_msgSend` frames). ### Why it fires on every request `RCTBlobManager.handleNetworkingResponse:` calls `suggestedFilename` on the networking / TurboModule queue for every response it converts to a blob. Since `whatwg-fetch` reads **every** response body as a blob, the fragile call runs for every `fetch()` an app makes. Even a very low per-call crash rate becomes a steady stream of native crashes at scale. We hit this in production at Phantom (millions of iOS users). Crash stacks consistently point into the UTType XPC machinery under `suggestedFilename`, always on the networking queue. ### The fix Derive the blob's `name` from the URL's last path component instead. No XPC involved. ```objc // before @"name" : RCTNullIfNil([response suggestedFilename]), // after @"name" : RCTNullIfNil(response.URL.lastPathComponent), ``` **Tradeoff:** filenames from a `Content-Disposition` header (or a MIME-derived extension) are no longer used. A response blob's `name` is rarely consumed; it only feeds `Blob` / `File.name` for response bodies. If you'd prefer to keep `Content-Disposition` support, parsing that header directly here would also avoid the XPC call. Happy to iterate. Related: the same XPC fragility on the **upload** path was reported in #35096. ## Changelog: [IOS] [FIXED] - Fix intermittent native crash (CoreServices/UTType XPC) in RCTBlobManager when deriving blob names for network responses Pull Request resolved: #58172 Test Plan: - This exact change has run in production at Phantom since May 2026 (applied as a patch). The crash class disappeared and stayed gone. - Fetch/blob flows (file and image downloads, uploads, WebSocket blobs) are covered by our device-farm e2e suites and are green with this change. - `name` is still populated from the URL path, and is empty when the URL has no path component, which matches one of `suggestedFilename`'s own fallback tiers. Reviewed By: javache Differential Revision: D117876442 Pulled By: christophpurrer fbshipit-source-id: 4505e4409e39595fd9fd3372dc93fc0fc39b5ae2
1 parent ea291d7 commit 671705d

1 file changed

Lines changed: 6 additions & 1 deletion

File tree

packages/react-native/Libraries/Blob/RCTBlobManager.mm

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,11 +297,16 @@ - (id)handleNetworkingResponse:(NSURLResponse *)response data:(NSData *)data
297297
// An empty body will have nil for data, in this case we need to return
298298
// an empty blob as per the XMLHttpRequest spec.
299299
data = data ?: [NSData new];
300+
// -[NSURLResponse suggestedFilename] resolves the filename through a
301+
// CoreServices/UTType XPC lookup that can crash intermittently
302+
// (NSXPCEncoder) when called off the main thread. Since whatwg-fetch reads
303+
// every response as a blob, that lookup used to run for every network
304+
// response. Derive the name from the URL instead; no XPC round-trip.
300305
return @{
301306
@"blobId" : [self store:data],
302307
@"offset" : @0,
303308
@"size" : @(data.length),
304-
@"name" : RCTNullIfNil([response suggestedFilename]),
309+
@"name" : RCTNullIfNil(response.URL.lastPathComponent),
305310
@"type" : RCTNullIfNil([response MIMEType]),
306311
};
307312
}

0 commit comments

Comments
 (0)