2
1
mirror of https://github.com/qpdf/qpdf.git synced 2024-12-22 10:58:58 +00:00

Merge pull request #1222 from m-holger/fuzz2

In PL_DCT add option to limit the size of uncompressed corrupt data
This commit is contained in:
m-holger 2024-06-27 08:20:01 +01:00 committed by GitHub
commit 732aab8610
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 63 additions and 44 deletions

View File

@ -7,7 +7,7 @@ cmake_minimum_required(VERSION 3.16)
# also find the version number here. generate_auto_job also reads the # also find the version number here. generate_auto_job also reads the
# version from here. # version from here.
project(qpdf project(qpdf
VERSION 11.9.2 VERSION 11.10.0
LANGUAGES C CXX) LANGUAGES C CXX)
# Enable correct rpath handling for MacOSX # Enable correct rpath handling for MacOSX

View File

@ -27,7 +27,7 @@ void
FuzzHelper::doChecks() FuzzHelper::doChecks()
{ {
Pl_Discard discard; Pl_Discard discard;
Pl_DCT p("decode", &discard); Pl_DCT p("decode", &discard, 20'000'000);
p.write(const_cast<unsigned char*>(data), size); p.write(const_cast<unsigned char*>(data), size);
p.finish(); p.finish();
} }

View File

