diff --git a/ChangeLog.md b/ChangeLog.md index ed410210..643d9e64 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -19,6 +19,11 @@ was previously enabled in a libjpeg or TurboJPEG instance. instance, and setting `TJPARAM_LOSSLESS`/`TJ.PARAM_LOSSLESS` to `0` now 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 ===== diff --git a/jcapimin.c b/jcapimin.c index cbb3d13e..7ddb09b7 100644 --- a/jcapimin.c +++ b/jcapimin.c @@ -5,7 +5,7 @@ * Copyright (C) 1994-1998, Thomas G. Lane. * Modified 2003-2010 by Guido Vollbeding. * 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 * file. * @@ -196,15 +196,21 @@ jpeg_finish_compress(j_compress_ptr cinfo) */ if (cinfo->data_precision == 16) { #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)) ERREXIT(cinfo, JERR_CANT_SUSPEND); #else ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); #endif } 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)) ERREXIT(cinfo, JERR_CANT_SUSPEND); } else { + if (cinfo->coef->compress_data == NULL) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); if (!(*cinfo->coef->compress_data) (cinfo, (JSAMPIMAGE)NULL)) ERREXIT(cinfo, JERR_CANT_SUSPEND); } diff --git a/jcapistd.c b/jcapistd.c index 2053028f..220c728d 100644 --- a/jcapistd.c +++ b/jcapistd.c @@ -4,7 +4,7 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1994-1996, Thomas G. Lane. * 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 * file. * @@ -117,6 +117,8 @@ _jpeg_write_scanlines(j_compress_ptr cinfo, _JSAMPARRAY scanlines, num_lines = rows_left; 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->next_scanline += row_ctr; return row_ctr; @@ -174,6 +176,8 @@ _jpeg_write_raw_data(j_compress_ptr cinfo, _JSAMPIMAGE data, ERREXIT(cinfo, JERR_BUFFER_SIZE); /* 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 compressor did not consume the whole row, suspend processing. */ return 0; diff --git a/jccoefct.c b/jccoefct.c index 2a5dde2d..4a47b3cb 100644 --- a/jccoefct.c +++ b/jccoefct.c @@ -4,7 +4,7 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1994-1997, Thomas G. Lane. * 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 * file. * @@ -414,6 +414,7 @@ _jinit_c_coef_controller(j_compress_ptr cinfo, boolean need_full_buffer) coef = (my_coef_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, sizeof(my_coef_controller)); + memset(coef, 0, sizeof(my_coef_controller)); cinfo->coef = (struct jpeg_c_coef_controller *)coef; coef->pub.start_pass = start_pass_coef; diff --git a/jcmainct.c b/jcmainct.c index fe8fc0b1..3db2e649 100644 --- a/jcmainct.c +++ b/jcmainct.c @@ -6,7 +6,7 @@ * Lossless JPEG Modifications: * Copyright (C) 1999, Ken Murchison. * 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 * file. * @@ -146,6 +146,7 @@ _jinit_c_main_controller(j_compress_ptr cinfo, boolean need_full_buffer) main_ptr = (my_main_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, sizeof(my_main_controller)); + memset(main_ptr, 0, sizeof(my_main_controller)); cinfo->main = (struct jpeg_c_main_controller *)main_ptr; main_ptr->pub.start_pass = start_pass_main; diff --git a/jdapistd.c b/jdapistd.c index 38da36b7..3a3aa602 100644 --- a/jdapistd.c +++ b/jdapistd.c @@ -128,20 +128,28 @@ output_pass_setup(j_decompress_ptr cinfo) } /* Process some data */ last_scanline = cinfo->output_scanline; + if (cinfo->data_precision == 16) { #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->output_scanline, (JDIMENSION)0); - else +#else + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); #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->output_scanline, (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->output_scanline, (JDIMENSION)0); + } if (cinfo->output_scanline == last_scanline) return FALSE; /* No progress made, must suspend */ } @@ -333,6 +341,8 @@ _jpeg_read_scanlines(j_decompress_ptr cinfo, _JSAMPARRAY scanlines, /* Process some data */ 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->output_scanline += row_ctr; return row_ctr; @@ -679,6 +689,8 @@ _jpeg_read_raw_data(j_decompress_ptr cinfo, _JSAMPIMAGE data, ERREXIT(cinfo, JERR_BUFFER_SIZE); /* 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)) return 0; /* suspension forced, can do nothing more */ diff --git a/jdcoefct.c b/jdcoefct.c index 40ce2725..194d5a5c 100644 --- a/jdcoefct.c +++ b/jdcoefct.c @@ -5,7 +5,7 @@ * Copyright (C) 1994-1997, Thomas G. Lane. * libjpeg-turbo Modifications: * Copyright 2009 Pierre Ossman 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. * For conditions of distribution and use, see the accompanying README.ijg * file. @@ -824,6 +824,7 @@ _jinit_d_coef_controller(j_decompress_ptr cinfo, boolean need_full_buffer) coef = (my_coef_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, sizeof(my_coef_controller)); + memset(coef, 0, sizeof(my_coef_controller)); cinfo->coef = (struct jpeg_d_coef_controller *)coef; coef->pub.start_input_pass = start_input_pass; coef->pub.start_output_pass = start_output_pass; diff --git a/jdmainct.c b/jdmainct.c index c672b4ba..4ed7a927 100644 --- a/jdmainct.c +++ b/jdmainct.c @@ -4,7 +4,7 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1994-1996, Thomas G. Lane. * 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 * file. * @@ -437,6 +437,7 @@ _jinit_d_main_controller(j_decompress_ptr cinfo, boolean need_full_buffer) main_ptr = (my_main_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, sizeof(my_main_controller)); + memset(main_ptr, 0, sizeof(my_main_controller)); cinfo->main = (struct jpeg_d_main_controller *)main_ptr; main_ptr->pub.start_pass = start_pass_main;