Skip to content

PNGLoader: Return an invalid image when a PNG is damaged - #1763

Closed
emezeske wants to merge 1 commit into
juce-framework:developfrom
emezeske:pr/png-error-longjmp
Closed

emezeske wants to merge 1 commit into
juce-framework:developfrom
emezeske:pr/png-error-longjmp

Conversation

@emezeske

@emezeske emezeske commented Oct 7, 2026

Copy link
Copy Markdown
Contributor

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.

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
emezeske marked this pull request as ready for review October 7, 2026 18:23
@juce-push-bot

Copy link
Copy Markdown
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

@tpoole

tpoole commented Oct 8, 2026

Copy link
Copy Markdown
Member

Thank you for reporting. Added here: fcee915

@tpoole tpoole closed this Oct 8, 2026
@emezeske

emezeske commented Oct 8, 2026

Copy link
Copy Markdown
Contributor Author

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants