wickwirew / Runtime

A Swift Runtime library for viewing type info, and the dynamic getting and setting of properties.
MIT License
1.08k stars 94 forks source link

TypeInfo of class types crashes on linux for swift >= 5.4 #92

Closed Supereg closed 2 years ago

Supereg commented 3 years ago

Hello,

wanted to report that the Runtime framework crashes (segfault) when used on linux platforms using a swift compiler >= 5.4. To my analysis, it comes from calling typeInfo(of:) for any class type.

I noticed this in the environment of our own project https://github.com/Apodini/Apodini/pull/294, but could also easily reproduce it with the provided test cases of the Runtime framework.

The following test cases fail:

I found that any call to typeInfo(of:) with a class type will result in a segfault (see backtrace below). Specifically, it will most certainly fail when evaluating the mangledName() method (inside the ClassMetadata.toTypeInfo() call): https://github.com/wickwirew/Runtime/blob/5b82a3e74bd9fd5dfcad8e6ab8cc3f907aa4e235/Sources/Runtime/Metadata/NominalMetadataType.swift#L43

If you uncomment that line it will fail on the next access to the pointer.pointee.typeDescriptor.pointee chain (e.g. in NominalMetadataType.numberOfFields).

For context, I created some extensive GitHub Ci (see Supereg/Runtime feature/github-ci branch) which runs the tests cases in all swift 5 version for all common linux distributions available on the Swift DockerHub: GitHub CI Run Overview. It shows that since swift 5.4 every swift release on all linux platforms are affected. I'll plan to create a pull request for that later as well.

Below is an exemplary backtrace of the segfault happening when running the shown command under xenial.

swift test --filter GetSetClassTests
[4/4] Build complete!
Test Suite 'Selected tests' started at 2021-06-30 15:04:32.986
Test Suite 'GetSetClassTests' started at 2021-06-30 15:04:32.987
Test Case 'GetSetClassTests.testGet' started at 2021-06-30 15:04:32.987
Exited with signal code 11
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x00007f1de0332263 in swift::metadataimpl::ValueWitnesses<swift::metadataimpl::NativeBox<unsigned int, 4ul, 4ul, 4ul> >::initializeWithCopy(swift::OpaqueValue*, swift::OpaqueValue*, swift::TargetMetadata<swift::InProcess> const*) ()
   from /usr/lib/swift/linux/libswiftCore.so
#1  0x000055a47e1b7dec in $s7Runtime15RelativePointerV8advancedSpyq_GyF (self=<error reading variable: Cannot access memory at address 0x28>) at /usr/src/Runtime/Sources/Runtime/Pointers/RelativePointer.swift:31
#2  0x000055a47e1ac340 in $s7Runtime19NominalMetadataTypePAAE11mangledNameSSyF (self=...) at /usr/src/Runtime/Sources/Runtime/Metadata/NominalMetadataType.swift:43
#3  0x000055a47e1a79ef in $s7Runtime13ClassMetadataV10toTypeInfoAA0eF0VyF (self=...) at /usr/src/Runtime/Sources/Runtime/Metadata/ClassMetadata.swift:88
#4  0x000055a47e1a80ab in $s7Runtime13ClassMetadataVAA19TypeInfoConvertibleA2aDP02todE0AA0dE0VyFTW ()
#5  0x000055a47e1b60c6 in $s7Runtime8typeInfo2ofAA04TypeC0VypXp_tKF (type=...) at /usr/src/Runtime/Sources/Runtime/Models/TypeInfo.swift:81
#6  0x000055a47e1c1a09 in $s12RuntimeTests011GetSetClassB0C04testC0yyKF (self=...) at /usr/src/Runtime/Tests/RuntimeTests/GetSetClassTests.swift:60
#7  0x000055a47e1e9625 in $s12RuntimeTests011GetSetClassB0C05__allB0SaySS_yyKcACctGvpZfiyyKcACcfu_yyKcfu0_ () at /usr/src/Runtime/Tests/RuntimeTests/XCTestManifests.swift:13
#8  0x000055a47e1f02af in $s12RuntimeTests011GetSetClassB0C05__allB0SaySS_yyKcACctGvpZfiyyKcACcfu_yyKcfu0_TA ()
#9  0x000055a47e1bb16f in $ss5Error_pIegzo_ytsAA_pIegrzo_TR ()
#10 0x000055a47e1ca944 in $ss5Error_pIegzo_ytsAA_pIegrzo_TRTA ()
#11 0x00007f1de0618b5c in $syts5Error_pIegrzo_sAA_pIegzo_TRTA () from /usr/lib/swift/linux/libXCTest.so
#12 0x00007f1de06189b8 in $s6XCTest4test33_3BE257A46ADB477C7BF2D39968B39F9DLLyyAA0A4CaseCKcyyKcxcAERbzlFyAEKcfU_TA () from /usr/lib/swift/linux/libXCTest.so
#13 0x00007f1de061894f in $s6XCTest0A4CaseCs5Error_pIeggzo_ACytsAD_pIegnrzo_TRTA () from /usr/lib/swift/linux/libXCTest.so
#14 0x00007f1de0618c16 in $s6XCTest0A4CaseCs5Error_pIeggzo_ACytsAD_pIegnrzo_TRTA.19 () from /usr/lib/swift/linux/libXCTest.so
#15 0x00007f1de060a628 in $s6XCTest0A4CaseCyts5Error_pIegnrzo_ACsAD_pIeggzo_TRTA () from /usr/lib/swift/linux/libXCTest.so
#16 0x00007f1de06172f8 in $s6XCTest0A4CaseC10invokeTestyyF () from /usr/lib/swift/linux/libXCTest.so
#17 0x00007f1de06170e3 in $s6XCTest0A4CaseC7performyyAA0A3RunCF () from /usr/lib/swift/linux/libXCTest.so
#18 0x00007f1de061a980 in $s6XCTestAAC3runyyF () from /usr/lib/swift/linux/libXCTest.so
#19 0x00007f1de0618eaf in $s6XCTest0A5SuiteC7performyyAA0A3RunCF () from /usr/lib/swift/linux/libXCTest.so
#20 0x00007f1de061a980 in $s6XCTestAAC3runyyF () from /usr/lib/swift/linux/libXCTest.so
#21 0x00007f1de0618eaf in $s6XCTest0A5SuiteC7performyyAA0A3RunCF () from /usr/lib/swift/linux/libXCTest.so
#22 0x00007f1de061a980 in $s6XCTestAAC3runyyF () from /usr/lib/swift/linux/libXCTest.so
#23 0x00007f1de0615d24 in $s6XCTest7XCTMain_9arguments9observerss5NeverOSayAA0A4CaseCm04testF5Class_SaySS_yAHKctG8allTeststG_SaySSGSayAA0A11Observation_pGtF () from /usr/lib/swift/linux/libXCTest.so
#24 0x00007f1de06156eb in $s6XCTest7XCTMainys5NeverOSayAA0A4CaseCm04testD5Class_SaySS_yAFKctG8allTeststGF () from /usr/lib/swift/linux/libXCTest.so
#25 0x000055a47e1bace1 in main () at /usr/src/Runtime/Tests/LinuxMain.swift:8

Happy to help if I can provide any further assistance.

Supereg commented 3 years ago

Reading through the ABI docs, might this be related to the following change: https://github.com/apple/swift/commit/38fc849a1fc8ea703de2fd1f280b43c682b70257#diff-22fb9f1513d9c05f34d493826b4553bba65a4336a41ae4413678feec549db3a5?

It reads like that on platforms without Objective-C interoperability the objCRuntimeReserve and rodataPointer fields are not present anymore.

Judging by the git tags, this change was introduced with swift 5.4

Supereg commented 3 years ago

Alright, I think I got it fixed. Successfully passes on all swift versions on all linux platforms (see my Action Run, note the swiftlang/swift:nightly-xenial which is failing. The tag is actually 9 months old and contains a swift 5.3 dev version which seemingly has the changed class metadata layout).