Ensure methods called by global funcs are init'd

If a hypothetical calling application does something really stupid and
changes cinfo->data_precision after calling jpeg_start_*compress(), then
the precision-specific methods called by jpeg_write_scanlines(),
jpeg_write_raw_data(), jpeg_finish_compress(), jpeg_read_scanlines(),
jpeg_read_raw_data(), or jpeg_start_output() may not be initialized.

Ensure that the first precision-specific method (which will always be
cinfo->main->process_data*(), cinfo->coef->compress_data*(), or
cinfo->coef->decompress_data()) called by any global function that may
be called after jpeg_start_*compress() is initialized and non-NULL.
This increases the likelihood (but does not guarantee) that a
hypothetical stupid calling application will fail gracefully rather than
segfault if it changes cinfo->data_precision after calling
jpeg_start_*compress().  A hypothetical stupid calling application can
still bork itself by changing cinfo->data_precision after initializing
the source manager but before calling jpeg_start_compress(), or after
initializing the destination manager but before calling
jpeg_start_decompress().
This commit is contained in:
DRC
2024-12-18 12:50:38 -05:00
parent 3e703af408
commit e81cb16e0f
8 changed files with 41 additions and 10 deletions

View File

@@ -19,6 +19,11 @@ was previously enabled in a libjpeg or TurboJPEG instance.
instance, and setting `TJPARAM_LOSSLESS`/`TJ.PARAM_LOSSLESS` to `0` now instance, and setting `TJPARAM_LOSSLESS`/`TJ.PARAM_LOSSLESS` to `0` now
disables lossless JPEG compression in a TurboJPEG instance. disables lossless JPEG compression in a TurboJPEG instance.
4. Hardened the libjpeg API against hypothetical calling applications that may
erroneously change the value of the `data_precision` field in
`jpeg_compress_struct` or `jpeg_decompress_struct` after calling
`jpeg_start_compress()` or `jpeg_start_decompress()`.
3.0.4 3.0.4
===== =====

View File

@@ -5,7 +5,7 @@
* Copyright (C) 1994-1998, Thomas G. Lane. * Copyright (C) 1994-1998, Thomas G. Lane.
* Modified 2003-2010 by Guido Vollbeding. * Modified 2003-2010 by Guido Vollbeding.
* libjpeg-turbo Modifications: * libjpeg-turbo Modifications:
* Copyright (C) 2022, D. R. Commander. * Copyright (C) 2022, 2024, D. R. Commander.
* For conditions of distribution and use, see the accompanying README.ijg * For conditions of distribution and use, see the accompanying README.ijg
* file. * file.
* *
@@ -196,15 +196,21 @@ jpeg_finish_compress(j_compress_ptr cinfo)
*/ */
if (cinfo->data_precision == 16) { if (cinfo->data_precision == 16) {
#ifdef C_LOSSLESS_SUPPORTED #ifdef C_LOSSLESS_SUPPORTED
if (cinfo->coef->compress_data_16 == NULL)
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
if (!(*cinfo->coef->compress_data_16) (cinfo, (J16SAMPIMAGE)NULL)) if (!(*cinfo->coef->compress_data_16) (cinfo, (J16SAMPIMAGE)NULL))
ERREXIT(cinfo, JERR_CANT_SUSPEND); ERREXIT(cinfo, JERR_CANT_SUSPEND);
#else #else
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
#endif #endif
} else if (cinfo->data_precision == 12) { } else if (cinfo->data_precision == 12) {
if (cinfo->coef->compress_data_12 == NULL)
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
if (!(*cinfo->coef->compress_data_12) (cinfo, (J12SAMPIMAGE)NULL)) if (!(*cinfo->coef->compress_data_12) (cinfo, (J12SAMPIMAGE)NULL))
ERREXIT(cinfo, JERR_CANT_SUSPEND); ERREXIT(cinfo, JERR_CANT_SUSPEND);
} else { } else {
if (cinfo->coef->compress_data == NULL)
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
if (!(*cinfo->coef->compress_data) (cinfo, (JSAMPIMAGE)NULL)) if (!(*cinfo->coef->compress_data) (cinfo, (JSAMPIMAGE)NULL))
ERREXIT(cinfo, JERR_CANT_SUSPEND); ERREXIT(cinfo, JERR_CANT_SUSPEND);
} }

View File

