Swift 4.2: Segmentation Fault - possible NPE in swift_dynamicCastMetatypeImpl in Casting.cpp


#1

I have this code on x86:

cat cast.swift

func allToAll<T, U>(_ t: T, _: U.Type) -> Bool {
  return t is U
}
allToAll(5, (AnyObject & CustomStringConvertible).self)

I get Segmentation fault upon running this code:

:/home/swift/testcases# ./cast
Segmentation fault (core dumped)

I think problem has to do with targetType being null over here https://github.com/apple/swift/blob/78f3017436dbbfe380b69b09a2d02937524ab076/stdlib/public/runtime/Casting.cpp#L1127

It seem like code expect targetType to be always not-null - A NPE check "fixes" the issue but I was wondering if that is the right thing to do. What would be expected targetType in this case?

Thanks.


(Jordan Rose) #2

I think the target type should be AnyObject & CustomStringConvertible, which should end up in the _dynamicCastToExistential function in that file rather than the one you called out. The code doesn't seem to crash on macOS for me (using master or 4.2), so maybe it's a problem with the non-SWIFT_OBJC_INTEROP parts of the code?


(Joe Groff) #3

Yeah, possibly this code needs to be updated now that casts also bridge on Linux. cc @millenomi


#4

It seems like exception is triggered during this check on Linux:

* thread #1, name = 'cast', stop reason = step over
    frame #0: 0x000003fffd99c280 libswiftCore.so`swift_swiftValueConformsTo at BridgeObjectiveC.swift:731 [opt]
   728    if let foundationType = _foundationSwiftValueType {
   729      return foundationType is T.Type
   730    } else {
-> 731      return _SwiftValue.self is T.Type
   732    }
   733  }

By the time code execution reaches CompatibilityOverride.def:100 it looses it's targetType

Any hints where I could add/remove checks/cast?


#5

Interestingly, wrapping it with print works. Wonder why that would be the case? @millenomi, any pointers?

allToAll(5, (AnyObject & CustomStringConvertible).self) //This segfaults on Linux, but ...
print(allToAll(5, (AnyObject & CustomStringConvertible).self)) // .. this works on Linux