Skip to content

Track data and src on canvas_jpeg_error_mgr to free on libjpeg longjmp#2581

Open
iurisilvio wants to merge 1 commit into
Automattic:masterfrom
iurisilvio:fix/jpeg-decode-longjmp-leak
Open

Track data and src on canvas_jpeg_error_mgr to free on libjpeg longjmp#2581
iurisilvio wants to merge 1 commit into
Automattic:masterfrom
iurisilvio:fix/jpeg-decode-longjmp-leak

Conversation

@iurisilvio
Copy link
Copy Markdown

Fixes #2577.

When libjpeg calls error_exit during jpeg_read_scanlines() (the common failure for corrupt or truncated JPEGs where the header decodes but the entropy-coded scan data is malformed), it does longjmp back to the setjmp in loadJPEGFromBuffer. That bypasses the cleanup code in decodeJPEGIntoSurface, leaking both data (width * height * 4 bytes) and src (scanline buffer) on every call.

Standalone repro on canvas@3.2.3 shows ~4 MiB leaked per call — process OOMs in seconds under sustained load on malformed JPEGs. Full numbers in #2577.

The fix tracks both pointers on canvas_jpeg_error_mgr so the error handler can delete[] them before the longjmp. The decode flow is reordered so jpeg_destroy_decompress and delete[] src happen before the cairo surface is created — that way the success path's ownership transfer is symmetric with the failure path, with no double-free.

If libjpeg calls error_exit during jpeg_read_scanlines (corrupt or
truncated JPEG that decoded the header but fails in the scan), it
longjmps back to the setjmp point in loadJPEGFromBuffer. That bypasses
the cleanup at the bottom of decodeJPEGIntoSurface, leaking both
'data' (width * height * 4) and 'src' (width * output_components).

Store both pointers on the canvas_jpeg_error_mgr so the error handler
can delete[] them before longjmp. Also reorder cleanup to destroy
libjpeg state and free src before creating the cairo surface, so the
success path is symmetric with the new failure path.
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.

decodeJPEGIntoSurface leaks data and src on libjpeg longjmp from jpeg_read_scanlines

1 participant