jchuff.c: Test for out-of-range coefficients
Restore two coefficient range checks from libjpeg to the C baseline Huffman encoder. This fixes an issue (https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=60253) whereby the encoder could read from uninitialized memory when attempting to transform a specially-crafted malformed arithmetic-coded JPEG source image into a baseline Huffman-coded JPEG destination image with default Huffman tables. More specifically, the out-of-range coefficients caused r to equal 256, which overflowed the actbl->ehufsi[] array. Because the overflow was contained within the huff_entropy_encoder structure, this issue was not exploitable (nor was it observable at all on x86 or Arm CPUs unless JSIMD_NOHUFFENC=1 or JSIMD_FORCENONE=1 was set in the environment or unless libjpeg-turbo was built with WITH_SIMD=0.) The fix is performance-neutral (+/- 1-2%) for x86-64 code and causes a 0-4% (avg. 1-2%, +/- 1-2%) compression regression for i386 code on Intel CPUs when the C baseline Huffman encoder is used (JSIMD_NOHUFFENC=1). The fix is performance-neutral (+/- 1-2%) on Intel CPUs when all of the libjpeg-turbo SIMD extensions are disabled (JSIMD_FORCENONE=1). The fix causes a 0-2% (avg. <1%, +/- 1%) compression regression for PowerPC code.
This commit is contained in:
@@ -55,6 +55,11 @@ metadata unless automatic JPEG destination buffer (re)allocation is used or
|
||||
`-map` option from working when decompressing 12-bit-per-component lossy JPEG
|
||||
images.
|
||||
|
||||
7. Fixed an issue that caused the C Huffman encoder (which is not used by
|
||||
default on x86 and Arm CPUs) to read from uninitialized memory when attempting
|
||||
to transform a specially-crafted malformed arithmetic-coded JPEG source image
|
||||
into a baseline Huffman-coded JPEG destination image.
|
||||
|
||||
|
||||
2.1.91 (3.0 beta2)
|
||||
==================
|
||||
|
||||
11
jchuff.c
11
jchuff.c
@@ -6,7 +6,7 @@
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* libjpeg-turbo Modifications:
|
||||
* Copyright (C) 2009-2011, 2014-2016, 2018-2022, D. R. Commander.
|
||||
* Copyright (C) 2009-2011, 2014-2016, 2018-2023, D. R. Commander.
|
||||
* Copyright (C) 2015, Matthieu Darbois.
|
||||
* Copyright (C) 2018, Matthias Räncker.
|
||||
* Copyright (C) 2020, Arm Limited.
|
||||
@@ -584,6 +584,7 @@ encode_one_block(working_state *state, JCOEFPTR block, int last_dc_val,
|
||||
bit_buf_type put_buffer;
|
||||
JOCTET _buffer[BUFSIZE], *buffer;
|
||||
int localbuf = 0;
|
||||
int max_coef_bits = state->cinfo->data_precision + 2;
|
||||
|
||||
free_bits = state->cur.free_bits;
|
||||
put_buffer = state->cur.put_buffer.c;
|
||||
@@ -604,6 +605,11 @@ encode_one_block(working_state *state, JCOEFPTR block, int last_dc_val,
|
||||
|
||||
/* Find the number of bits needed for the magnitude of the coefficient */
|
||||
nbits = JPEG_NBITS(nbits);
|
||||
/* Check for out-of-range coefficient values.
|
||||
* Since we're encoding a difference, the range limit is twice as much.
|
||||
*/
|
||||
if (nbits > max_coef_bits + 1)
|
||||
ERREXIT(state->cinfo, JERR_BAD_DCT_COEF);
|
||||
|
||||
/* Emit the Huffman-coded symbol for the number of bits.
|
||||
* Emit that number of bits of the value, if positive,
|
||||
@@ -629,6 +635,9 @@ encode_one_block(working_state *state, JCOEFPTR block, int last_dc_val,
|
||||
temp += nbits; \
|
||||
nbits ^= temp; \
|
||||
nbits = JPEG_NBITS_NONZERO(nbits); \
|
||||
/* Check for out-of-range coefficient values */ \
|
||||
if (nbits > max_coef_bits) \
|
||||
ERREXIT(state->cinfo, JERR_BAD_DCT_COEF); \
|
||||
/* if run length > 15, must emit special run-length-16 codes (0xF0) */ \
|
||||
while (r >= 16 * 16) { \
|
||||
r -= 16 * 16; \
|
||||
|
||||
Reference in New Issue
Block a user