diff --git a/ChangeLog.md b/ChangeLog.md index a5597fad..c1690617 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -74,6 +74,11 @@ transformer (unlike the decompressor) is not generally exposed to arbitrary data exploits, and given that 12-bit-per-component builds of libjpeg-turbo are uncommon, this issue did not likely pose a security risk. +3. Fixed an issue whereby, when using a 12-bit-per-component build of +libjpeg-turbo (`-DWITH_12BIT=1`), passing samples with values greater than 4095 +or less than 0 to `jpeg_write_scanlines()` caused a buffer overrun or underrun +in the RGB-to-YCbCr color converter. + 2.1.4 ===== diff --git a/jccolext.c b/jccolext.c index 874e8fbf..c422b566 100644 --- a/jccolext.c +++ b/jccolext.c @@ -48,9 +48,9 @@ rgb_ycc_convert_internal(j_compress_ptr cinfo, _JSAMPARRAY input_buf, outptr2 = output_buf[2][output_row]; output_row++; for (col = 0; col < num_cols; col++) { - r = inptr[RGB_RED]; - g = inptr[RGB_GREEN]; - b = inptr[RGB_BLUE]; + r = RANGE_LIMIT(inptr[RGB_RED]); + g = RANGE_LIMIT(inptr[RGB_GREEN]); + b = RANGE_LIMIT(inptr[RGB_BLUE]); inptr += RGB_PIXELSIZE; /* If the inputs are 0.._MAXJSAMPLE, the outputs of these equations * must be too; we do not need an explicit range-limiting operation. @@ -100,9 +100,9 @@ rgb_gray_convert_internal(j_compress_ptr cinfo, _JSAMPARRAY input_buf, outptr = output_buf[0][output_row]; output_row++; for (col = 0; col < num_cols; col++) { - r = inptr[RGB_RED]; - g = inptr[RGB_GREEN]; - b = inptr[RGB_BLUE]; + r = RANGE_LIMIT(inptr[RGB_RED]); + g = RANGE_LIMIT(inptr[RGB_GREEN]); + b = RANGE_LIMIT(inptr[RGB_BLUE]); inptr += RGB_PIXELSIZE; /* Y */ outptr[col] = (_JSAMPLE)((ctab[r + R_Y_OFF] + ctab[g + G_Y_OFF] + diff --git a/jccolor.c b/jccolor.c index dbbcecd9..834c33fd 100644 --- a/jccolor.c +++ b/jccolor.c @@ -84,6 +84,18 @@ typedef my_color_converter *my_cconvert_ptr; #define B_CR_OFF (7 * (_MAXJSAMPLE + 1)) #define TABLE_SIZE (8 * (_MAXJSAMPLE + 1)) +/* 12-bit samples use a 16-bit data type, so it is possible to pass + * out-of-range sample values (< 0 or > 4095) to jpeg_write_scanlines(). + * Thus, we mask the incoming 12-bit samples to guard against overrunning + * or underrunning the conversion tables. + */ + +#if BITS_IN_JSAMPLE == 12 +#define RANGE_LIMIT(value) ((value) & 0xFFF) +#else +#define RANGE_LIMIT(value) (value) +#endif + /* Include inline routines for colorspace extensions */ @@ -392,9 +404,9 @@ cmyk_ycck_convert(j_compress_ptr cinfo, _JSAMPARRAY input_buf, outptr3 = output_buf[3][output_row]; output_row++; for (col = 0; col < num_cols; col++) { - r = _MAXJSAMPLE - inptr[0]; - g = _MAXJSAMPLE - inptr[1]; - b = _MAXJSAMPLE - inptr[2]; + r = _MAXJSAMPLE - RANGE_LIMIT(inptr[0]); + g = _MAXJSAMPLE - RANGE_LIMIT(inptr[1]); + b = _MAXJSAMPLE - RANGE_LIMIT(inptr[2]); /* K passes through as-is */ outptr3[col] = inptr[3]; inptr += 4;