Skip to content

Commit

Permalink
Re-fix buf img mode decompr err w/short prog JPEGs
Browse files Browse the repository at this point in the history
This commit reverts 4dbc293 and
9f8f683 (the previous two commits) and
fixes #613 the correct way.  The crux of the issue wasn't the size of
the whole_image virtual array but rather that, since last_iMCU_row is
unsigned, (last_iMCU_row - 1) wrapped around to 0xFFFFFFFF when
last_iMCU_row was 0.  This caused the interblock smoothing algorithm
introduced in 6d91e95 to erroneously
try to access the next two iMCU rows, neither of which existed.  The
first attempt at a fix (4dbc293)
exposed a NULL dereference, detected by OSS-Fuzz, that occurred when
attempting to decompress a specially-crafted malformed JPEG image to a
YUV buffer using tjDecompressToYUV*() with 1/4 IDCT scaling.

Fixes #613 (again)
Also fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=49898
  • Loading branch information
dcommander committed Aug 8, 2022
1 parent 9f8f683 commit 2e136a7
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 12 deletions.
7 changes: 4 additions & 3 deletions ChangeLog.md
Expand Up @@ -18,9 +18,10 @@ This allows both AltiVec-equipped (PowerPC G4 and G5) and non-AltiVec-equipped
(PowerPC G3) CPUs to be supported using the same build of libjpeg-turbo.

4. Fixed an error ("Bogus virtual array access") that occurred when attempting
to decompress a progressive JPEG image with a height less than or equal to
(32 * the vertical sampling factor) using buffered image mode. This was a
regression introduced by 2.1 beta1[6(b)].
to decompress a progressive JPEG image with a height less than or equal to one
iMCU (8 * the vertical sampling factor) using buffered-image mode with
interblock smoothing enabled. This was a regression introduced by
2.1 beta1[6(b)].


2.1.3
Expand Down
15 changes: 6 additions & 9 deletions jdcoefct.c
Expand Up @@ -475,7 +475,7 @@ decompress_smooth_data(j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
if (!compptr->component_needed)
continue;
/* Count non-dummy DCT block rows in this iMCU row. */
if (cinfo->output_iMCU_row < last_iMCU_row - 1) {
if (cinfo->output_iMCU_row + 1 < last_iMCU_row) {
block_rows = compptr->v_samp_factor;
access_rows = block_rows * 3; /* this and next two iMCU rows */
} else if (cinfo->output_iMCU_row < last_iMCU_row) {
Expand Down Expand Up @@ -560,7 +560,7 @@ decompress_smooth_data(j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
next_block_row = buffer_ptr;

if (block_row < block_rows - 2 ||
cinfo->output_iMCU_row < last_iMCU_row - 1)
cinfo->output_iMCU_row + 1 < last_iMCU_row)
next_next_block_row =
buffer[block_row + 2] + cinfo->master->first_MCU_col[ci];
else
Expand Down Expand Up @@ -835,21 +835,18 @@ jinit_d_coef_controller(j_decompress_ptr cinfo, boolean need_full_buffer)

for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
JDIMENSION num_rows =
(JDIMENSION)jround_up((long)compptr->height_in_blocks,
(long)compptr->v_samp_factor);
access_rows = compptr->v_samp_factor;
#ifdef BLOCK_SMOOTHING_SUPPORTED
/* If block smoothing could be used, need a bigger window */
if (cinfo->progressive_mode) {
if (cinfo->progressive_mode)
access_rows *= 5;
num_rows = MAX(num_rows, (JDIMENSION)access_rows);
}
#endif
coef->whole_image[ci] = (*cinfo->mem->request_virt_barray)
((j_common_ptr)cinfo, JPOOL_IMAGE, TRUE,
(JDIMENSION)jround_up((long)compptr->width_in_blocks,
(long)compptr->h_samp_factor), num_rows,
(long)compptr->h_samp_factor),
(JDIMENSION)jround_up((long)compptr->height_in_blocks,
(long)compptr->v_samp_factor),
(JDIMENSION)access_rows);
}
coef->pub.consume_data = consume_data;
Expand Down

0 comments on commit 2e136a7

Please sign in to comment.