diff --git a/CMakeLists.txt b/CMakeLists.txt index fc50ea22..6caba84f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,7 +7,7 @@ cmake_minimum_required(VERSION 3.16) # also find the version number here. generate_auto_job also reads the # version from here. project(qpdf - VERSION 11.9.2 + VERSION 11.10.0 LANGUAGES C CXX) # Enable correct rpath handling for MacOSX diff --git a/fuzz/dct_fuzzer.cc b/fuzz/dct_fuzzer.cc index 6e42ef6d..54ca730c 100644 --- a/fuzz/dct_fuzzer.cc +++ b/fuzz/dct_fuzzer.cc @@ -27,7 +27,7 @@ void FuzzHelper::doChecks() { Pl_Discard discard; - Pl_DCT p("decode", &discard); + Pl_DCT p("decode", &discard, 20'000'000); p.write(const_cast(data), size); p.finish(); } diff --git a/include/qpdf/DLL.h b/include/qpdf/DLL.h index 9ce953b5..2a97969c 100644 --- a/include/qpdf/DLL.h +++ b/include/qpdf/DLL.h @@ -25,13 +25,13 @@ /* The first version of qpdf to include the version constants is 10.6.0. */ #define QPDF_MAJOR_VERSION 11 -#define QPDF_MINOR_VERSION 9 -#define QPDF_PATCH_VERSION 2 +#define QPDF_MINOR_VERSION 10 +#define QPDF_PATCH_VERSION 0 #ifdef QPDF_FUTURE -# define QPDF_VERSION "11.9.2+future" +# define QPDF_VERSION "11.10.0+future" #else -# define QPDF_VERSION "11.9.2" +# define QPDF_VERSION "11.10.0" #endif /* diff --git a/include/qpdf/Pl_DCT.hh b/include/qpdf/Pl_DCT.hh index 0f5466f6..5d77db51 100644 --- a/include/qpdf/Pl_DCT.hh +++ b/include/qpdf/Pl_DCT.hh @@ -34,6 +34,11 @@ class QPDF_DLL_CLASS Pl_DCT: public Pipeline QPDF_DLL Pl_DCT(char const* identifier, Pipeline* next); + // Constructor for decompressing image data. If corrupt_data_limit is non-zero and the data is + // corrupt, only attempt to uncompress if the uncompressed size is less than corrupt_data_limit. + QPDF_DLL + Pl_DCT(char const* identifier, Pipeline* next, size_t corrupt_data_limit); + class QPDF_DLL_CLASS CompressConfig { public: @@ -80,26 +85,30 @@ class QPDF_DLL_CLASS Pl_DCT: public Pipeline ~Members() = default; private: + // For compression Members( - action_e action, - char const* buf_description, - JDIMENSION image_width = 0, - JDIMENSION image_height = 0, - int components = 1, - J_COLOR_SPACE color_space = JCS_GRAYSCALE, - CompressConfig* config_callback = nullptr); + JDIMENSION image_width, + JDIMENSION image_height, + int components, + J_COLOR_SPACE color_space, + CompressConfig* config_callback); + // For decompression + Members(size_t corrupt_data_limit); Members(Members const&) = delete; action_e action; Pl_Buffer buf; - // Used for compression - JDIMENSION image_width; - JDIMENSION image_height; - int components; - J_COLOR_SPACE color_space; + // Used for decompression + size_t corrupt_data_limit{0}; - CompressConfig* config_callback; + // Used for compression + JDIMENSION image_width{0}; + JDIMENSION image_height{0}; + int components{1}; + J_COLOR_SPACE color_space{JCS_GRAYSCALE}; + + CompressConfig* config_callback{nullptr}; }; std::shared_ptr m; diff --git a/job.sums b/job.sums index faabe5ae..4f53c923 100644 --- a/job.sums +++ b/job.sums @@ -1,5 +1,5 @@ # Generated by generate_auto_job -CMakeLists.txt 085e7290a43f2cc0cbac31aeab0a571731f4c26be25a243c458d93881ef8fc3d +CMakeLists.txt 47752f33b17fa526d46fc608a25ad6b8c61feba9deb1bd659fddf93e6e08b102 generate_auto_job f64733b79dcee5a0e3e8ccc6976448e8ddf0e8b6529987a66a7d3ab2ebc10a86 include/qpdf/auto_job_c_att.hh 4c2b171ea00531db54720bf49a43f8b34481586ae7fb6cbf225099ee42bc5bb4 include/qpdf/auto_job_c_copy_att.hh 50609012bff14fd82f0649185940d617d05d530cdc522185c7f3920a561ccb42 @@ -16,5 +16,5 @@ libqpdf/qpdf/auto_job_json_init.hh a87256c082427ec0318223762472970b2eced535c0c8b libqpdf/qpdf/auto_job_schema.hh 5dac568dff39614e161a0af59a0f328f1e28edf69b96f08bb76fd592d51bb053 manual/_ext/qpdf.py 6add6321666031d55ed4aedf7c00e5662bba856dfcd66ccb526563bffefbb580 manual/cli.rst 94057baba9ecffb4ce19ae61c8fa507ef07209c280fccae97b283c3dfce834e0 -manual/qpdf.1 f39379c4921f4c22ba4a2ab28dcda8b1898347b149032de603fd423cbde56fe4 +manual/qpdf.1 0ec05f1392c160165cdf6adada4de84c0de75bd2fb5762caff4e1372aacada4c manual/qpdf.1.in 436ecc85d45c4c9e2dbd1725fb7f0177fb627179469f114561adf3cb6cbb677b diff --git a/libqpdf/Pl_DCT.cc b/libqpdf/Pl_DCT.cc index 042d3977..61f3791e 100644 --- a/libqpdf/Pl_DCT.cc +++ b/libqpdf/Pl_DCT.cc @@ -1,5 +1,6 @@ #include +#include "qpdf/QPDFLogger.hh" #include #include @@ -31,16 +32,21 @@ error_handler(j_common_ptr cinfo) longjmp(jerr->jmpbuf, 1); } +Pl_DCT::Members::Members(size_t corrupt_data_limit) : + action(a_decompress), + buf("DCT compressed image"), + corrupt_data_limit(corrupt_data_limit) +{ +} + Pl_DCT::Members::Members( - action_e action, - char const* buf_description, JDIMENSION image_width, JDIMENSION image_height, int components, J_COLOR_SPACE color_space, CompressConfig* config_callback) : - action(action), - buf(buf_description), + action(a_compress), + buf("DCT uncompressed image"), image_width(image_width), image_height(image_height), components(components), @@ -50,8 +56,13 @@ Pl_DCT::Members::Members( } Pl_DCT::Pl_DCT(char const* identifier, Pipeline* next) : + Pl_DCT(identifier, next, 0) +{ +} + +Pl_DCT::Pl_DCT(char const* identifier, Pipeline* next, size_t corrupt_data_limit) : Pipeline(identifier, next), - m(new Members(a_decompress, "DCT compressed image")) + m(new Members(corrupt_data_limit)) { } @@ -64,14 +75,7 @@ Pl_DCT::Pl_DCT( J_COLOR_SPACE color_space, CompressConfig* config_callback) : Pipeline(identifier, next), - m(new Members( - a_compress, - "DCT uncompressed image", - image_width, - image_height, - components, - color_space, - config_callback)) + m(new Members(image_width, image_height, components, color_space, config_callback)) { } @@ -311,16 +315,22 @@ Pl_DCT::decompress(void* cinfo_p, Buffer* b) (void)jpeg_read_header(cinfo, TRUE); (void)jpeg_calc_output_dimensions(cinfo); - unsigned int width = cinfo->output_width * QIntC::to_uint(cinfo->output_components); - JSAMPARRAY buffer = - (*cinfo->mem->alloc_sarray)(reinterpret_cast(cinfo), JPOOL_IMAGE, width, 1); + if (cinfo->err->num_warnings == 0 || m->corrupt_data_limit == 0 || + (width * QIntC::to_uint(cinfo->output_height)) < m->corrupt_data_limit) { + // err->num_warnings is the number of corrupt data warnings emitted. + // err->msg_code could also be the code of an informational message. + JSAMPARRAY buffer = (*cinfo->mem->alloc_sarray)( + reinterpret_cast(cinfo), JPOOL_IMAGE, width, 1); - (void)jpeg_start_decompress(cinfo); - while (cinfo->output_scanline < cinfo->output_height) { - (void)jpeg_read_scanlines(cinfo, buffer, 1); - this->getNext()->write(buffer[0], width * sizeof(buffer[0][0])); + (void)jpeg_start_decompress(cinfo); + while (cinfo->output_scanline < cinfo->output_height) { + (void)jpeg_read_scanlines(cinfo, buffer, 1); + getNext()->write(buffer[0], width * sizeof(buffer[0][0])); + } + (void)jpeg_finish_decompress(cinfo); + } else { + *QPDFLogger::defaultLogger()->getError() << "corrupt JPEG data ignored" << "\n"; } - (void)jpeg_finish_decompress(cinfo); - this->getNext()->finish(); + getNext()->finish(); } diff --git a/manual/qpdf.1 b/manual/qpdf.1 index da4d677f..ec7b851b 100644 --- a/manual/qpdf.1 +++ b/manual/qpdf.1 @@ -3,7 +3,7 @@ .\" Edits will be automatically overwritten if the build is .\" run in maintainer mode. .\" -.TH QPDF "1" "" "qpdf version 11.9.2" "User Commands" +.TH QPDF "1" "" "qpdf version 11.10.0" "User Commands" .SH NAME qpdf \- PDF transformation software .SH SYNOPSIS