-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
FNextPushId 'successor' crash #8790
Comments
Note: The Objective-C implementation is similar to the java implementation for android. I assume the same error may exist in other implementations of the sdk as well: |
@mortenbekditlevsen Thanks for the report. I can reproduce. @schmidt-sebastian Do you know why FNextPushId only considers alphanumeric ASCII characters when all unicode characters are valid for a key? |
Just to comment on the question above: For the auto-generated keys it's of course perfectly fine with the restriction of the 64 ASCII characters - it's only the I would like to help with a solution, but it ties closely into the concept of sorting. I can see that the key sorting implemented on iOS uses NSString literal sort, which I guess compares utf16 representations of the unicode code points. Is this in fact how the server sorts keys as well? It would be really excellent if the server side key sorting algorithm could be shared, so that a 100% robust version of |
I'm currently performing an experiment, trying to write values for keys of every unicode code point from 0x00 to 0x10FFFF. Using this to get a better feeling for allowed characters and later I'll start experiments to test how the server performs sorting. |
Using the limited ASCII space keeps the PushIDs readable, which simplifies their usage in the Console. I don't think this is a fixed requirement. @IanWyszynski Is this something you can look at? |
Please note that this is not an issue with push ids. It's an issue with assuming that all keys are push ids. |
Yeah, I assume this is due to the successor logic in startAfter. |
It looks like the issue is that we're not considering all valid utf8 characters that can be included in keys.
https://firebase.google.com/docs/database/ios/structure-data#how_data_is_structured_its_a_json_tree FWIW, the server sort function is identical to compareKey. The key index is used as a fallback for other ordering indexes to break ties, but when using |
Thanks for the clarification, Ian. I thought that it might be a little peculiar that the server also used utf16 'character' comparison like in Objective-C - which in my testing does not give the same ordering as unicode codepoint order. My tests were: I then tested with adding those strings as keys in the rtdb and performed queries limiting to first - and this indeed also gave unicode 10FFFF as the the 'first' element. Ok, so I guess that gives us some of the points we need for modifying the In rtdb, the following unicode code points are invalid to use (found by testing): So the lowest allowed value is 0x20 - space Getting the 'plus one' value needs to skip all disallowed ranges mentioned above. And plus one will be different based on whether the code point encodes as one or two utf16 characters. If it encodes as two, then I guess 0x10FFFF + 1 will be 0xE000?? Getting the minus one is similarly complicated. Even more complicated is the fact that the transport (and thus max key length) is counted in utf8 bytes, but the ordering is in utf16. For instance, I can't write a key of unicode codepoint FFFF repeated 768/2 times as FFFF takes three utf8 bytes, but only one utf16 character (corresponding to two bytes). This means that it's quite hard to calculate any string padding when calculating the predecessor. I don't know if you can use these considerations for anything, but I guess that my point is: This will be really, really hard to get correct. I'd perhaps even go so far as to say: In order to get this correct you might actually need a dedicated query type supported by the server, so that the server can do the successor/predecessor logic - or even just query from the supplied key but skip values with that key in the response. Final comment is: Help, during my testing I added keys of length 768 to the database and I can't get rid of them trough the console. |
Another small comment - apologies for the bandwidth here - I'm just really curious about how things work: In the javascript sdk we have:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Less_than
Update: in nodejs at least, the ordering also appears to be utf16 character ordering, so I assume that the documentation referred above is not entirely correct.
|
Ah, another finding: |
Update: I have a shot at an implementation. Will create a pr later this weekend or on Monday. |
I referenced this issue from firebase-js-sdk and firebase-android-sdk. Couldn't find any ditto in unity or cpp sdks. @IanWyszynski |
Fixed by #8817 |
Step 0: Are you in the right place?
file a Github issue.
with the
firebase
tag.google group.
of the above categories, reach out to
Firebase Support.
this repository, please delete this section.
[REQUIRED] Step 1: Describe your environment
Swift Package Manager
[REQUIRED] Step 2: Describe the problem
The methods
successor
andpredecessor
erronously deal with PUSH_CHARS even though it's entirely valid to use unicode keys that are not within the PUSH_CHARS set.Around line 98 in FNextPushId.m we have:
The issue is that if
source
is for instance a space, then sourceIndex will be max int and the sourcePlusOne calculation causes a crash (since max int + 1 gives min int in objective-c, and min int is out of bounds).Thread 1: "-[__NSCFConstantString characterAtIndex:]: Range or index out of bounds"
Steps to reproduce:
Easily reproducible with the one-liner below:
Relevant Code:
Suggestion for a solution
I guess that 'successor' and 'predecessor' ought to deal with unicode character points instead of the PUSH_CHARs used to auto-generate keys.
In the same line, I believe that appending MIN_PUSH_CHAR to keys that are shorter than MAX_KEY_LENGTH is not entirely correct, since it wont give the string value that immediately succeeds the input key when using the key index comparison - - which for non-numeric keys ends up using the following comparison:
So 'successor' should return the key that immediately follows the input as defined by the
+compareKey:toKey
method in FUtilities.The crash itself is a bit contrived, but here is an actual issue:
If you have the following data in RTDB:
{ "a": "hello",
"a!": "world"
}
and do a queryStarting(afterValue: "a"), then I suspect that the query will start at "a-" meaning that it will miss the "a!" entry...
The text was updated successfully, but these errors were encountered: