Uh oh!
There was an error while loading. Please reload this page.
Fix incorrect early exit in SortKey.Compare and seal type - #31779
Conversation
GrabYourPitchforks
commented
Feb 5, 2020
There's another interesting behavior here. Since under the invariant mode sort keys are a raw projection of chars to bytes, there are endianness issues to consider. For example, under the invariant mode: /* on a little-endian machine */// "ĕ" = "\u0115"string.Compare("e","ĕ",StringComparison.Ordinal);// returns < 0CompareInfo.Compare("e","ĕ");// returns < 0SortKey.Compare(CompareInfo.GetSortKey("e"),CompareInfo.GetSortKey("ĕ"));// returns > 0/* on a big-endian machine */string.Compare("e","ĕ",StringComparison.Ordinal);// returns < 0CompareInfo.Compare("e","ĕ");// returns < 0SortKey.Compare(CompareInfo.GetSortKey("e"),CompareInfo.GetSortKey("ĕ"));// returns < 0Open question: Is this discrepancy allowable? I don't know if there's a valid scenario in which somebody uses |
tarekgh
commented
Feb 5, 2020
I wouldn't care much if someone using InvarantMode and Sort Keys. sort keys are really useful for scenarios that use real cultures and cares about linguistic behavior. The invariant mode is not for such scenarios at all. |
GrabYourPitchforks
commented
Feb 5, 2020
Would it make sense for us to block the |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
GrabYourPitchforks
commented
Feb 5, 2020
Another possible solution (if we do care about if(GlobalizationMode.Invariant){returnkey1._bytes.AsChars().SequenceCompareTo(key2._bytes.AsChars());}else{returnkey1._bytes.SequenceCompareTo(key2._bytes);} |
jkotas
commented
Feb 5, 2020
Would it make sense to swap the bytes when creating the sort key in InvariantMode to fix this?
|
GrabYourPitchforks
commented
Feb 5, 2020
Sounds like that's two votes for "don't bother with endianness concerns"? :) |
jkotas
commented
Feb 5, 2020
That, or if you would like to write the few lines of code to swap endianess in the invariantmode sort key generation - that's fine too. |
pentp
commented
Feb 5, 2020
Making |
GrabYourPitchforks
commented
Feb 5, 2020
Latest iteration:
|
tarekgh
commented
Feb 5, 2020
GetHashCode doesn't allow CompareOptions.StringSort I think. |
It has to. This same logic applies to |
GrabYourPitchforks
commented
Feb 6, 2020
Latest iteration:
|
The method
SortKey.Comparecontains an early incorrect exit which can cause it to return 0 if all of the below conditions hold:sortKey1norsortKey2represents the empty string, andsortKey1is a prefix ofsortKey2(or vice versa).In a nutshell, this means that under the invariant globalization mode, the expression
compareInfo.GetSortKey("he").Equals(compareInfo.GetSortKey("hello!"))incorrectly returns true.There may also be some inputs under the non-invariant mode which trigger this incorrect output, but I didn't attempt this since it would be highly dependent on how the active version of NLS or ICU produces sort keys. It's far easier to trigger this bug under the invariant mode.
This PR addresses that issue in
SortKey.Compare. Additionally, there are some performance optimizations made toSortKey.EqualsandSortKey.GetHashCode. This also builds on #31761 by sealing theSortKeytype and devirtualizing the methods.