App built with Release configuration and Xcode15.3 or later version will crashes on real devices(iPhone and iPad)

I created a demo Xcode project, it can reproduce the crash easily.

Please follow the 'STEPS TO REPRODUCE THE CRASH' below:

  1. Archive the demo project with Release configuration and Xcode15.3 or later versions
  2. Export ipa with adhoc.
  3. Install it on your real devices(iPhone or iPad).
  4. Launch the app.
  5. Press 'Parse PDF' button, then App will crash.
Answered by DTS Engineer in 801821022

It’s likely that you’ll receive an official reply via your bug (FB14806158) soon, but I want to expand on that a little. You wrote:

I created a

Thanks for that.

Note I wasn’t able to download your project via that link, but I was able to get it from your bug report. In general, if you’re sharing a test project here, it’s best to put it on a site, like GitHub, that doesn’t required authentication. For more hints and tips, see Creating a test project.

Looking at your project, I see that it has code like this:

var contents = String()
…
let stream = CGPDFContentStreamCreateWithPage(page)
let scanner = CGPDFScannerCreate(stream, operators, &contents)
                                                 // ^ Forming 'UnsafeMutableRawPointer'
                                                 // to an inout variable of type
                                                 // String exposes the internal
                                                 // representation rather than
                                                 // the string contents.

This is almost certainly the cause of the crash you’re seeing. Swift’s & sigil has a very different meaning from the equivalent in C. I discuss this in gory detail in The Peril of the Ampersand.

A minimal fix for this would like:

var contents = String()
withUnsafeMutablePointer(to: &contents) { stringPointer in
    let stream = CGPDFContentStreamCreateWithPage(page)
    let scanner = CGPDFScannerCreate(stream, operators, stringPointer)
    …
}

Your operator callbacks can now cast their context parameter to an UnsafeMutablePointer<String>, and modify the string as necessary.

However, my preferred option for dealing with this is to create a temporary object and then pass in self. I have posted numerous examples of this in the past; here’s one that’s kinda similar to what you’re trying to do.

The nice thing about this approach is that it’s not limited to just one value. You can access an arbitrary amount of state simply by adding more properties to the class.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Any suggestion is appreciate, i have fired a bug for apple. thanks.

Unfortunately apple has no response for the bug,

anyone can help? thanks in advance

It’s likely that you’ll receive an official reply via your bug (FB14806158) soon, but I want to expand on that a little. You wrote:

I created a

Thanks for that.

Note I wasn’t able to download your project via that link, but I was able to get it from your bug report. In general, if you’re sharing a test project here, it’s best to put it on a site, like GitHub, that doesn’t required authentication. For more hints and tips, see Creating a test project.

Looking at your project, I see that it has code like this:

var contents = String()
…
let stream = CGPDFContentStreamCreateWithPage(page)
let scanner = CGPDFScannerCreate(stream, operators, &contents)
                                                 // ^ Forming 'UnsafeMutableRawPointer'
                                                 // to an inout variable of type
                                                 // String exposes the internal
                                                 // representation rather than
                                                 // the string contents.

This is almost certainly the cause of the crash you’re seeing. Swift’s & sigil has a very different meaning from the equivalent in C. I discuss this in gory detail in The Peril of the Ampersand.

A minimal fix for this would like:

var contents = String()
withUnsafeMutablePointer(to: &contents) { stringPointer in
    let stream = CGPDFContentStreamCreateWithPage(page)
    let scanner = CGPDFScannerCreate(stream, operators, stringPointer)
    …
}

Your operator callbacks can now cast their context parameter to an UnsafeMutablePointer<String>, and modify the string as necessary.

However, my preferred option for dealing with this is to create a temporary object and then pass in self. I have posted numerous examples of this in the past; here’s one that’s kinda similar to what you’re trying to do.

The nice thing about this approach is that it’s not limited to just one value. You can access an arbitrary amount of state simply by adding more properties to the class.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Hi Apple, Thanks for your reply, i tried to use withUnsafeMutablePointer and the crash disappeared. but we did not figure out the root causes:

  1. Why it crashed when building with Release configuration and using Xcode15.3 or newer Xcode versions including Xcode beta 16.1?
  2. Why it does not crash when building with Release configuration and using Xcode15.2?
  3. Why it does not crash when building with Debug configuration and using any Xcode versions?
  4. Why it does not crash if it goes into an extra logic if isUsingCharFilter is true? for more detail see

If we do not figure out the root cause described above, it has big risk. cause it maybe a bug of Xcode15.3 and newer Xcode versions. Please help to figure out, thanks for your help.

i tried to use withUnsafeMutablePointer and the crash disappeared.

Cool.

but we did not figure out the root causes:

Yeah, you kinda did. Your program was previously relying on undefined behaviour. The behaviour of such programs is… well… undefined. You may see different behaviour with different compiler versions, different compiler settings, different OS versions, different users, and so on.

Now, it’s probably possible to find answers to all the questions you posed, but that’ll require a) digging into the compiler implementation, including the LLVM optimisers, and b) debugging your program on specific OS versions at the assembly language level. All of that is possible, and in some cases it’s justified. However, in this case you have a clear answer and you should just take the win.

If you want to spend more time on this I recommend that you audit the rest of your project for compiler warnings. In this case you didn’t heed the compiler warning about this problem and that caused you to spend a lot of time debugging it based on the symptoms. If there are other warnings like that in your code, you should investigate them now. That’ll save you time in the long term.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

App built with Release configuration and Xcode15.3 or later version will crashes on real devices(iPhone and iPad)
 
 
Q