Commit 732aab86107e17770e1aedc2686411d1aa337839

Authored by m-holger
Committed by GitHub
2 parents 3d569e21 d83cf438

Merge pull request #1222 from m-holger/fuzz2

In PL_DCT add option to limit the size of uncompressed corrupt data
CMakeLists.txt
@@ -7,7 +7,7 @@ cmake_minimum_required(VERSION 3.16) @@ -7,7 +7,7 @@ cmake_minimum_required(VERSION 3.16)
7 # also find the version number here. generate_auto_job also reads the 7 # also find the version number here. generate_auto_job also reads the
8 # version from here. 8 # version from here.
9 project(qpdf 9 project(qpdf
10 - VERSION 11.9.2 10 + VERSION 11.10.0
11 LANGUAGES C CXX) 11 LANGUAGES C CXX)
12 12
13 # Enable correct rpath handling for MacOSX 13 # Enable correct rpath handling for MacOSX
fuzz/dct_fuzzer.cc
@@ -27,7 +27,7 @@ void @@ -27,7 +27,7 @@ void
27 FuzzHelper::doChecks() 27 FuzzHelper::doChecks()
28 { 28 {
29 Pl_Discard discard; 29 Pl_Discard discard;
30 - Pl_DCT p("decode", &discard); 30 + Pl_DCT p("decode", &discard, 20'000'000);
31 p.write(const_cast<unsigned char*>(data), size); 31 p.write(const_cast<unsigned char*>(data), size);
32 p.finish(); 32 p.finish();
33 } 33 }
include/qpdf/DLL.h
@@ -25,13 +25,13 @@ @@ -25,13 +25,13 @@
25 25
26 /* The first version of qpdf to include the version constants is 10.6.0. */ 26 /* The first version of qpdf to include the version constants is 10.6.0. */
27 #define QPDF_MAJOR_VERSION 11 27 #define QPDF_MAJOR_VERSION 11
28 -#define QPDF_MINOR_VERSION 9  
29 -#define QPDF_PATCH_VERSION 2 28 +#define QPDF_MINOR_VERSION 10
  29 +#define QPDF_PATCH_VERSION 0