@@ -4,7 +4,7 @@
* This file was part of the Independent JPEG Group's software: * This file was part of the Independent JPEG Group's software:
* Copyright (C) 1994-1996, Thomas G. Lane. * Copyright (C) 1994-1996, Thomas G. Lane.
* libjpeg-turbo Modifications: * libjpeg-turbo Modifications:
* Copyright (C) 2022, D. R. Commander. * Copyright (C) 2022, 2024, D. R. Commander.
* For conditions of distribution and use, see the accompanying README.ijg * For conditions of distribution and use, see the accompanying README.ijg
* file. * file.
* *
@@ -117,6 +117,8 @@ _jpeg_write_scanlines(j_compress_ptr cinfo, _JSAMPARRAY scanlines,
num_lines = rows_left; num_lines = rows_left;
row_ctr = 0; row_ctr = 0;
if (cinfo->main->_process_data == NULL)
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
(*cinfo->main->_process_data) (cinfo, scanlines, &row_ctr, num_lines); (*cinfo->main->_process_data) (cinfo, scanlines, &row_ctr, num_lines);
cinfo->next_scanline += row_ctr; cinfo->next_scanline += row_ctr;
return row_ctr; return row_ctr;
@@ -174,6 +176,8 @@ _jpeg_write_raw_data(j_compress_ptr cinfo, _JSAMPIMAGE data,
ERREXIT(cinfo, JERR_BUFFER_SIZE); ERREXIT(cinfo, JERR_BUFFER_SIZE);
/* Directly compress the row. */ /* Directly compress the row. */
if (cinfo->coef->_compress_data == NULL)
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
if (!(*cinfo->coef->_compress_data) (cinfo, data)) { if (!(*cinfo->coef->_compress_data) (cinfo, data)) {
/* If compressor did not consume the whole row, suspend processing. */ /* If compressor did not consume the whole row, suspend processing. */
return 0; return 0;

View File

@@ -4,7 +4,7 @@
* This file was part of the Independent JPEG Group's software: * This file was part of the Independent JPEG Group's software:
* Copyright (C) 1994-1997, Thomas G. Lane. * Copyright (C) 1994-1997, Thomas G. Lane.
* libjpeg-turbo Modifications: * libjpeg-turbo Modifications:
* Copyright (C) 2022, D. R. Commander. * Copyright (C) 2022, 2024, D. R. Commander.
* For conditions of distribution and use, see the accompanying README.ijg * For conditions of distribution and use, see the accompanying README.ijg
* file. * file.
* *
@@ -414,6 +414,7 @@ _jinit_c_coef_controller(j_compress_ptr cinfo, boolean need_full_buffer)
coef = (my_coef_ptr) coef = (my_coef_ptr)
(*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(my_coef_controller)); sizeof(my_coef_controller));
memset(coef, 0, sizeof(my_coef_controller));
cinfo->coef = (struct jpeg_c_coef_controller *)coef; cinfo->coef = (struct jpeg_c_coef_controller *)coef;
coef->pub.start_pass = start_pass_coef; coef->pub.start_pass = start_pass_coef;

View File

@@ -6,7 +6,7 @@
* Lossless JPEG Modifications: * Lossless JPEG Modifications:
* Copyright (C) 1999, Ken Murchison. * Copyright (C) 1999, Ken Murchison.
* libjpeg-turbo Modifications: * libjpeg-turbo Modifications:
* Copyright (C) 2022, D. R. Commander. * Copyright (C) 2022, 2024, D. R. Commander.
* For conditions of distribution and use, see the accompanying README.ijg * For conditions of distribution and use, see the accompanying README.ijg
* file. * file.
* *
@@ -146,6 +146,7 @@ _jinit_c_main_controller(j_compress_ptr cinfo, boolean need_full_buffer)
main_ptr = (my_main_ptr) main_ptr = (my_main_ptr)
(*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(my_main_controller)); sizeof(my_main_controller));
memset(main_ptr, 0, sizeof(my_main_controller));
cinfo->main = (struct jpeg_c_main_controller *)main_ptr; cinfo->main = (struct jpeg_c_main_controller *)main_ptr;
main_ptr->pub.start_pass = start_pass_main; main_ptr->pub.start_pass = start_pass_main;

View File

@@ -128,20 +128,28 @@ output_pass_setup(j_decompress_ptr cinfo)
} }
/* Process some data */ /* Process some data */
last_scanline = cinfo->output_scanline; last_scanline = cinfo->output_scanline;
if (cinfo->data_precision == 16) {
#ifdef D_LOSSLESS_SUPPORTED #ifdef D_LOSSLESS_SUPPORTED
if (cinfo->data_precision == 16) if (cinfo->main->process_data_16 == NULL)
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
(*cinfo->main->process_data_16) (cinfo, (J16SAMPARRAY)NULL, (*cinfo->main->process_data_16) (cinfo, (J16SAMPARRAY)NULL,
&cinfo->output_scanline, &cinfo->output_scanline,
(JDIMENSION)0); (JDIMENSION)0);
else #else
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
#endif #endif
if (cinfo->data_precision == 12) } else if (cinfo->data_precision == 12) {
if (cinfo->main->process_data_12 == NULL)
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
(*cinfo->main->process_data_12) (cinfo, (J12SAMPARRAY)NULL, (*cinfo->main->process_data_12) (cinfo, (J12SAMPARRAY)NULL,
&cinfo->output_scanline, &cinfo->output_scanline,
(JDIMENSION)0); (JDIMENSION)0);
else } else {
if (cinfo->main->process_data == NULL)
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
(*cinfo->main->process_data) (cinfo, (JSAMPARRAY)NULL, (*cinfo->main->process_data) (cinfo, (JSAMPARRAY)NULL,
&cinfo->output_scanline, (JDIMENSION)0); &cinfo->output_scanline, (JDIMENSION)0);
}
if (cinfo->output_scanline == last_scanline) if (cinfo->output_scanline == last_scanline)
return FALSE; /* No progress made, must suspend */ return FALSE; /* No progress made, must suspend */
} }
@@ -333,6 +341,8 @@ _jpeg_read_scanlines(j_decompress_ptr cinfo, _JSAMPARRAY scanlines,
/* Process some data */ /* Process some data */
row_ctr = 0; row_ctr = 0;
if (cinfo->main->_process_data == NULL)
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
(*cinfo->main->_process_data) (cinfo, scanlines, &row_ctr, max_lines); (*cinfo->main->_process_data) (cinfo, scanlines, &row_ctr, max_lines);
cinfo->output_scanline += row_ctr; cinfo->output_scanline += row_ctr;
return row_ctr; return row_ctr;
@@ -679,6 +689,8 @@ _jpeg_read_raw_data(j_decompress_ptr cinfo, _JSAMPIMAGE data,
ERREXIT(cinfo, JERR_BUFFER_SIZE); ERREXIT(cinfo, JERR_BUFFER_SIZE);
/* Decompress directly into user's buffer. */ /* Decompress directly into user's buffer. */
if (cinfo->coef->_decompress_data == NULL)
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
if (!(*cinfo->coef->_decompress_data) (cinfo, data)) if (!(*cinfo->coef->_decompress_data) (cinfo, data))
return 0; /* suspension forced, can do nothing more */ return 0; /* suspension forced, can do nothing more */

View File

@@ -5,7 +5,7 @@
* Copyright (C) 1994-1997, Thomas G. Lane. * Copyright (C) 1994-1997, Thomas G. Lane.
* libjpeg-turbo Modifications: * libjpeg-turbo Modifications:
* Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB * Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
* Copyright (C) 2010, 2015-2016, 2019-2020, 2022-2023, D. R. Commander. * Copyright (C) 2010, 2015-2016, 2019-2020, 2022-2024, D. R. Commander.
* Copyright (C) 2015, 2020, Google, Inc. * Copyright (C) 2015, 2020, Google, Inc.
* For conditions of distribution and use, see the accompanying README.ijg * For conditions of distribution and use, see the accompanying README.ijg
* file. * file.
@@ -824,6 +824,7 @@ _jinit_d_coef_controller(j_decompress_ptr cinfo, boolean need_full_buffer)
coef = (my_coef_ptr) coef = (my_coef_ptr)
(*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(my_coef_controller)); sizeof(my_coef_controller));
memset(coef, 0, sizeof(my_coef_controller));
cinfo->coef = (struct jpeg_d_coef_controller *)coef; cinfo->coef = (struct jpeg_d_coef_controller *)coef;
coef->pub.start_input_pass = start_input_pass; coef->pub.start_input_pass = start_input_pass;
coef->pub.start_output_pass = start_output_pass; coef->pub.start_output_pass = start_output_pass;

View File

@@ -4,7 +4,7 @@
* This file was part of the Independent JPEG Group's software: * This file was part of the Independent JPEG Group's software:
* Copyright (C) 1994-1996, Thomas G. Lane. * Copyright (C) 1994-1996, Thomas G. Lane.
* libjpeg-turbo Modifications: * libjpeg-turbo Modifications:
* Copyright (C) 2010, 2016, 2022, D. R. Commander. * Copyright (C) 2010, 2016, 2022, 2024, D. R. Commander.
* For conditions of distribution and use, see the accompanying README.ijg * For conditions of distribution and use, see the accompanying README.ijg
* file. * file.
* *
@@ -437,6 +437,7 @@ _jinit_d_main_controller(j_decompress_ptr cinfo, boolean need_full_buffer)
main_ptr = (my_main_ptr) main_ptr = (my_main_ptr)
(*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(my_main_controller)); sizeof(my_main_controller));
memset(main_ptr, 0, sizeof(my_main_controller));
cinfo->main = (struct jpeg_d_main_controller *)main_ptr; cinfo->main = (struct jpeg_d_main_controller *)main_ptr;
main_ptr->pub.start_pass = start_pass_main; main_ptr->pub.start_pass = start_pass_main;