Skip to content

Commit 07f0049

Browse files
committed
[Foundation] Override mutable copying for CharacterSet
Some mutation cases will cause the underlying copy on write cases to crash with a _SwiftNSCharacterSet doesn't respond to -mutableCopyWithZone: failure. Fixes Bugs: https://bugs.swift.org/browse/SR-1782 <rdar://problem/26608216>
1 parent 2e9f13e commit 07f0049

File tree

3 files changed

+23
-1
lines changed

3 files changed

+23
-1
lines changed

stdlib/public/SDK/Foundation/Boxing.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ extension _SwiftNativeFoundationType {
116116
}
117117

118118
func mutableCopy(with zone : NSZone) -> AnyObject {
119-
return _mapUnmanaged { ($0 as AnyObject).mutableCopy(with: zone) }
119+
return _mapUnmanaged { $0.mutableCopy() }
120120
}
121121

122122
var hashValue: Int {

stdlib/public/SDK/Foundation/CharacterSet.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,16 @@ internal final class _SwiftNSCharacterSet : _SwiftNativeNSCharacterSet, _SwiftNa
4949
deinit {
5050
releaseWrappedObject()
5151
}
52+
53+
@objc(copyWithZone:)
54+
func copy(with zone: NSZone? = nil) -> AnyObject {
55+
return _mapUnmanaged { $0.copy(with: zone) }
56+
}
57+
58+
@objc(mutableCopyWithZone:)
59+
func mutableCopy(with zone: NSZone? = nil) -> AnyObject {
60+
return _mapUnmanaged { $0.mutableCopy(with: zone) }
61+
}
5262
}
5363

5464
/**

test/1_stdlib/TestCharacterSet.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,17 @@ class TestCharacterSet : TestCharacterSetSuper {
7474
expectTrue(secondCharacterSet.contains(capitalC), "Character set must not contain our letter")
7575
expectTrue(thirdCharacterSet.contains(capitalC), "Character set must contain our letter")
7676
}
77+
78+
func testMutability_mutableCopyCrash() {
79+
let cs = CharacterSet(charactersIn: "ABC")
80+
(cs as NSCharacterSet).mutableCopy() // this should not crash
81+
}
7782

83+
func testMutability_SR_1782() {
84+
var nonAlphanumeric = CharacterSet.alphanumerics.inverted
85+
nonAlphanumeric.remove(charactersIn: " ") // this should not crash
86+
}
87+
7888
func testRanges() {
7989
// Simple range check
8090
let asciiUppercase = CharacterSet(charactersIn: UnicodeScalar(0x41)...UnicodeScalar(0x5A))
@@ -140,6 +150,8 @@ class TestCharacterSet : TestCharacterSetSuper {
140150
var CharacterSetTests = TestSuite("TestCharacterSet")
141151
CharacterSetTests.test("testBasicConstruction") { TestCharacterSet().testBasicConstruction() }
142152
CharacterSetTests.test("testMutability_copyOnWrite") { TestCharacterSet().testMutability_copyOnWrite() }
153+
CharacterSetTests.test("testMutability_mutableCopyCrash") { TestCharacterSet().testMutability_mutableCopyCrash() }
154+
CharacterSetTests.test("testMutability_SR_1782") { TestCharacterSet().testMutability_SR_1782() }
143155
CharacterSetTests.test("testRanges") { TestCharacterSet().testRanges() }
144156
CharacterSetTests.test("testInsertAndRemove") { TestCharacterSet().testInsertAndRemove() }
145157
CharacterSetTests.test("testBasics") { TestCharacterSet().testBasics() }

0 commit comments

Comments
 (0)