Repository navigation
Conversation
Decoding a truncated or corrupt PNG with PNGImageFormat terminates the process instead of returning an invalid Image. For example, the first half of a valid PNG passed to ImageFileFormat::loadFrom crashes on Windows, and on any platform that uses the bundled libpng rather than CoreImage. When libpng reports an error it calls the error callback and, if that returns, its default handler, which jumps to the libpng-owned jump buffer and otherwise aborts. Where PNG_SETJMP_SUPPORTED is defined, the error callback called setjmp on that buffer and returned, so the default handler jumped back into a stack frame that had already returned. The callback now always longjmps to the jump buffer passed to png_set_error_fn, which readHeader, readImageData and writeImageToStream set with setjmp, so they return failure as intended.
emezeske
marked this pull request as ready for review
October 7, 2026 18:23
Collaborator
|
This pull request has been mentioned on The JUCE Forum. There might be relevant details there: https://forum.juce.com/t/pr-fix-pngloader-crash-on-invalid-png-files/69663/1 |
Member
|
Thank you for reporting. Added here: fcee915 |
Contributor
Author
|
Thanks! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Decoding a truncated or corrupt PNG with PNGImageFormat (or ImageFileFormat::loadFrom) terminates the process instead of returning an invalid Image. libpng prints its error to stderr, for example "libpng error: bad header (invalid type)", and then the process aborts.
To reproduce, take any valid PNG, keep the first half of its bytes, and pass them to PNGImageFormat::decodeImage through a MemoryInputStream. Flipping a byte of the IHDR chunk's CRC does the same. I see it on Windows with MSVC; it applies wherever the bundled libpng is used rather than CoreImage, since the bundled pnglibconf.h defines PNG_SETJMP_SUPPORTED.
When libpng hits an error it calls the error callback, and if that returns, its own default handler, which longjmps to the jump buffer libpng owns or else aborts. With PNG_SETJMP_SUPPORTED defined, PNGHelpers::errorCallback called setjmp on that libpng-owned buffer and returned, so the default handler then jumped back into the callback's frame after it had already returned. The callback now always longjmps to the jmp_buf passed to png_set_error_fn, which readHeader, readImageData and writeImageToStream each set with setjmp, so they return failure as they were written to.