1
0
mirror of https://github.com/libjpeg-turbo/libjpeg-turbo.git synced 2026-10-23 11:48:53 +03:00
Files
DRC 0ff47f0b46 jpeg_crop_scanline: Throw error if raw data output
jpeg_crop_scanline() doesn't actually work with raw data output.  If
buffered-image mode is disabled and raw data output is enabled, the
function throws JERR_BAD_STATE because the global state is DSTATE_RAW_OK
rather than DSTATE_SCANNING.  However, due to an oversight in
8162eddf04 (libjpeg-turbo 2.1.4), enabling
both buffered-image mode and raw data output allowed the caller to sneak
through the gates.  Thus, executing the following sequence with the same
libjpeg API instance caused a use-after-free issue:

- jpeg_start_decompress(&cinfo)
  * calls j*init_upsampler() to allocate the upsampler (cinfo.upsample)
- jpeg_abort_decompress(&cinfo)
  * frees the upsampler
- cinfo.raw_data_out = TRUE
- cinfo.buffered_image = TRUE
- jpeg_start_decompress(&cinfo)
  * does not call j*init_upsampler(), because cinfo.raw_data_out == TRUE
- jpeg_crop_scanline(&cinfo, &xoffset, &width)
  where xoffset and width would cause any of the component planes to be
  cropped to a width of 1 sample
  * fails to catch that raw data output is enabled, because the global
    state is DSTATE_BUFIMAGE rather than DSTATE_RAW_OK
  * fails to catch that the previous decompression operation was
    aborted, because cinfo->output_scanline is 0 (since
    jpeg*_read_scanlines() was never called)
  * calls j*init_upsampler() with
    cinfo->master->jinit_upsampler_no_alloc == TRUE, which tells
    j*init_upsampler() to reuse the upsampler
  * j*init_upsampler() tries to reuse the upsampler that has already
    been freed.

Any application that did this could never work properly.  (The best it
could hope for is a bogus output image or an error.)  Thus, this
represented an opportunity for API hardening rather than a security
vulnerability.

This commit also modifies the jpeg_crop_scanline() documentation to
clarify that the function doesn't work with raw data output.
(Previously, the documentation was subtle on that point.  It says that
jpeg_crop_scanline() must be called between jpeg_start_decompress() and
jpeg*_read_scanlines(), which implies that it can't be called between
jpeg_start_decompress() and jpeg*_read_raw_data().)
2026-04-11 11:39:12 -04:00
..
2026-03-25 08:58:02 -04:00