-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RCNConfigRealtime crash "CFString cannot be created from a negative number of bytes" #14094
Comments
I couldn't figure out how to label this issue, so I've labeled it for a human to triage. Hang tight. |
Hey there, can you please give an example or snippet of what you mean? |
Hey @pyrtsa. We need more information to resolve this issue but there hasn't been an update in 5 weekdays. I'm marking the issue as stale and if there are no new updates in the next 5 days I will close it automatically. If you have more information that will help us get to the bottom of this, just add a comment! |
I'm sorry @MichaelVerdon, I thought I shared all the pertinent information in the original message already. But allow me to better illustrate the problem with a code snippet. When strongSelf->_dataTask = [strongSelf->_session dataTaskWithRequest:strongSelf->_request];
[strongSelf->_dataTask resume]; as the The way Issue 1. The first problematic part is the construction of a UTF-8 decoded NSString *strData = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; In case the HTTP body contains any multibyte UTF-8 code unit sequences, it is possible that the incoming Issue 2. Next, the delegate method makes an apparent attempt at error handling by trying to find the character sequence if ([strData containsString:kServerForbiddenStatusCode]) {
// ...
[self propagateErrors:error];
return;
} This logic is problematic for the same reasons as before: the Issue 3. This is what really caught us in form of a crash report, however infrequent. After the above error handling, the delegate method continues to search for what seems like the NSRange endRange = [strData rangeOfString:@"}"];
NSRange beginRange = [strData rangeOfString:@"{"];
if (beginRange.location != NSNotFound && endRange.location != NSNotFound) {
// ...
NSRange msgRange =
NSMakeRange(beginRange.location, endRange.location - beginRange.location + 1);
strData = [strData substringWithRange:msgRange]; // 💥 crash due to invalid `msgRange`
data = [strData dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *response = [NSJSONSerialization JSONObjectWithData:data
options:NSJSONReadingMutableContainers
error:&dataError];
[self evaluateStreamResponse:response error:dataError];
} The problem in this logic is that, again, it is not guaranteed by There are two problematic parts in issue 3:
Now, the simplest way to fix these issues is to add buffering to the delegate method implementation: instead of looking for patters within It might be clearest to do this by not converting the bytes to Footnotes
|
+1 |
+1 same issue |
Thanks alot for the additional information @pyrtsa. I have been unable to reproduce the issue but obtained different issues but I will keep trying, can I see a snippet of how you implemented the ConfigUpdateListener or maybe even a MCVE? |
@MichaelVerdon Based on the description above, is it possible to write a unit test that returns the NSURLSession in different chunks to reproduce the problem with the assumption of matching braces in the code? |
I will give this a shot @paulb777 thanks for the suggestion. |
@MichaelVerdon One possible solution maybe be to make the URLRequest with |
Just a ping that we keep seeing these crashes in production. @MichaelVerdon Any luck fixing it? |
Description
Expected to happen
Calling
RemoteConfig.addOnConfigUpdateListener(remoteConfigUpdateCompletion:)
should set up a listener for realtime config updates without crashing the app, regardless of network conditions.Actual outcome
💥 We see intermittent crashes in Crashlytics where
-[RCNConfigRealtime URLSession:dataTask:didReceiveData:]
attempted to construct a substring from an opening brace{
through to a closing one}
, expecting that they unconditionally occur in that order in the piece ofNSData
returned byNSURLSession
, but they didn't.The precise crash is an uncaught Obj-C exception
CFString cannot be created from a negative number of bytes
thrown from the call to-[NSString substringWithRange:]
atRCNConfigRealtime.m:583
. The crash would be avoided by adding the necessary requirement thatbeginRange.location < endRange.location
before continuing the logic.But please note that
-[NSURLSessionDataDelegate URLSession:dataTask:didReceiveData:]
provides no guarantees as to where theNSData
input is being cut: it could be an arbitrary slice of the full response body, and the SDK should probably include some buffering to pick up JSON objects divided in two or more such slices.Also the previous check for
if ([strData containsString:kServerForbiddenStatusCode]) { ... }
is probably not working in all cases when the matched patternkServerForbiddenStatusCode
of the bytes"code": 403
could be similarly split.Reproducing the issue
Precise steps to reproduce unknown, as the reproduction of this crash requires a particular kind of response from the Remote Config server and a particular buffering of the response body by
NSURLSession
.Firebase SDK Version
11.4.0
Xcode Version
16.0
Installation Method
Swift Package Manager
Firebase Product(s)
Analytics, Crashlytics, Remote Config
Targeted Platforms
iOS
Relevant Log Output
If using Swift Package Manager, the project's Package.resolved
Expand
Package.resolved
snippetIf using CocoaPods, the project's Podfile.lock
No response
The text was updated successfully, but these errors were encountered: