Skip to content

Commit ec2a34f

Browse files
committed
[Stdlib] Make the SwiftNativeNSXXXBase classes gracefully handle being decoded with NSKeyedUnarchiver.
These would never be decoded in normal use, but it's possible to construct an archive that will attempt to decode them. Without this override, that throws an exception or worse. rdar://problem/48429185
1 parent 5e36f55 commit ec2a34f

File tree

2 files changed

+59
-0
lines changed

2 files changed

+59
-0
lines changed

stdlib/public/stubs/SwiftNativeNSXXXBase.mm.gyb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ SWIFT_RUNTIME_STDLIB_API
6262

6363
@implementation __SwiftNativeNS${Class}Base
6464

65+
- (id)initWithCoder: (NSCoder *)coder {
66+
return [self init];
67+
}
6568
- (id)retain {
6669
auto SELF = reinterpret_cast<HeapObject *>(self);
6770
swift_retain(SELF);
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// RUN: %target-run-simple-swift
2+
// REQUIRES: executable_test
3+
4+
// REQUIRES: objc_interop
5+
6+
import Foundation
7+
import StdlibUnittest
8+
9+
let testSuite = TestSuite("SwiftNativeNSXXXCoding")
10+
11+
// Ensure that T gracefully handles being decoded. It doesn't have to
12+
// work, just not crash.
13+
private func test<T: NSObject & NSCoding>(type: T.Type) {
14+
if #available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *) {
15+
let swiftClassName = "__SwiftNative\(type)Base"
16+
print(swiftClassName)
17+
let archiver = NSKeyedArchiver(requiringSecureCoding: true)
18+
archiver.setClassName(swiftClassName, for: T.self)
19+
archiver.encode(T(), forKey: "key")
20+
archiver.finishEncoding()
21+
let d = archiver.encodedData
22+
23+
let unarchiver = try! NSKeyedUnarchiver(forReadingFrom: d)
24+
_ = unarchiver.decodeObject(of: T.self, forKey: "key")
25+
}
26+
}
27+
28+
29+
// Test all the classes listed in SwiftNativeNSXXXBase.mm.gyb except for
30+
// NSEnumerator (which doesn't conform to NSCoding).
31+
32+
testSuite.test("NSArray") {
33+
test(type: NSArray.self)
34+
}
35+
36+
testSuite.test("NSDictionary") {
37+
test(type: NSDictionary.self)
38+
}
39+
40+
testSuite.test("NSSet") {
41+
test(type: NSSet.self)
42+
}
43+
44+
testSuite.test("NSString") {
45+
test(type: NSString.self)
46+
}
47+
48+
testSuite.test("NSData") {
49+
test(type: NSData.self)
50+
}
51+
52+
testSuite.test("NSIndexSet") {
53+
test(type: NSIndexSet.self)
54+
}
55+
56+
runAllTests()

0 commit comments

Comments
 (0)