at-internet / atinternet-apple-sdk

AT Internet mobile analytics solution for Apple devices
http://www.atinternet.com
MIT License
25 stars 47 forks source link

Crash on iOS 12 or lower when Objective-C app uses a Swift framework that tries to decode a missing JSON property #120

Closed felipe-saez closed 3 years ago

felipe-saez commented 3 years ago

Hello team,

Hope you are all doing well.

There seems to be a weird crash which happens under the following conditions:

More specifically, the crash occurs when you call the decode method of the JSONDecoder class. It also happens when calling the decode or decodeIfPresent methods of the KeyedDecodingContainer struct, see the example below:

@objc public class TestClass: NSObject {
    
    struct TestType: Decodable {
        let name: String
        let description: String
        let nonExistingProperty: String // we won't provide this property as part of the data
    }
    
    @objc public func process() {
        let data = """
        {
            "name": "A name",
            "description": "A description"
        }
        """.data(using: .utf8) // <- we don't provide `nonExistingProperty`
        
        let jsonDecoder = JSONDecoder()
        
        if let data = data, let decoded = try? jsonDecoder.decode(TestType.self, from: data) { // <-- This is where the app crashes
            print("Name: \(decoded.name)")
        }
    }
}

This is the crash message, which doesn't give much details: Thread 1: EXC_BAD_ACCESS (code=1, address=0x0)

image

Please find this project that meets all the conditions mentioned above where it's possible to reproduce the crash (I'm currently using Xcode 12.5):

ATInternetSampleApp.zip

Please find also the stack trace I get when the crash happens:

Stack trace crash AT Internet.txt

I noticed that this crash is similar to what is described here: https://stackoverflow.com/questions/58694448/ios-12-error-swift-getassociatedtypewitnessslowimpl-exc-bad-access-in-assembly-c/59338381#59338381 Basically, they mention that without explanation, once they removed an unused protocol, in their case Identifiable, they managed to remove the issue. By looking into the ATInternet code, more specifically here https://github.com/at-internet/atinternet-apple-sdk/blob/master/ATInternetTracker/Sources/Crypt.swift#L171, I noticed that the CustomStringConvertible protocol is not used and if I remove it, the crash disappears. Neither the issue nor the fix make sense, because one would think that because of the @available(iOS 13.0, *) check this code would not be visible to iOS 12 but removing the unused protocol just magically works, maybe an Xcode compiler bug?

Please let me know if you think more information is required.

Kind regards,

Felipe

nsagnett commented 3 years ago

Hello,

Many thanks for the PR (and thanks XCode to give us some dream every day !)

I just released 2.23.5 version which embed your fix, thanks again !

Regards,

felipe-saez commented 3 years ago

thanks for deploying the fix so quickly!