swiftlang/swift

swift_getSingletonMetadata crashes when called via Bundle.main.classNamed()

Opened this issue · 0 comments

Description

The code somewhere in swift_getSingletonMetadata crashes with EXC_BAD_ACCESS (SIGSEGV) when trying to get an ObjC Class definition via Bundle.main.classNamed(), NSClassFromString, objc_getClass or objc_lookUpClass for a Swift class that references a class in RoomPlan or ActivityKit on an iOS version lower than the minimum required version of RoomPlan or ActivityKit.

This came up in getsentry/sentry-cocoa#3798.

Reproduction

I created a sample project on GH: https://github.com/philipphofmann/ObjCGetClassCrash, but here are the most important steps:

Create the following class in Swift

import RoomPlan

@available(iOS 17.0, *)
class RoomPlanWrapper {
    private var finalResults: CapturedStructure?
}

Then try to get the ObjC class definition via the following ObjC code.

void getClass(void) {
    // Also crashes with objc_getClass or objc_lookUpClass
    NSClassFromString(@"YourProjectName.RoomPlanWrapper");
}

Run the project on an iOS simulator with iOS version 15.x or lower.

The app crashes with EXC_BAD_ACCESS (SIGSEGV).

Stack dump

Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
Exception Subtype: KERN_INVALID_ADDRESS at 0x0000000000000000
Exception Codes: 0x0000000000000001, 0x0000000000000000
VM Region Info: 0 is not in any region.  Bytes before following region: 4306698240
      REGION TYPE                    START - END         [ VSIZE] PRT/MAX SHRMOD  REGION DETAIL
      UNUSED SPACE AT START
--->  
      __TEXT                      100b30000-100b3c000    [   48K] r-x/r-x SM=COW  ...GetClassCrash
Termination Reason: SIGNAL 11 Segmentation fault: 11
Terminating Process: exc handler [20850]

Triggered by Thread:  0

Thread 0 Crashed::  Dispatch queue: com.apple.main-thread
0   ???                           	               0x0 ???
1   ObjCGetClassCrash             	       0x100b33e20 type metadata completion function for RoomPlanWrapper + 28
2   libswiftCore.dylib            	       0x103b98930 swift::MetadataCacheEntryBase<(anonymous namespace)::SingletonMetadataCacheEntry, int>::doInitialization(swift::MetadataWaitQueue::Worker&, swift::MetadataRequest) + 392
3   libswiftCore.dylib            	       0x103b89cf8 swift_getSingletonMetadata + 956
4   ObjCGetClassCrash             	       0x100b33de4 type metadata accessor for RoomPlanWrapper + 68
5   ObjCGetClassCrash             	       0x100b33d98 ObjC metadata update function for RoomPlanWrapper + 16
6   libobjc.A.dylib               	       0x100df3938 realizeClassMaybeSwiftMaybeRelock(objc_class*, mutex_tt<false>&, bool) + 116
7   libobjc.A.dylib               	       0x100df9548 look_up_class + 108
8   Foundation                    	       0x10246fcb8 NSClassFromString + 192
9   ObjCGetClassCrash             	       0x100b31dec getClass + 36 (GetClassCrash.m:4)
10  ObjCGetClassCrash             	       0x100b336d8 ObjCGetClassCrashApp.init() + 28 (ObjCGetClassCrashApp.swift:13)
11  ObjCGetClassCrash             	       0x100b339e8 protocol witness for App.init() in conformance ObjCGetClassCrashApp + 12
12  SwiftUI                       	       0x10b0fa670 static App.main() + 64
13  ObjCGetClassCrash             	       0x100b33950 static ObjCGetClassCrashApp.$main() + 40
14  ObjCGetClassCrash             	       0x100b339fc main + 12 (ObjCGetClassCrashApp.swift:11)
15  dyld_sim                      	       0x100cb9cd8 start_sim + 20
16  dyld                          	       0x100e9a0e0 start + 2360


Thread 0 crashed with ARM Thread State (64-bit):
    x0: 0x00000000000000ff   x1: 0x000000016f2cd870   x2: 0x0000000000000000   x3: 0x0000000104594510
    x4: 0x0000000000000000   x5: 0x0000000000000000   x6: 0x0000000000000072   x7: 0x0000000000000000
    x8: 0x00000000000000ff   x9: 0x0000000000000000  x10: 0x0000000000000000  x11: 0x0000000000000000
   x12: 0x0000000000000000  x13: 0x0000000031070000  x14: 0x0000000031000000  x15: 0x000000000000006f
   x16: 0x0000000000000000  x17: 0x000000000d400000  x18: 0x0000000000000000  x19: 0x00006000031280c0
   x20: 0x000000016f2cd8f8  x21: 0x00006000031280c0  x22: 0x0000000100b40270  x23: 0x0000000000000000
   x24: 0x0000000100b48938  x25: 0x0000000000000000  x26: 0x0000000000000000  x27: 0x0000000000000002
   x28: 0x0000000000000000   fp: 0x000000016f2cd810   lr: 0x0000000100b33f00
    sp: 0x000000016f2cd7e0   pc: 0x0000000000000000 cpsr: 0x60001400
   far: 0x0000000000000000  esr: 0x82000006 (Instruction Abort) Translation fault

Expected behavior

The call to Bundle.main.classNamed(), NSClassFromString, objc_getClass or objc_lookUpClass should return the class without crashing or nil.

Environment

swift-driver version: 1.90.11.1 Apple Swift version 5.10 (swiftlang-5.10.0.13 clang-1500.3.9.4)
Target: arm64-apple-macosx14.0

It also crashes when compiling the project with Xcode 15.1 / Swift 5.9.

Additional information

No response