Merge pull request #707 from parkera/sr2988
diff --git a/Foundation/CharacterSet.swift b/Foundation/CharacterSet.swift
index 4babf01..35fbe72 100644
--- a/Foundation/CharacterSet.swift
+++ b/Foundation/CharacterSet.swift
@@ -13,6 +13,10 @@
private func _utfRangeToNSRange(_ inRange : Range<UnicodeScalar>) -> NSRange {
return NSMakeRange(Int(inRange.lowerBound.value), Int(inRange.upperBound.value - inRange.lowerBound.value))
}
+
+private func _utfRangeToNSRange(_ inRange : ClosedRange<UnicodeScalar>) -> NSRange {
+ return NSMakeRange(Int(inRange.lowerBound.value), Int(inRange.upperBound.value - inRange.lowerBound.value + 1))
+}
internal final class _SwiftNSCharacterSet : NSCharacterSet, _SwiftNativeFoundationType {
internal typealias ImmutableType = NSCharacterSet
@@ -129,8 +133,7 @@
///
/// It is the caller's responsibility to ensure that the values represent valid `UnicodeScalar` values, if that is what is desired.
public init(charactersIn range: ClosedRange<UnicodeScalar>) {
- let halfOpenRange = range.lowerBound..<UnicodeScalar(range.upperBound.value + 1)!
- _wrapped = _SwiftNSCharacterSet(immutableObject: NSCharacterSet(range: _utfRangeToNSRange(halfOpenRange)))
+ _wrapped = _SwiftNSCharacterSet(immutableObject: NSCharacterSet(range: _utfRangeToNSRange(range)))
}
/// Initialize with the characters in the given string.
@@ -320,8 +323,7 @@
///
/// It is the caller's responsibility to ensure that the values represent valid `UnicodeScalar` values, if that is what is desired.
public mutating func insert(charactersIn range: ClosedRange<UnicodeScalar>) {
- let halfOpenRange = range.lowerBound..<UnicodeScalar(range.upperBound.value + 1)!
- let nsRange = _utfRangeToNSRange(halfOpenRange)
+ let nsRange = _utfRangeToNSRange(range)
_applyUnmanagedMutation {
$0.addCharacters(in: nsRange)
}
@@ -337,8 +339,7 @@
/// Remove a closed range of integer values from the `CharacterSet`.
public mutating func remove(charactersIn range: ClosedRange<UnicodeScalar>) {
- let halfOpenRange = range.lowerBound..<UnicodeScalar(range.upperBound.value + 1)!
- let nsRange = _utfRangeToNSRange(halfOpenRange)
+ let nsRange = _utfRangeToNSRange(range)
_applyUnmanagedMutation {
$0.removeCharacters(in: nsRange)
}
diff --git a/TestFoundation/TestNSCharacterSet.swift b/TestFoundation/TestNSCharacterSet.swift
index 71ff177..7bd9d62 100644
--- a/TestFoundation/TestNSCharacterSet.swift
+++ b/TestFoundation/TestNSCharacterSet.swift
@@ -28,7 +28,7 @@
("testRanges", testRanges),
("testInsertAndRemove", testInsertAndRemove),
("testBasics", testBasics),
-
+ ("testClosedRanges_SR_2988", testClosedRanges_SR_2988),
("test_Predefines", test_Predefines),
("test_Range", test_Range),
("test_String", test_String),
@@ -223,6 +223,18 @@
}
}
+ func testClosedRanges_SR_2988() {
+ // "CharacterSet.insert(charactersIn: ClosedRange) crashes on a closed ClosedRange<UnicodeScalar> containing U+D7FF"
+ let problematicChar = UnicodeScalar(0xD7FF)!
+ let range = capitalA...problematicChar
+ var characters = CharacterSet(charactersIn: range) // this should not crash
+ XCTAssertTrue(characters.contains(problematicChar))
+ characters.remove(charactersIn: range) // this should not crash
+ XCTAssertTrue(!characters.contains(problematicChar))
+ characters.insert(charactersIn: range) // this should not crash
+ XCTAssertTrue(characters.contains(problematicChar))
+ }
+
func test_Bitmap() {
}