From ded5bc966345e063c9a125a232952d1994e29425 Mon Sep 17 00:00:00 2001 From: Todd White Date: Sun, 28 Jun 2026 15:32:33 -0400 Subject: [PATCH] CFString: fix range in CFStringGetSurrogatePairForLongCharacter The function rejected characters greater than U+10000 (returning false) and produced a surrogate pair for everything up to and including U+10000, including BMP characters. The comparison was inverted: a surrogate pair is needed for supplementary-plane characters (>= U+10000), while BMP characters (< U+10000) need none, so nearly the whole supplementary plane (U+10001..U+10FFFF) was wrongly rejected. Use "character < 0x10000". Add Tests/CFString/surrogate.m. --- Source/CFString.c | 2 +- Tests/CFString/surrogate.m | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 Tests/CFString/surrogate.m diff --git a/Source/CFString.c b/Source/CFString.c index cbd67b8c..6d012cdc 100644 --- a/Source/CFString.c +++ b/Source/CFString.c @@ -935,7 +935,7 @@ Boolean CFStringGetSurrogatePairForLongCharacter (UTF32Char character, UniChar * surrogates) { - if (character > 0x10000) + if (character < 0x10000) return false; surrogates[0] = U16_LEAD (character); diff --git a/Tests/CFString/surrogate.m b/Tests/CFString/surrogate.m new file mode 100644 index 00000000..dec2cece --- /dev/null +++ b/Tests/CFString/surrogate.m @@ -0,0 +1,24 @@ +#include "CoreFoundation/CFString.h" +#include "../CFTesting.h" + +/* CFStringGetSurrogatePairForLongCharacter for supplementary-plane and BMP characters. */ + +int main (void) +{ + UniChar pair[2]; + + PASS_CF(CFStringGetSurrogatePairForLongCharacter(0x1F600, pair) == true, + "Supplementary character U+1F600 yields a surrogate pair."); + PASS_CF(pair[0] == 0xD83D && pair[1] == 0xDE00, + "Surrogate pair for U+1F600 is D83D DE00."); + PASS_CF(CFStringGetLongCharacterForSurrogatePair(pair[0], pair[1]) == 0x1F600, + "Surrogate pair round-trips back to U+1F600."); + + PASS_CF(CFStringGetSurrogatePairForLongCharacter(0x10000, pair) == true, + "The first supplementary character U+10000 yields a pair."); + + PASS_CF(CFStringGetSurrogatePairForLongCharacter(0x0041, pair) == false, + "A BMP character (U+0041) yields no surrogate pair."); + + return 0; +}