mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
The last two tests in the NotPresent test check for fixes that went into 5.3. Testing these against earlier runtimes will fail. Add availability checks so we only test when the fix is present. While we're here, switch the symbolic references test to use indirect references. Direct references are very likely to pass the test even without the fix, as the reference is likely to point to readable memory. Indirect references make this much more likely to crash by then reading and dereferencing a pointer from the memory the relative pointer points to. rdar://159034772
281 lines
10 KiB
Swift
281 lines
10 KiB
Swift
// RUN: %empty-directory(%t)
|
|
|
|
// RUN: %target-build-swift-dylib(%t/%target-library-name(resilient_struct)) -enable-library-evolution %S/../../Inputs/resilient_struct.swift -emit-module -emit-module-path %t/resilient_struct.swiftmodule -module-name resilient_struct
|
|
// RUN: %target-codesign %t/%target-library-name(resilient_struct)
|
|
|
|
// RUN: %target-build-swift-dylib(%t/%target-library-name(resilient_class)) -enable-library-evolution %S/../../Inputs/resilient_class.swift -emit-module -emit-module-path %t/resilient_class.swiftmodule -module-name resilient_class -I%t -L%t -lresilient_struct
|
|
// RUN: %target-codesign %t/%target-library-name(resilient_class)
|
|
|
|
// RUN: %target-build-swift-dylib(%t/%target-library-name(resilient_objc_class)) -Xfrontend -enable-resilience %S/../../Inputs/resilient_objc_class.swift -emit-module -emit-module-path %t/resilient_objc_class.swiftmodule -module-name resilient_objc_class -I%t -L%t -lresilient_struct
|
|
// RUN: %target-codesign %t/%target-library-name(resilient_objc_class)
|
|
|
|
// RUN: %target-build-swift %s -L %t -I %t -lresilient_struct -lresilient_class -lresilient_objc_class -o %t/main %target-rpath(%t)
|
|
// RUN: %target-codesign %t/main
|
|
|
|
// RUN: %target-run %t/main %t/%target-library-name(resilient_struct) %t/libresilient_class%{target-shared-library-suffix} %t/libresilient_objc_class%{target-shared-library-suffix}
|
|
|
|
|
|
// REQUIRES: executable_test
|
|
// REQUIRES: objc_interop
|
|
|
|
// Test Swift's hook for objc_getClass()
|
|
|
|
import StdlibUnittest
|
|
import ObjectiveC
|
|
import Foundation
|
|
import resilient_struct
|
|
import resilient_class
|
|
import resilient_objc_class
|
|
|
|
// Old OS versions do not have this hook.
|
|
let getClassHookMissing = {
|
|
nil == dlsym(UnsafeMutableRawPointer(bitPattern: -2),
|
|
"objc_setHook_getClass")
|
|
}()
|
|
|
|
var testSuite = TestSuite("objc_getClass")
|
|
|
|
|
|
class SwiftSuperclass { }
|
|
class SwiftSubclass : SwiftSuperclass { }
|
|
|
|
class ObjCSuperclass : NSObject { }
|
|
class ObjCSubclass : ObjCSuperclass { }
|
|
|
|
|
|
class MangledSwiftSuperclass { }
|
|
class MangledSwiftSubclass : MangledSwiftSuperclass { }
|
|
|
|
class MangledObjCSuperclass : NSObject { }
|
|
class MangledObjCSubclass : MangledObjCSuperclass { }
|
|
|
|
|
|
class GenericSwiftClass<Value> {
|
|
let value: Value
|
|
init(value: Value) { self.value = value }
|
|
}
|
|
class ConstrainedSwiftSuperclass : GenericSwiftClass<String> {
|
|
init() { super.init(value:"") }
|
|
}
|
|
class ConstrainedSwiftSubclass : ConstrainedSwiftSuperclass { }
|
|
|
|
|
|
class MangledGenericSwiftClass<Value> {
|
|
let value: Value
|
|
init(value: Value) { self.value = value }
|
|
}
|
|
class MangledConstrainedSwiftSuperclass : MangledGenericSwiftClass<String> {
|
|
init() { super.init(value:"") }
|
|
}
|
|
class MangledConstrainedSwiftSubclass : MangledConstrainedSwiftSuperclass { }
|
|
|
|
|
|
class GenericObjCClass<Value> : NSObject {
|
|
let value: Value
|
|
init(value: Value) { self.value = value }
|
|
}
|
|
class ConstrainedObjCSuperclass : GenericObjCClass<String> {
|
|
init() { super.init(value:"") }
|
|
}
|
|
class ConstrainedObjCSubclass : ConstrainedObjCSuperclass { }
|
|
|
|
|
|
class MangledGenericObjCClass<Value> : NSObject {
|
|
let value: Value
|
|
init(value: Value) { self.value = value }
|
|
}
|
|
class MangledConstrainedObjCSuperclass : MangledGenericObjCClass<String> {
|
|
init() { super.init(value:"") }
|
|
}
|
|
class MangledConstrainedObjCSubclass : MangledConstrainedObjCSuperclass { }
|
|
|
|
|
|
class ResilientSuperclass : ResilientOutsideParent {
|
|
var supervalue = 10
|
|
}
|
|
|
|
class ResilientSubclass : ResilientSuperclass {
|
|
var subvalue = 20
|
|
}
|
|
|
|
|
|
class ResilientFieldSuperclassSwift {
|
|
var supervalue = ResilientInt(i: 1)
|
|
}
|
|
|
|
class ResilientFieldSubclassSwift : ResilientFieldSuperclassSwift {
|
|
var subvalue = ResilientInt(i: 2)
|
|
}
|
|
|
|
class ResilientFieldSuperclassObjC : NSObject {
|
|
var supervalue = ResilientInt(i: 3)
|
|
}
|
|
class ResilientFieldSubclassObjC : ResilientFieldSuperclassObjC {
|
|
var subvalue = ResilientInt(i: 4)
|
|
}
|
|
|
|
class ResilientSubclassOfNSObject : ResilientNSObjectOutsideParent {
|
|
var subvalue = ResilientInt(i: 5)
|
|
}
|
|
|
|
class ResilientSubclassOfGenericNSObject : ResilientGenericNSObjectOutsideParent<Int> {
|
|
var subvalue = ResilientInt(i: 6)
|
|
init() { super.init(property: 0) }
|
|
}
|
|
|
|
class ResilientSubclassOfConcreteNSObject : ResilientConcreteNSObjectOutsideChild {
|
|
var subvalue = ResilientInt(i: 7)
|
|
init() { super.init(property: "") }
|
|
}
|
|
|
|
func requireClass(named name: String, demangledName: String) {
|
|
for _ in 1...2 {
|
|
let cls: AnyClass? = NSClassFromString(name)
|
|
expectNotNil(cls, "class named \(name) unexpectedly not found")
|
|
expectEqual(NSStringFromClass(cls!), demangledName,
|
|
"class named \(name) has the wrong name");
|
|
}
|
|
}
|
|
|
|
func requireClass(named name: String) {
|
|
return requireClass(named: name, demangledName: name)
|
|
}
|
|
|
|
testSuite.test("Basic")
|
|
.requireOwnProcess()
|
|
.code {
|
|
requireClass(named: "main.SwiftSubclass")
|
|
requireClass(named: "main.SwiftSuperclass")
|
|
requireClass(named: "main.ObjCSubclass")
|
|
requireClass(named: "main.ObjCSuperclass")
|
|
}
|
|
|
|
class Çlass<T> {}
|
|
class SubÇlass: Çlass<Int> {}
|
|
|
|
testSuite.test("BasicMangled")
|
|
.requireOwnProcess()
|
|
.code {
|
|
requireClass(named: "_TtC4main20MangledSwiftSubclass",
|
|
demangledName: "main.MangledSwiftSubclass")
|
|
requireClass(named: "_TtC4main22MangledSwiftSuperclass",
|
|
demangledName: "main.MangledSwiftSuperclass")
|
|
requireClass(named: "_TtC4main19MangledObjCSubclass",
|
|
demangledName: "main.MangledObjCSubclass")
|
|
requireClass(named: "_TtC4main21MangledObjCSuperclass",
|
|
demangledName: "main.MangledObjCSuperclass")
|
|
}
|
|
|
|
testSuite.test("Generic")
|
|
.skip(.custom({ getClassHookMissing },
|
|
reason: "objc_getClass hook not present"))
|
|
.requireOwnProcess()
|
|
.code {
|
|
requireClass(named: "main.ConstrainedSwiftSubclass")
|
|
requireClass(named: "main.ConstrainedSwiftSuperclass")
|
|
requireClass(named: "main.ConstrainedObjCSubclass")
|
|
requireClass(named: "main.ConstrainedObjCSuperclass")
|
|
}
|
|
|
|
testSuite.test("GenericMangled")
|
|
.skip(.custom({ getClassHookMissing },
|
|
reason: "objc_getClass hook not present"))
|
|
.requireOwnProcess()
|
|
.code {
|
|
guard #available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *) else { return }
|
|
requireClass(named: "_TtC4main24ConstrainedSwiftSubclass",
|
|
demangledName: "main.ConstrainedSwiftSubclass")
|
|
requireClass(named: "_TtC4main26ConstrainedSwiftSuperclass",
|
|
demangledName: "main.ConstrainedSwiftSuperclass")
|
|
requireClass(named: "_TtC4main23ConstrainedObjCSubclass",
|
|
demangledName: "main.ConstrainedObjCSubclass")
|
|
requireClass(named: "_TtC4main25ConstrainedObjCSuperclass",
|
|
demangledName: "main.ConstrainedObjCSuperclass")
|
|
|
|
// Make sure we don't accidentally ban high-bit characters.
|
|
requireClass(named: "_TtC4main9SubÇlass", demangledName: "main.SubÇlass")
|
|
requireClass(named: "4main9SubÇlassC", demangledName: "main.SubÇlass")
|
|
}
|
|
|
|
testSuite.test("ResilientSubclass")
|
|
.skip(.custom({ getClassHookMissing },
|
|
reason: "objc_getClass hook not present"))
|
|
.requireOwnProcess()
|
|
.code {
|
|
requireClass(named: "main.ResilientSubclass")
|
|
requireClass(named: "main.ResilientSuperclass")
|
|
|
|
expectEqual(ResilientSuperclass().supervalue, 10)
|
|
expectEqual(ResilientSubclass().supervalue, 10)
|
|
expectEqual(ResilientSubclass().subvalue, 20)
|
|
}
|
|
|
|
testSuite.test("ResilientField")
|
|
.skip(.custom({ getClassHookMissing },
|
|
reason: "objc_getClass hook not present"))
|
|
.requireOwnProcess()
|
|
.code {
|
|
requireClass(named: "main.ResilientFieldSubclassSwift")
|
|
requireClass(named: "main.ResilientFieldSuperclassSwift")
|
|
requireClass(named: "main.ResilientFieldSubclassObjC")
|
|
requireClass(named: "main.ResilientFieldSuperclassObjC")
|
|
|
|
expectEqual(ResilientFieldSuperclassSwift().supervalue.i, 1)
|
|
expectEqual(ResilientFieldSubclassSwift().supervalue.i, 1)
|
|
expectEqual(ResilientFieldSubclassSwift().subvalue.i, 2)
|
|
expectEqual(ResilientFieldSuperclassObjC().supervalue.i, 3)
|
|
expectEqual(ResilientFieldSubclassObjC().supervalue.i, 3)
|
|
expectEqual(ResilientFieldSubclassObjC().subvalue.i, 4)
|
|
}
|
|
|
|
testSuite.test("ResilientNSObject")
|
|
.skip(.custom({ getClassHookMissing },
|
|
reason: "objc_getClass hook not present"))
|
|
.requireOwnProcess()
|
|
.code {
|
|
guard #available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *) else { return }
|
|
requireClass(named: "_TtC4main27ResilientSubclassOfNSObject",
|
|
demangledName: "main.ResilientSubclassOfNSObject")
|
|
requireClass(named: "_TtC4main34ResilientSubclassOfGenericNSObject",
|
|
demangledName: "main.ResilientSubclassOfGenericNSObject")
|
|
requireClass(named: "_TtC4main35ResilientSubclassOfConcreteNSObject",
|
|
demangledName: "main.ResilientSubclassOfConcreteNSObject")
|
|
|
|
expectEqual(ResilientSubclassOfNSObject().subvalue.i, 5)
|
|
expectEqual(ResilientSubclassOfGenericNSObject().subvalue.i, 6)
|
|
expectEqual(ResilientSubclassOfConcreteNSObject().subvalue.i, 7)
|
|
}
|
|
|
|
testSuite.test("NotPresent") {
|
|
// This class does not exist.
|
|
expectNil(NSClassFromString("main.ThisClassDoesNotExist"));
|
|
|
|
// This name is improperly mangled
|
|
expectNil(NSClassFromString("_TtC5main"));
|
|
|
|
// Swift.Int is not a class type.
|
|
expectNil(NSClassFromString("Si"))
|
|
|
|
if #available(StdlibDeploymentTarget 5.3, *) {
|
|
// Mangled names with byte sequences that look like symbolic references
|
|
// should not be demangled. Use indirect references to test. Direct
|
|
// references often resolve to readable memory, and then the data there
|
|
// often looks like a descriptor with an unknown kind and the lookup code
|
|
// then fails gracefully. With an indirect reference, the indirected pointer
|
|
// is typically garbage and dereferencing it will crash.
|
|
expectNil(NSClassFromString("\u{2}badnews"));
|
|
expectNil(NSClassFromString("$s\u{2}badnews"));
|
|
expectNil(NSClassFromString("_T\u{2}badnews"));
|
|
}
|
|
|
|
if #available(StdlibDeploymentTarget 5.3, *) {
|
|
// Correct mangled names with additional text afterwards should not resolve.
|
|
expectNil(NSClassFromString("_TtC4main20MangledSwiftSubclass_"))
|
|
expectNil(NSClassFromString("_TtC4main22MangledSwiftSuperclassXYZ"))
|
|
expectNil(NSClassFromString("_TtC4main19MangledObjCSubclass123"))
|
|
expectNil(NSClassFromString("_TtC4main21MangledObjCSuperclasswhee"))
|
|
}
|
|
}
|
|
|
|
runAllTests()
|