Skip to content

Commit c5b9dee

Browse files
committed
JSONSerialization: some gardening for parseUnicodeSequence(_:)
1 parent f139268 commit c5b9dee

File tree

1 file changed

+27
-10
lines changed

1 file changed

+27
-10
lines changed

Foundation/JSONSerialization.swift

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -741,23 +741,40 @@ private struct JSONReader {
741741
let isLeadSurrogate = UTF16.isLeadSurrogate(codeUnit)
742742
let isTrailSurrogate = UTF16.isTrailSurrogate(codeUnit)
743743

744-
if !isLeadSurrogate && !isTrailSurrogate {
744+
guard isLeadSurrogate || isTrailSurrogate else {
745+
// The code units that are neither lead surrogates nor trail surrogates
746+
// form valid unicode scalars.
745747
return (String(UnicodeScalar(codeUnit)!), index)
746748
}
747749

748-
guard !isTrailSurrogate else {
749-
throw NSError(domain: NSCocoaErrorDomain, code: CocoaError.propertyListReadCorrupt.rawValue, userInfo: [
750-
"NSDebugDescription" : "Unable to convert unicode escape sequence (no high-surrogate code point) to UTF8-encoded character at position \(source.distanceFromStart(input))"
751-
])
750+
// Surrogates must always come in pairs.
751+
752+
guard isLeadSurrogate else {
753+
// Trail surrogate must supercede lead surrogate
754+
throw NSError(domain: NSCocoaErrorDomain,
755+
code: CocoaError.propertyListReadCorrupt.rawValue,
756+
userInfo: [
757+
"NSDebugDescription" : """
758+
Unable to convert unicode escape sequence (no high-surrogate code point) \
759+
to UTF8-encoded character at position \(source.distanceFromStart(input))
760+
"""
761+
])
752762
}
753763

754-
guard let (trailCodeUnit, finalIndex) = try consumeASCIISequence("\\u", input: index).flatMap(parseCodeUnit), UTF16.isTrailSurrogate(trailCodeUnit) else {
755-
throw NSError(domain: NSCocoaErrorDomain, code: CocoaError.propertyListReadCorrupt.rawValue, userInfo: [
756-
"NSDebugDescription" : "Unable to convert unicode escape sequence (no low-surrogate code point) to UTF8-encoded character at position \(source.distanceFromStart(input))"
757-
])
764+
guard let (trailCodeUnit, finalIndex) = try consumeASCIISequence("\\u", input: index).flatMap(parseCodeUnit),
765+
UTF16.isTrailSurrogate(trailCodeUnit) else {
766+
767+
throw NSError(domain: NSCocoaErrorDomain,
768+
code: CocoaError.propertyListReadCorrupt.rawValue,
769+
userInfo: [
770+
"NSDebugDescription" : """
771+
Unable to convert unicode escape sequence (no low-surrogate code point) \
772+
to UTF8-encoded character at position \(source.distanceFromStart(input))
773+
"""
774+
])
758775
}
759776

760-
let highValue = (UInt32(codeUnit - 0xD800) << 10)
777+
let highValue = (UInt32(codeUnit - 0xD800) << 10)
761778
let lowValue = UInt32(trailCodeUnit - 0xDC00)
762779
return (String(UnicodeScalar(highValue + lowValue + 0x10000)!), finalIndex)
763780
}

0 commit comments

Comments
 (0)