30 30
31 #ifdef QPDF_FUTURE 31 #ifdef QPDF_FUTURE
32 -# define QPDF_VERSION "11.9.2+future" 32 +# define QPDF_VERSION "11.10.0+future"
33 #else 33 #else
34 -# define QPDF_VERSION "11.9.2" 34 +# define QPDF_VERSION "11.10.0"
35 #endif 35 #endif
36 36
37 /* 37 /*
include/qpdf/Pl_DCT.hh
@@ -34,6 +34,11 @@ class QPDF_DLL_CLASS Pl_DCT: public Pipeline @@ -34,6 +34,11 @@ class QPDF_DLL_CLASS Pl_DCT: public Pipeline
34 QPDF_DLL 34 QPDF_DLL
35 Pl_DCT(char const* identifier, Pipeline* next); 35 Pl_DCT(char const* identifier, Pipeline* next);
36 36
  37 + // Constructor for decompressing image data. If corrupt_data_limit is non-zero and the data is
  38 + // corrupt, only attempt to uncompress if the uncompressed size is less than corrupt_data_limit.
  39 + QPDF_DLL
  40 + Pl_DCT(char const* identifier, Pipeline* next, size_t corrupt_data_limit);
  41 +
37 class QPDF_DLL_CLASS CompressConfig 42 class QPDF_DLL_CLASS CompressConfig
38 { 43 {
39 public: 44 public:
@@ -80,26 +85,30 @@ class QPDF_DLL_CLASS Pl_DCT: public Pipeline @@ -80,26 +85,30 @@ class QPDF_DLL_CLASS Pl_DCT: public Pipeline
80 ~Members() = default; 85 ~Members() = default;
81 86
82 private: 87 private:
  88 + // For compression
83 Members( 89 Members(
84 - action_e action,  
85 - char const* buf_description,  
86 - JDIMENSION image_width = 0,  
87 - JDIMENSION image_height = 0,  
88 - int components = 1,  
89 - J_COLOR_SPACE color_space = JCS_GRAYSCALE,  
90 - CompressConfig* config_callback = nullptr); 90 + JDIMENSION image_width,
  91 + JDIMENSION image_height,
  92 + int components,
  93 + J_COLOR_SPACE color_space,
  94 + CompressConfig* config_callback);
  95 + // For decompression
  96 + Members(size_t corrupt_data_limit);
91 Members(Members const&) = delete; 97 Members(Members const&) = delete;
92 98
93 action_e action; 99 action_e action;
94 Pl_Buffer buf; 100 Pl_Buffer buf;
95 101
  102 + // Used for decompression
  103 + size_t corrupt_data_limit{0};
  104 +
96 // Used for compression 105 // Used for compression
97 - JDIMENSION image_width;  
98 - JDIMENSION image_height;  
99 - int components;  
100 - J_COLOR_SPACE color_space; 106 + JDIMENSION image_width{0};
  107 + JDIMENSION image_height{0};
  108 + int components{1};
  109 + J_COLOR_SPACE color_space{JCS_GRAYSCALE};
101 110
102 - CompressConfig* config_callback; 111 + CompressConfig* config_callback{nullptr};
103 }; 112 };
104 113
105 std::shared_ptr<Members> m; 114 std::shared_ptr<Members> m;
job.sums
1 # Generated by generate_auto_job 1 # Generated by generate_auto_job
2 -CMakeLists.txt 085e7290a43f2cc0cbac31aeab0a571731f4c26be25a243c458d93881ef8fc3d 2 +CMakeLists.txt 47752f33b17fa526d46fc608a25ad6b8c61feba9deb1bd659fddf93e6e08b102
3 generate_auto_job f64733b79dcee5a0e3e8ccc6976448e8ddf0e8b6529987a66a7d3ab2ebc10a86 3 generate_auto_job f64733b79dcee5a0e3e8ccc6976448e8ddf0e8b6529987a66a7d3ab2ebc10a86
4 include/qpdf/auto_job_c_att.hh 4c2b171ea00531db54720bf49a43f8b34481586ae7fb6cbf225099ee42bc5bb4 4 include/qpdf/auto_job_c_att.hh 4c2b171ea00531db54720bf49a43f8b34481586ae7fb6cbf225099ee42bc5bb4
5 include/qpdf/auto_job_c_copy_att.hh 50609012bff14fd82f0649185940d617d05d530cdc522185c7f3920a561ccb42 5 include/qpdf/auto_job_c_copy_att.hh 50609012bff14fd82f0649185940d617d05d530cdc522185c7f3920a561ccb42
@@ -16,5 +16,5 @@ libqpdf/qpdf/auto_job_json_init.hh a87256c082427ec0318223762472970b2eced535c0c8b @@ -16,5 +16,5 @@ libqpdf/qpdf/auto_job_json_init.hh a87256c082427ec0318223762472970b2eced535c0c8b
16 libqpdf/qpdf/auto_job_schema.hh 5dac568dff39614e161a0af59a0f328f1e28edf69b96f08bb76fd592d51bb053 16 libqpdf/qpdf/auto_job_schema.hh 5dac568dff39614e161a0af59a0f328f1e28edf69b96f08bb76fd592d51bb053
17 manual/_ext/qpdf.py 6add6321666031d55ed4aedf7c00e5662bba856dfcd66ccb526563bffefbb580 17 manual/_ext/qpdf.py 6add6321666031d55ed4aedf7c00e5662bba856dfcd66ccb526563bffefbb580
18 manual/cli.rst 94057baba9ecffb4ce19ae61c8fa507ef07209c280fccae97b283c3dfce834e0 18 manual/cli.rst 94057baba9ecffb4ce19ae61c8fa507ef07209c280fccae97b283c3dfce834e0
19 -manual/qpdf.1 f39379c4921f4c22ba4a2ab28dcda8b1898347b149032de603fd423cbde56fe4 19 +manual/qpdf.1 0ec05f1392c160165cdf6adada4de84c0de75bd2fb5762caff4e1372aacada4c
20 manual/qpdf.1.in 436ecc85d45c4c9e2dbd1725fb7f0177fb627179469f114561adf3cb6cbb677b 20 manual/qpdf.1.in 436ecc85d45c4c9e2dbd1725fb7f0177fb627179469f114561adf3cb6cbb677b
libqpdf/Pl_DCT.cc
1 #include <qpdf/Pl_DCT.hh> 1 #include <qpdf/Pl_DCT.hh>
2 2
  3 +#include "qpdf/QPDFLogger.hh"
3 #include <qpdf/QIntC.hh> 4 #include <qpdf/QIntC.hh>
4 #include <qpdf/QTC.hh> 5 #include <qpdf/QTC.hh>
5 6
@@ -31,16 +32,21 @@ error_handler(j_common_ptr cinfo) @@ -31,16 +32,21 @@ error_handler(j_common_ptr cinfo)
31 longjmp(jerr->jmpbuf, 1); 32 longjmp(jerr->jmpbuf, 1);
32 } 33 }
33 34
  35 +Pl_DCT::Members::Members(size_t corrupt_data_limit) :
  36 + action(a_decompress),
  37 + buf("DCT compressed image"),
  38 + corrupt_data_limit(corrupt_data_limit)
  39 +{
  40 +}
  41 +
34 Pl_DCT::Members::Members( 42 Pl_DCT::Members::Members(
35 - action_e action,  
36 - char const* buf_description,  
37 JDIMENSION image_width, 43 JDIMENSION image_width,
38 JDIMENSION image_height, 44 JDIMENSION image_height,
39 int components, 45 int components,
40 J_COLOR_SPACE color_space, 46 J_COLOR_SPACE color_space,
41 CompressConfig* config_callback) : 47 CompressConfig* config_callback) :
42 - action(action),  
43 - buf(buf_description), 48 + action(a_compress),
  49 + buf("DCT uncompressed image"),
44 image_width(image_width), 50 image_width(image_width),
45 image_height(image_height), 51 image_height(image_height),
46 components(components), 52 components(components),
@@ -50,8 +56,13 @@ Pl_DCT::Members::Members( @@ -50,8 +56,13 @@ Pl_DCT::Members::Members(
50 } 56 }
51 57
52 Pl_DCT::Pl_DCT(char const* identifier, Pipeline* next) : 58 Pl_DCT::Pl_DCT(char const* identifier, Pipeline* next) :
  59 + Pl_DCT(identifier, next, 0)
  60 +{
  61 +}
  62 +
  63 +Pl_DCT::Pl_DCT(char const* identifier, Pipeline* next, size_t corrupt_data_limit) :
53 Pipeline(identifier, next), 64 Pipeline(identifier, next),
54 - m(new Members(a_decompress, "DCT compressed image")) 65 + m(new Members(corrupt_data_limit))
55 { 66 {
56 } 67 }
57 68
@@ -64,14 +75,7 @@ Pl_DCT::Pl_DCT( @@ -64,14 +75,7 @@ Pl_DCT::Pl_DCT(
64 J_COLOR_SPACE color_space, 75 J_COLOR_SPACE color_space,
65 CompressConfig* config_callback) : 76 CompressConfig* config_callback) :
66 Pipeline(identifier, next), 77 Pipeline(identifier, next),
67 - m(new Members(  
68 - a_compress,  
69 - "DCT uncompressed image",  
70 - image_width,  
71 - image_height,  
72 - components,  
73 - color_space,  
74 - config_callback)) 78 + m(new Members(image_width, image_height, components, color_space, config_callback))
75 { 79 {
76 } 80 }
77 81
@@ -311,16 +315,22 @@ Pl_DCT::decompress(void* cinfo_p, Buffer* b) @@ -311,16 +315,22 @@ Pl_DCT::decompress(void* cinfo_p, Buffer* b)
311 315
312 (void)jpeg_read_header(cinfo, TRUE); 316 (void)jpeg_read_header(cinfo, TRUE);
313 (void)jpeg_calc_output_dimensions(cinfo); 317 (void)jpeg_calc_output_dimensions(cinfo);
314 -  
315 unsigned int width = cinfo->output_width * QIntC::to_uint(cinfo->output_components); 318 unsigned int width = cinfo->output_width * QIntC::to_uint(cinfo->output_components);
316 - JSAMPARRAY buffer =  
317 - (*cinfo->mem->alloc_sarray)(reinterpret_cast<j_common_ptr>(cinfo), JPOOL_IMAGE, width, 1);  
318 -  
319 - (void)jpeg_start_decompress(cinfo);  
320 - while (cinfo->output_scanline < cinfo->output_height) {  
321 - (void)jpeg_read_scanlines(cinfo, buffer, 1);  
322 - this->getNext()->write(buffer[0], width * sizeof(buffer[0][0])); 319 + if (cinfo->err->num_warnings == 0 || m->corrupt_data_limit == 0 ||
  320 + (width * QIntC::to_uint(cinfo->output_height)) < m->corrupt_data_limit) {
  321 + // err->num_warnings is the number of corrupt data warnings emitted.
  322 + // err->msg_code could also be the code of an informational message.
  323 + JSAMPARRAY buffer = (*cinfo->mem->alloc_sarray)(
  324 + reinterpret_cast<j_common_ptr>(cinfo), JPOOL_IMAGE, width, 1);
  325 +
  326 + (void)jpeg_start_decompress(cinfo);
  327 + while (cinfo->output_scanline < cinfo->output_height) {
  328 + (void)jpeg_read_scanlines(cinfo, buffer, 1);
  329 + getNext()->write(buffer[0], width * sizeof(buffer[0][0]));
  330 + }
  331 + (void)jpeg_finish_decompress(cinfo);
  332 + } else {
  333 + *QPDFLogger::defaultLogger()->getError() << "corrupt JPEG data ignored" << "\n";
323 } 334 }
324 - (void)jpeg_finish_decompress(cinfo);  
325 - this->getNext()->finish(); 335 + getNext()->finish();
326 } 336 }
manual/qpdf.1
@@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
3 .\" Edits will be automatically overwritten if the build is 3 .\" Edits will be automatically overwritten if the build is
4 .\" run in maintainer mode. 4 .\" run in maintainer mode.
5 .\" 5 .\"
6 -.TH QPDF "1" "" "qpdf version 11.9.2" "User Commands" 6 +.TH QPDF "1" "" "qpdf version 11.10.0" "User Commands"
7 .SH NAME 7 .SH NAME
8 qpdf \- PDF transformation software 8 qpdf \- PDF transformation software
9 .SH SYNOPSIS 9 .SH SYNOPSIS