Compressor: Guard against 0 in quantization tables ... which could cause compute_reciprocal() to divide by 0. (Minimally, that is undefined behavior, and on some platforms it will trigger a floating point exception.) The most direct way to trigger the issue is by manually modifying the exposed quantization table values in jpeg_compress_struct just before calling jpeg_start_compress(). However, referring to #862, a more indirect way involves using jpeg_read_header() to read a malformed JPEG header containing quantization tables with values of 0, calling jpeg_copy_critical_parameters() to transfer those quantization tables into a compressor instance, and calling jpeg_start_compress(). In both cases, the calling program is abusing the API: - Applications are supposed to call jpeg_add_quant_table() to pass custom quantization tables to the compressor, and jpeg_add_quant_table() clamps all values < 1. - jpeg_copy_critical_parameters() is generally only used with transcoding. Using it with jpeg_start_compress() is only valid when the application intends to reuse quantization tables from a tables-only datastream, in which case the application must carefully control the datastream (as opposed to reading arbitrary data) in order to generate a valid image. Fixes #862
diff --git a/ChangeLog.md b/ChangeLog.md index 8293dd0..034fd23 100644 --- a/ChangeLog.md +++ b/ChangeLog.md
@@ -120,6 +120,12 @@ erroneously call `tjCompress*()` or `tjTransform()` with a reused JPEG destination buffer pointer while specifying a destination buffer size of 0. +19. Hardened the libjpeg API against hypothetical applications that may +erroneously set one of the exposed quantization table values to 0 just before +calling `jpeg_start_compress()`. (This would never happen in a +correctly-written program, because `jpeg_add_quant_table()` clamps all values +less than 1.) + 2.0.8 ESR =========
diff --git a/jcdctmgr.c b/jcdctmgr.c index c04058e..08ddc75 100644 --- a/jcdctmgr.c +++ b/jcdctmgr.c
@@ -6,7 +6,7 @@ * libjpeg-turbo Modifications: * Copyright (C) 1999-2006, MIYASAKA Masaru. * Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB - * Copyright (C) 2011, 2014-2015, D. R. Commander. + * Copyright (C) 2011, 2014-2015, 2026, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -176,11 +176,17 @@ UDCTELEM c; int b, r; - if (divisor == 1) { + if (divisor <= 1) { /* divisor == 1 means unquantized, so these reciprocal/correction/shift * values will cause the C quantization algorithm to act like the * identity function. Since only the C quantization algorithm is used in * these cases, the scale value is irrelevant. + * + * divisor == 0 can never happen in a normal program, because + * jpeg_add_quant_table() clamps values < 1. However, a program could + * abuse the API by manually modifying the exposed quantization table just + * before calling jpeg_start_compress(). Thus, we effectively clamp + * values < 1 here as well, to avoid dividing by 0. */ dtbl[DCTSIZE2 * 0] = (DCTELEM)1; /* reciprocal */ dtbl[DCTSIZE2 * 1] = (DCTELEM)0; /* correction */