@ -25,13 +25,13 @@
/* The first version of qpdf to include the version constants is 10.6.0. */ /* The first version of qpdf to include the version constants is 10.6.0. */
#define QPDF_MAJOR_VERSION 11 #define QPDF_MAJOR_VERSION 11
#define QPDF_MINOR_VERSION 9 #define QPDF_MINOR_VERSION 10
#define QPDF_PATCH_VERSION 2 #define QPDF_PATCH_VERSION 0
#ifdef QPDF_FUTURE #ifdef QPDF_FUTURE
# define QPDF_VERSION "11.9.2+future" # define QPDF_VERSION "11.10.0+future"
#else #else
# define QPDF_VERSION "11.9.2" # define QPDF_VERSION "11.10.0"
#endif #endif
/* /*

View File

@ -34,6 +34,11 @@ class QPDF_DLL_CLASS Pl_DCT: public Pipeline
QPDF_DLL QPDF_DLL
Pl_DCT(char const* identifier, Pipeline* next); 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 class QPDF_DLL_CLASS CompressConfig
{ {
public: public:
@ -80,26 +85,30 @@ class QPDF_DLL_CLASS Pl_DCT: public Pipeline
~Members() = default; ~Members() = default;
private: private:
// For compression
Members( Members(
action_e action, JDIMENSION image_width,
char const* buf_description, JDIMENSION image_height,
JDIMENSION image_width = 0, int components,
JDIMENSION image_height = 0, J_COLOR_SPACE color_space,
int components = 1, CompressConfig* config_callback);
J_COLOR_SPACE color_space = JCS_GRAYSCALE, // For decompression
CompressConfig* config_callback = nullptr); Members(size_t corrupt_data_limit);
Members(Members const&) = delete; Members(Members const&) = delete;
action_e action; action_e action;
Pl_Buffer buf; Pl_Buffer buf;
// Used for compression // Used for decompression
JDIMENSION image_width; size_t corrupt_data_limit{0};
JDIMENSION image_height;
int components;
J_COLOR_SPACE color_space;
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<Members> m; std::shared_ptr<Members> m;

View File

@ -1,5 +1,5 @@
# Generated by generate_auto_job # Generated by generate_auto_job
CMakeLists.txt 085e7290a43f2cc0cbac31aeab0a571731f4c26be25a243c458d93881ef8fc3d CMakeLists.txt 47752f33b17fa526d46fc608a25ad6b8c61feba9deb1bd659fddf93e6e08b102
generate_auto_job f64733b79dcee5a0e3e8ccc6976448e8ddf0e8b6529987a66a7d3ab2ebc10a86 generate_auto_job f64733b79dcee5a0e3e8ccc6976448e8ddf0e8b6529987a66a7d3ab2ebc10a86
include/qpdf/auto_job_c_att.hh 4c2b171ea00531db54720bf49a43f8b34481586ae7fb6cbf225099ee42bc5bb4 include/qpdf/auto_job_c_att.hh 4c2b171ea00531db54720bf49a43f8b34481586ae7fb6cbf225099ee42bc5bb4
include/qpdf/auto_job_c_copy_att.hh 50609012bff14fd82f0649185940d617d05d530cdc522185c7f3920a561ccb42 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 libqpdf/qpdf/auto_job_schema.hh 5dac568dff39614e161a0af59a0f328f1e28edf69b96f08bb76fd592d51bb053
manual/_ext/qpdf.py 6add6321666031d55ed4aedf7c00e5662bba856dfcd66ccb526563bffefbb580 manual/_ext/qpdf.py 6add6321666031d55ed4aedf7c00e5662bba856dfcd66ccb526563bffefbb580
manual/cli.rst 94057baba9ecffb4ce19ae61c8fa507ef07209c280fccae97b283c3dfce834e0 manual/cli.rst 94057baba9ecffb4ce19ae61c8fa507ef07209c280fccae97b283c3dfce834e0
manual/qpdf.1 f39379c4921f4c22ba4a2ab28dcda8b1898347b149032de603fd423cbde56fe4 manual/qpdf.1 0ec05f1392c160165cdf6adada4de84c0de75bd2fb5762caff4e1372aacada4c
manual/qpdf.1.in 436ecc85d45c4c9e2dbd1725fb7f0177fb627179469f114561adf3cb6cbb677b manual/qpdf.1.in 436ecc85d45c4c9e2dbd1725fb7f0177fb627179469f114561adf3cb6cbb677b

View File

@ -1,5 +1,6 @@
#include <qpdf/Pl_DCT.hh> #include <qpdf/Pl_DCT.hh>
#include "qpdf/QPDFLogger.hh"
#include <qpdf/QIntC.hh> #include <qpdf/QIntC.hh>
#include <qpdf/QTC.hh> #include <qpdf/QTC.hh>
@ -31,16 +32,21 @@ error_handler(j_common_ptr cinfo)
longjmp(jerr->jmpbuf, 1); 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( Pl_DCT::Members::Members(
action_e action,
char const* buf_description,
JDIMENSION image_width, JDIMENSION image_width,
JDIMENSION image_height, JDIMENSION image_height,
int components, int components,
J_COLOR_SPACE color_space, J_COLOR_SPACE color_space,
CompressConfig* config_callback) : CompressConfig* config_callback) :
action(action), action(a_compress),
buf(buf_description), buf("DCT uncompressed image"),
image_width(image_width), image_width(image_width),
image_height(image_height), image_height(image_height),
components(components), components(components),
@ -50,8 +56,13 @@ Pl_DCT::Members::Members(
} }
Pl_DCT::Pl_DCT(char const* identifier, Pipeline* next) : 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), 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, J_COLOR_SPACE color_space,
CompressConfig* config_callback) : CompressConfig* config_callback) :
Pipeline(identifier, next), Pipeline(identifier, next),
m(new Members( m(new Members(image_width, image_height, components, color_space, config_callback))
a_compress,
"DCT uncompressed image",
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_read_header(cinfo, TRUE);
(void)jpeg_calc_output_dimensions(cinfo); (void)jpeg_calc_output_dimensions(cinfo);
unsigned int width = cinfo->output_width * QIntC::to_uint(cinfo->output_components); unsigned int width = cinfo->output_width * QIntC::to_uint(cinfo->output_components);
JSAMPARRAY buffer = if (cinfo->err->num_warnings == 0 || m->corrupt_data_limit == 0 ||
(*cinfo->mem->alloc_sarray)(reinterpret_cast<j_common_ptr>(cinfo), JPOOL_IMAGE, width, 1); (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<j_common_ptr>(cinfo), JPOOL_IMAGE, width, 1);
(void)jpeg_start_decompress(cinfo); (void)jpeg_start_decompress(cinfo);
while (cinfo->output_scanline < cinfo->output_height) { while (cinfo->output_scanline < cinfo->output_height) {
(void)jpeg_read_scanlines(cinfo, buffer, 1); (void)jpeg_read_scanlines(cinfo, buffer, 1);
this->getNext()->write(buffer[0], width * sizeof(buffer[0][0])); 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); getNext()->finish();
this->getNext()->finish();
} }

View File

@ -3,7 +3,7 @@
.\" Edits will be automatically overwritten if the build is .\" Edits will be automatically overwritten if the build is
.\" run in maintainer mode. .\" 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 .SH NAME
qpdf \- PDF transformation software qpdf \- PDF transformation software
.SH SYNOPSIS .SH SYNOPSIS