Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SR-10547] Unavailable class with Swift-only protocol implementation causes a crash in getCanonicalTypeMetadata #52947

Open
ghugues opened this issue Apr 25, 2019 · 6 comments
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself crash Bug: A crash, i.e., an abnormal termination of software regression run-time crash Bug → crash: Swift code crashed during execution swift 5.0

Comments

@ghugues
Copy link

ghugues commented Apr 25, 2019

Previous ID SR-10547
Radar rdar://problem/50207523
Original Reporter @ghugues
Type Bug

Attachment: Download

Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Bug, 5.0Regression, RunTimeCrash
Assignee None
Priority Medium

md5: 7cca5f7cab0ff32756235f128b90b95f

Issue Description:

When a class that is only available starting with a given version of iOS implements a Swift only protocol, a crash occurs when testing conformance to this protocol on previous versions of iOS.

The following example crashes on all versions of iOS below iOS 12.0 :

protocol TestProtocol { }

@available(iOS 12.0, *)
class iOS12OnlySubclass: UITextInputPasswordRules, TestProtocol { }

func testCrash() {
    let instance = NSObject() // Can be anything
    _ = instance is TestProtocol // Crashes here
}

testCrash()

The UITextInputPasswordRules is just an example of a class that was introduced in iOS 12, any other class introduced in iOS 12 will cause the same crash.
iOS 12 is just an example of a version of iOS. If the class is only available in iOS n, then the crash occurs on all versions of iOS less than n.

This bug was introduced in Xcode 10.2 and does not seem to occur in Xcode 10.1
Compiled with Xcode 10.2, Swift 5.0 -> Crash
Compiled with Xcode 10.2, Swift 4.2 -> Crash
Compiled with Xcode 10.1, Swift 4.2 -> No crash

Workaround: If the protocol TestProtocol is declared @objc, no crash occurs.

Stacktrace :

* thread #​1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
    frame #​0: 0x0000000109a6c19f CoreFoundation`___forwarding___ + 1471
    frame #​1: 0x0000000109a6bb58 CoreFoundation`__forwarding_prep_0___ + 120
    frame #​2: 0x0000000105b93a14 libobjc.A.dylib`CALLING_SOME_+initialize_METHOD + 19
    frame #​3: 0x0000000105b93dae libobjc.A.dylib`_class_initialize + 276
    frame #​4: 0x0000000105b9a5e7 libobjc.A.dylib`lookUpImpOrForward + 225
    frame #​5: 0x0000000105baa3d4 libobjc.A.dylib`_objc_msgSend_uncached + 68
    frame #&#8203;6: 0x000000010527cde5 TestApp`type metadata accessor for iOS12OnlySubclass at <compiler-generated>:0
    frame #&#8203;7: 0x0000000108d0747c libswiftCore.dylib`swift::TargetProtocolConformanceDescriptor<swift::InProcess>::getCanonicalTypeMetadata() const + 172
    frame #&#8203;8: 0x0000000108d08564 libswiftCore.dylib`swift_conformsToSwiftProtocolImpl(swift::TargetMetadata<swift::InProcess> const*, swift::TargetProtocolDescriptor<swift::InProcess> const*, llvm::StringRef) + 292
    frame #&#8203;9: 0x0000000108d08348 libswiftCore.dylib`swift_conformsToProtocol + 152
    frame #&#8203;10: 0x0000000108cdcd8a libswiftCore.dylib`swift::_conformsToProtocol(swift::OpaqueValue const*, swift::TargetMetadata<swift::InProcess> const*, swift::TargetProtocolDescriptorRef<swift::InProcess>, swift::TargetWitnessTable<swift::InProcess> const**) + 42
    frame #&#8203;11: 0x0000000108ce0b97 libswiftCore.dylib`_conformsToProtocols(swift::OpaqueValue const*, swift::TargetMetadata<swift::InProcess> const*, swift::TargetExistentialTypeMetadata<swift::InProcess> const*, swift::TargetWitnessTable<swift::InProcess> const**) + 231
    frame #&#8203;12: 0x0000000108cdff69 libswiftCore.dylib`_dynamicCastToExistential(swift::OpaqueValue*, swift::OpaqueValue*, swift::TargetMetadata<swift::InProcess> const*, swift::TargetExistentialTypeMetadata<swift::InProcess> const*, swift::DynamicCastFlags) + 489
  * frame #&#8203;13: 0x000000010527d02a TestApp`testCrash() at AppDelegate.swift:19:18

Console logs :

TestApp[18250:3491571] *** NSForwarding: warning: object 0x1052812f8 of class 'TestApp.iOS12OnlySubclass' does not implement methodSignatureForSelector: -- did you forget to declare the superclass of 'TestApp.iOS12OnlySubclass'?
TestApp[18250:3491571] *** NSForwarding: warning: object 0x1052812f8 of class 'TestApp.iOS12OnlySubclass' does not implement doesNotRecognizeSelector: -- abort
@belkadan
Copy link
Contributor

Even though the repro case is so simple, can you attach a project so that we can be sure we're testing the same configuration? Does this happen in both debug and release builds?

@belkadan
Copy link
Contributor

@mikeash, maybe we're trying to instantiate the type when reading the conformance records?

@mikeash
Copy link
Contributor

mikeash commented Apr 25, 2019

Looks like. And somehow it ends up looking like an ObjC root class and we blow up trying to initialize it because it's not made to be a root class.

ObjC is supposed to handle classes with weak, not-present superclasses by making them act as if they were nil. Either that's not working, or Swift isn't emitting the superclass in the right way to trigger it.

In addition to that, we'll also need to make sure that the rest of this code properly handles a nil class.

@ghugues
Copy link
Author

ghugues commented Apr 25, 2019

I've attached a sample project. Crash happens both on Debug and Release configurations.
Tested on an iPhone 7 running iOS 11.0

@JaviSoto
Copy link
Contributor

If any other stack-traces would be useful to diagnose this issue, let me know. Since releasing the first update of the Twitch app with Swift 5, we're seeing dozens of distinct crashes just like this one, referencing different types.

@ghugues
Copy link
Author

ghugues commented Oct 19, 2019

Hi,
Just letting you know that I'm still reproducing this issue with Xcode 11.1

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
@AnthonyLatsis AnthonyLatsis added the crash Bug: A crash, i.e., an abnormal termination of software label Dec 12, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself crash Bug: A crash, i.e., an abnormal termination of software regression run-time crash Bug → crash: Swift code crashed during execution swift 5.0
Projects
None yet
Development

No branches or pull requests

5 participants