Skip to content

Commit c3aa443

Browse files
committed
[Runtime] Fix crash in protocol conformance checks on KVO artificial subclasses.
tryGetCompleteMetadataNonblocking crashes on artificial subclasses due to the NULL type descriptor. Explicitly check for artificial subclasses in getSuperclassForMaybeIncompleteMetadata and immediately return their Superclass field. Artificial subclasses are always fully initialized so we don't need to do anything special for them. rdar://72583931
1 parent 75fb3c7 commit c3aa443

File tree

2 files changed

+18
-0
lines changed

2 files changed

+18
-0
lines changed

stdlib/public/runtime/ProtocolConformance.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,14 @@ static MetadataResponse getSuperclassForMaybeIncompleteMetadata(
169169
if (!classMetadata)
170170
return {_swift_class_getSuperclass(metadata), MetadataState::Complete};
171171

172+
#if SWIFT_OBJC_INTEROP
173+
// Artificial subclasses are not valid type metadata and
174+
// tryGetCompleteMetadataNonblocking will crash on them. However, they're
175+
// always fully set up, so we can just skip it and fetch the Subclass field.
176+
if (classMetadata->isTypeMetadata() && classMetadata->isArtificialSubclass())
177+
return {classMetadata->Superclass, MetadataState::Complete};
178+
#endif
179+
172180
MetadataState metadataState;
173181
if (knownMetadataState)
174182
metadataState = *knownMetadataState;

test/Casting/Casts.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -983,6 +983,16 @@ CastsTests.test("Do not overuse __SwiftValue") {
983983
}
984984
#endif
985985

986+
#if _runtime(_ObjC)
987+
CastsTests.test("Artificial subclass protocol conformance") {
988+
class SwiftClass: NSObject {}
989+
let subclass: AnyClass = objc_allocateClassPair(SwiftClass.self,
990+
"ArtificialSwiftSubclass", 0)!
991+
objc_registerClassPair(subclass)
992+
expectFalse(subclass is P.Type)
993+
}
994+
#endif
995+
986996
CastsTests.test("Do not overuse __SwiftValue (non-ObjC)") {
987997
struct Bar {}
988998
// This should succeed because this is what __SwiftValue boxing is for

0 commit comments

Comments
 (0)