Commit 466169d0cb2d735fb745026ceafc7333028da045
Committed by
GitHub
Merge pull request #1350 from m-holger/fuzz
Apply sanity checks on SF_FlateLzwDecode parameters
Showing
15 changed files
with
78 additions
and
67 deletions
.git-blame-ignore-revs
| @@ -18,3 +18,5 @@ d740c6ccced02147f84a39d5e5f0984d12bac6cb | @@ -18,3 +18,5 @@ d740c6ccced02147f84a39d5e5f0984d12bac6cb | ||
| 18 | 9ae7bdea966102f9621b22192747a891078e7470 | 18 | 9ae7bdea966102f9621b22192747a891078e7470 |
| 19 | # Normalize white space in ChangeLog | 19 | # Normalize white space in ChangeLog |
| 20 | d7b909f97d3effc9540c35b0251bdf1c9abf187c | 20 | d7b909f97d3effc9540c35b0251bdf1c9abf187c |
| 21 | +# Remove 'this->' | ||
| 22 | +f5cac93ac63559ddc0aec1b1c61c9e2503c7b8e0 |
fuzz/CMakeLists.txt
| @@ -154,6 +154,7 @@ set(CORPUS_OTHER | @@ -154,6 +154,7 @@ set(CORPUS_OTHER | ||
| 154 | 389974979.fuzz | 154 | 389974979.fuzz |
| 155 | 391974927.fuzz | 155 | 391974927.fuzz |
| 156 | 394129398.fuzz | 156 | 394129398.fuzz |
| 157 | + 394463491.fuzz | ||
| 157 | ) | 158 | ) |
| 158 | 159 | ||
| 159 | set(CORPUS_DIR ${CMAKE_CURRENT_BINARY_DIR}/qpdf_corpus) | 160 | set(CORPUS_DIR ${CMAKE_CURRENT_BINARY_DIR}/qpdf_corpus) |
fuzz/qpdf_crypt_fuzzer.cc
| @@ -111,7 +111,7 @@ FuzzHelper::doChecks() | @@ -111,7 +111,7 @@ FuzzHelper::doChecks() | ||
| 111 | Pl_PNGFilter::setMemoryLimit(1'000'000); | 111 | Pl_PNGFilter::setMemoryLimit(1'000'000); |
| 112 | Pl_RunLength::setMemoryLimit(1'000'000); | 112 | Pl_RunLength::setMemoryLimit(1'000'000); |
| 113 | Pl_TIFFPredictor::setMemoryLimit(1'000'000); | 113 | Pl_TIFFPredictor::setMemoryLimit(1'000'000); |
| 114 | - Pl_Flate::setMemoryLimit(200'000); | 114 | + Pl_Flate::memory_limit(200'000); |
| 115 | 115 | ||
| 116 | // Do not decompress corrupt data. This may cause extended runtime within jpeglib without | 116 | // Do not decompress corrupt data. This may cause extended runtime within jpeglib without |
| 117 | // exercising additional code paths in qpdf, and potentially causing counterproductive timeouts. | 117 | // exercising additional code paths in qpdf, and potentially causing counterproductive timeouts. |
fuzz/qpdf_crypt_insecure_fuzzer.cc
| @@ -111,7 +111,7 @@ FuzzHelper::doChecks() | @@ -111,7 +111,7 @@ FuzzHelper::doChecks() | ||
| 111 | Pl_PNGFilter::setMemoryLimit(1'000'000); | 111 | Pl_PNGFilter::setMemoryLimit(1'000'000); |
| 112 | Pl_RunLength::setMemoryLimit(1'000'000); | 112 | Pl_RunLength::setMemoryLimit(1'000'000); |
| 113 | Pl_TIFFPredictor::setMemoryLimit(1'000'000); | 113 | Pl_TIFFPredictor::setMemoryLimit(1'000'000); |
| 114 | - Pl_Flate::setMemoryLimit(200'000); | 114 | + Pl_Flate::memory_limit(200'000); |
| 115 | 115 | ||
| 116 | // Do not decompress corrupt data. This may cause extended runtime within jpeglib without | 116 | // Do not decompress corrupt data. This may cause extended runtime within jpeglib without |
| 117 | // exercising additional code paths in qpdf, and potentially causing counterproductive timeouts. | 117 | // exercising additional code paths in qpdf, and potentially causing counterproductive timeouts. |
fuzz/qpdf_extra/394463491.fuzz
0 → 100644
No preview for this file type
fuzz/qpdf_fuzzer.cc
| @@ -109,7 +109,7 @@ FuzzHelper::doChecks() | @@ -109,7 +109,7 @@ FuzzHelper::doChecks() | ||
| 109 | Pl_PNGFilter::setMemoryLimit(1'000'000); | 109 | Pl_PNGFilter::setMemoryLimit(1'000'000); |
| 110 | Pl_RunLength::setMemoryLimit(1'000'000); | 110 | Pl_RunLength::setMemoryLimit(1'000'000); |
| 111 | Pl_TIFFPredictor::setMemoryLimit(1'000'000); | 111 | Pl_TIFFPredictor::setMemoryLimit(1'000'000); |
| 112 | - Pl_Flate::setMemoryLimit(200'000); | 112 | + Pl_Flate::memory_limit(200'000); |
| 113 | 113 | ||
| 114 | // Do not decompress corrupt data. This may cause extended runtime within jpeglib without | 114 | // Do not decompress corrupt data. This may cause extended runtime within jpeglib without |
| 115 | // exercising additional code paths in qpdf, and potentially causing counterproductive timeouts. | 115 | // exercising additional code paths in qpdf, and potentially causing counterproductive timeouts. |
fuzz/qpdf_lin_fuzzer.cc
| @@ -110,7 +110,7 @@ FuzzHelper::doChecks() | @@ -110,7 +110,7 @@ FuzzHelper::doChecks() | ||
| 110 | Pl_PNGFilter::setMemoryLimit(1'000'000); | 110 | Pl_PNGFilter::setMemoryLimit(1'000'000); |
| 111 | Pl_RunLength::setMemoryLimit(1'000'000); | 111 | Pl_RunLength::setMemoryLimit(1'000'000); |
| 112 | Pl_TIFFPredictor::setMemoryLimit(1'000'000); | 112 | Pl_TIFFPredictor::setMemoryLimit(1'000'000); |
| 113 | - Pl_Flate::setMemoryLimit(200'000); | 113 | + Pl_Flate::memory_limit(200'000); |
| 114 | 114 | ||
| 115 | // Do not decompress corrupt data. This may cause extended runtime within jpeglib without | 115 | // Do not decompress corrupt data. This may cause extended runtime within jpeglib without |
| 116 | // exercising additional code paths in qpdf, and potentially causing counterproductive timeouts. | 116 | // exercising additional code paths in qpdf, and potentially causing counterproductive timeouts. |
fuzz/qpdf_outlines_fuzzer.cc
| @@ -87,7 +87,7 @@ FuzzHelper::doChecks() | @@ -87,7 +87,7 @@ FuzzHelper::doChecks() | ||
| 87 | Pl_PNGFilter::setMemoryLimit(1'000'000); | 87 | Pl_PNGFilter::setMemoryLimit(1'000'000); |
| 88 | Pl_RunLength::setMemoryLimit(1'000'000); | 88 | Pl_RunLength::setMemoryLimit(1'000'000); |
| 89 | Pl_TIFFPredictor::setMemoryLimit(1'000'000); | 89 | Pl_TIFFPredictor::setMemoryLimit(1'000'000); |
| 90 | - Pl_Flate::setMemoryLimit(200'000); | 90 | + Pl_Flate::memory_limit(200'000); |
| 91 | 91 | ||
| 92 | // Do not decompress corrupt data. This may cause extended runtime within jpeglib without | 92 | // Do not decompress corrupt data. This may cause extended runtime within jpeglib without |
| 93 | // exercising additional code paths in qpdf, and potentially causing counterproductive timeouts. | 93 | // exercising additional code paths in qpdf, and potentially causing counterproductive timeouts. |
fuzz/qpdf_pages_fuzzer.cc
| @@ -108,7 +108,7 @@ FuzzHelper::doChecks() | @@ -108,7 +108,7 @@ FuzzHelper::doChecks() | ||
| 108 | Pl_PNGFilter::setMemoryLimit(1'000'000); | 108 | Pl_PNGFilter::setMemoryLimit(1'000'000); |
| 109 | Pl_RunLength::setMemoryLimit(1'000'000); | 109 | Pl_RunLength::setMemoryLimit(1'000'000); |
| 110 | Pl_TIFFPredictor::setMemoryLimit(1'000'000); | 110 | Pl_TIFFPredictor::setMemoryLimit(1'000'000); |
| 111 | - Pl_Flate::setMemoryLimit(200'000); | 111 | + Pl_Flate::memory_limit(200'000); |
| 112 | 112 | ||
| 113 | // Do not decompress corrupt data. This may cause extended runtime within jpeglib without | 113 | // Do not decompress corrupt data. This may cause extended runtime within jpeglib without |
| 114 | // exercising additional code paths in qpdf, and potentially causing counterproductive timeouts. | 114 | // exercising additional code paths in qpdf, and potentially causing counterproductive timeouts. |
fuzz/qtest/fuzz.test
| @@ -11,7 +11,7 @@ my $td = new TestDriver('fuzz'); | @@ -11,7 +11,7 @@ my $td = new TestDriver('fuzz'); | ||
| 11 | 11 | ||
| 12 | my $qpdf_corpus = $ENV{'QPDF_FUZZ_CORPUS'} || die "must set QPDF_FUZZ_CORPUS"; | 12 | my $qpdf_corpus = $ENV{'QPDF_FUZZ_CORPUS'} || die "must set QPDF_FUZZ_CORPUS"; |
| 13 | 13 | ||
| 14 | -my $n_qpdf_files = 91; # increment when adding new files | 14 | +my $n_qpdf_files = 92; # increment when adding new files |
| 15 | 15 | ||
| 16 | my @fuzzers = ( | 16 | my @fuzzers = ( |
| 17 | ['ascii85' => 1], | 17 | ['ascii85' => 1], |
include/qpdf/Pl_Flate.hh
| @@ -48,7 +48,9 @@ class QPDF_DLL_CLASS Pl_Flate: public Pipeline | @@ -48,7 +48,9 @@ class QPDF_DLL_CLASS Pl_Flate: public Pipeline | ||
| 48 | // Limit the memory used. | 48 | // Limit the memory used. |
| 49 | // NB This is a static option affecting all Pl_Flate instances. | 49 | // NB This is a static option affecting all Pl_Flate instances. |
| 50 | QPDF_DLL | 50 | QPDF_DLL |
| 51 | - static void setMemoryLimit(unsigned long long limit); | 51 | + static unsigned long long memory_limit(); |
| 52 | + QPDF_DLL | ||
| 53 | + static void memory_limit(unsigned long long limit); | ||
| 52 | 54 | ||
| 53 | QPDF_DLL | 55 | QPDF_DLL |
| 54 | void write(unsigned char const* data, size_t len) override; | 56 | void write(unsigned char const* data, size_t len) override; |
libqpdf/Pl_Flate.cc
| @@ -14,7 +14,7 @@ | @@ -14,7 +14,7 @@ | ||
| 14 | 14 | ||
| 15 | namespace | 15 | namespace |
| 16 | { | 16 | { |
| 17 | - unsigned long long memory_limit{0}; | 17 | + unsigned long long memory_limit_{0}; |
| 18 | } // namespace | 18 | } // namespace |
| 19 | 19 | ||
| 20 | int Pl_Flate::compression_level = Z_DEFAULT_COMPRESSION; | 20 | int Pl_Flate::compression_level = Z_DEFAULT_COMPRESSION; |
| @@ -80,10 +80,16 @@ Pl_Flate::~Pl_Flate() // NOLINT (modernize-use-equals-default) | @@ -80,10 +80,16 @@ Pl_Flate::~Pl_Flate() // NOLINT (modernize-use-equals-default) | ||
| 80 | // Must be explicit and not inline -- see QPDF_DLL_CLASS in README-maintainer | 80 | // Must be explicit and not inline -- see QPDF_DLL_CLASS in README-maintainer |
| 81 | } | 81 | } |
| 82 | 82 | ||
| 83 | +unsigned long long | ||
| 84 | +Pl_Flate::memory_limit() | ||
| 85 | +{ | ||
| 86 | + return memory_limit_; | ||
| 87 | +} | ||
| 88 | + | ||
| 83 | void | 89 | void |
| 84 | -Pl_Flate::setMemoryLimit(unsigned long long limit) | 90 | +Pl_Flate::memory_limit(unsigned long long limit) |
| 85 | { | 91 | { |
| 86 | - memory_limit = limit; | 92 | + memory_limit_ = limit; |
| 87 | } | 93 | } |
| 88 | 94 | ||
| 89 | void | 95 | void |
| @@ -197,9 +203,9 @@ Pl_Flate::handleData(unsigned char const* data, size_t len, int flush) | @@ -197,9 +203,9 @@ Pl_Flate::handleData(unsigned char const* data, size_t len, int flush) | ||
| 197 | } | 203 | } |
| 198 | uLong ready = QIntC::to_ulong(m->out_bufsize - zstream.avail_out); | 204 | uLong ready = QIntC::to_ulong(m->out_bufsize - zstream.avail_out); |
| 199 | if (ready > 0) { | 205 | if (ready > 0) { |
| 200 | - if (memory_limit && m->action != a_deflate) { | 206 | + if (memory_limit_ && m->action != a_deflate) { |
| 201 | m->written += ready; | 207 | m->written += ready; |
| 202 | - if (m->written > memory_limit) { | 208 | + if (m->written > memory_limit_) { |
| 203 | throw std::runtime_error("PL_Flate memory limit exceeded"); | 209 | throw std::runtime_error("PL_Flate memory limit exceeded"); |
| 204 | } | 210 | } |
| 205 | } | 211 | } |
| @@ -220,7 +226,7 @@ Pl_Flate::handleData(unsigned char const* data, size_t len, int flush) | @@ -220,7 +226,7 @@ Pl_Flate::handleData(unsigned char const* data, size_t len, int flush) | ||
| 220 | void | 226 | void |
| 221 | Pl_Flate::finish() | 227 | Pl_Flate::finish() |
| 222 | { | 228 | { |
| 223 | - if (m->written > memory_limit) { | 229 | + if (m->written > memory_limit_) { |
| 224 | throw std::runtime_error("PL_Flate memory limit exceeded"); | 230 | throw std::runtime_error("PL_Flate memory limit exceeded"); |
| 225 | } | 231 | } |
| 226 | try { | 232 | try { |
libqpdf/QPDFJob_argv.cc
| @@ -117,8 +117,10 @@ ArgParser::argZopfli() | @@ -117,8 +117,10 @@ ArgParser::argZopfli() | ||
| 117 | logger->info("Set the environment variable QPDF_ZOPFLI to activate.\n"); | 117 | logger->info("Set the environment variable QPDF_ZOPFLI to activate.\n"); |
| 118 | logger->info("* QPDF_ZOPFLI=disabled or QPDF_ZOPFLI not set: don't use zopfli.\n"); | 118 | logger->info("* QPDF_ZOPFLI=disabled or QPDF_ZOPFLI not set: don't use zopfli.\n"); |
| 119 | logger->info("* QPDF_ZOPFLI=force: use zopfli, and fail if not available.\n"); | 119 | logger->info("* QPDF_ZOPFLI=force: use zopfli, and fail if not available.\n"); |
| 120 | - logger->info("* QPDF_ZOPFLI=silent: use zopfli if available and silently fall back if not.\n"); | ||
| 121 | - logger->info("* QPDF_ZOPFLI= any other value: use zopfli if available, and warn if not.\n"); | 120 | + logger->info( |
| 121 | + "* QPDF_ZOPFLI=silent: use zopfli if available and silently fall back if not.\n"); | ||
| 122 | + logger->info( | ||
| 123 | + "* QPDF_ZOPFLI= any other value: use zopfli if available, and warn if not.\n"); | ||
| 122 | } | 124 | } |
| 123 | } else { | 125 | } else { |
| 124 | logger->error("zopfli support is not enabled\n"); | 126 | logger->error("zopfli support is not enabled\n"); |
libqpdf/SF_FlateLzwDecode.cc
| @@ -7,17 +7,6 @@ | @@ -7,17 +7,6 @@ | ||
| 7 | #include <qpdf/QIntC.hh> | 7 | #include <qpdf/QIntC.hh> |
| 8 | #include <qpdf/QTC.hh> | 8 | #include <qpdf/QTC.hh> |
| 9 | 9 | ||
| 10 | -SF_FlateLzwDecode::SF_FlateLzwDecode(bool lzw) : | ||
| 11 | - lzw(lzw), | ||
| 12 | - // Initialize values to their defaults as per the PDF spec | ||
| 13 | - predictor(1), | ||
| 14 | - columns(1), | ||
| 15 | - colors(1), | ||
| 16 | - bits_per_component(8), | ||
| 17 | - early_code_change(true) | ||
| 18 | -{ | ||
| 19 | -} | ||
| 20 | - | ||
| 21 | bool | 10 | bool |
| 22 | SF_FlateLzwDecode::setDecodeParms(QPDFObjectHandle decode_parms) | 11 | SF_FlateLzwDecode::setDecodeParms(QPDFObjectHandle decode_parms) |
| 23 | { | 12 | { |
| @@ -25,78 +14,83 @@ SF_FlateLzwDecode::setDecodeParms(QPDFObjectHandle decode_parms) | @@ -25,78 +14,83 @@ SF_FlateLzwDecode::setDecodeParms(QPDFObjectHandle decode_parms) | ||
| 25 | return true; | 14 | return true; |
| 26 | } | 15 | } |
| 27 | 16 | ||
| 28 | - bool filterable = true; | 17 | + auto memory_limit = Pl_Flate::memory_limit(); |
| 18 | + | ||
| 29 | std::set<std::string> keys = decode_parms.getKeys(); | 19 | std::set<std::string> keys = decode_parms.getKeys(); |
| 30 | for (auto const& key: keys) { | 20 | for (auto const& key: keys) { |
| 31 | QPDFObjectHandle value = decode_parms.getKey(key); | 21 | QPDFObjectHandle value = decode_parms.getKey(key); |
| 32 | if (key == "/Predictor") { | 22 | if (key == "/Predictor") { |
| 33 | if (value.isInteger()) { | 23 | if (value.isInteger()) { |
| 34 | - this->predictor = value.getIntValueAsInt(); | ||
| 35 | - if (!((this->predictor == 1) || (this->predictor == 2) || | ||
| 36 | - ((this->predictor >= 10) && (this->predictor <= 15)))) { | ||
| 37 | - filterable = false; | 24 | + predictor = value.getIntValueAsInt(); |
| 25 | + if (!(predictor == 1 || predictor == 2 || (predictor >= 10 && predictor <= 15))) { | ||
| 26 | + return false; | ||
| 38 | } | 27 | } |
| 39 | } else { | 28 | } else { |
| 40 | - filterable = false; | 29 | + return false; |
| 41 | } | 30 | } |
| 42 | - } else if ((key == "/Columns") || (key == "/Colors") || (key == "/BitsPerComponent")) { | 31 | + } else if (key == "/Columns" || key == "/Colors" || key == "/BitsPerComponent") { |
| 43 | if (value.isInteger()) { | 32 | if (value.isInteger()) { |
| 44 | int val = value.getIntValueAsInt(); | 33 | int val = value.getIntValueAsInt(); |
| 34 | + if (memory_limit && static_cast<unsigned int>(val) > memory_limit) { | ||
| 35 | + QPDFLogger::defaultLogger()->warn( | ||
| 36 | + "SF_FlateLzwDecode parameter exceeds PL_Flate memory limit\n"); | ||
| 37 | + return false; | ||
| 38 | + } | ||
| 45 | if (key == "/Columns") { | 39 | if (key == "/Columns") { |
| 46 | - this->columns = val; | 40 | + columns = val; |
| 47 | } else if (key == "/Colors") { | 41 | } else if (key == "/Colors") { |
| 48 | - this->colors = val; | 42 | + colors = val; |
| 49 | } else if (key == "/BitsPerComponent") { | 43 | } else if (key == "/BitsPerComponent") { |
| 50 | - this->bits_per_component = val; | 44 | + bits_per_component = val; |
| 51 | } | 45 | } |
| 52 | } else { | 46 | } else { |
| 53 | - filterable = false; | 47 | + return false; |
| 54 | } | 48 | } |
| 55 | } else if (lzw && (key == "/EarlyChange")) { | 49 | } else if (lzw && (key == "/EarlyChange")) { |
| 56 | if (value.isInteger()) { | 50 | if (value.isInteger()) { |
| 57 | int earlychange = value.getIntValueAsInt(); | 51 | int earlychange = value.getIntValueAsInt(); |
| 58 | - this->early_code_change = (earlychange == 1); | ||
| 59 | - if (!((earlychange == 0) || (earlychange == 1))) { | ||
| 60 | - filterable = false; | 52 | + early_code_change = (earlychange == 1); |
| 53 | + if (!(earlychange == 0 || earlychange == 1)) { | ||
| 54 | + return false; | ||
| 61 | } | 55 | } |
| 62 | } else { | 56 | } else { |
| 63 | - filterable = false; | 57 | + return false; |
| 64 | } | 58 | } |
| 65 | } | 59 | } |
| 66 | } | 60 | } |
| 67 | 61 | ||
| 68 | - if ((this->predictor > 1) && (this->columns == 0)) { | ||
| 69 | - filterable = false; | 62 | + if (predictor > 1 && columns == 0) { |
| 63 | + return false; | ||
| 70 | } | 64 | } |
| 71 | 65 | ||
| 72 | - return filterable; | 66 | + return true; |
| 73 | } | 67 | } |
| 74 | 68 | ||
| 75 | Pipeline* | 69 | Pipeline* |
| 76 | SF_FlateLzwDecode::getDecodePipeline(Pipeline* next) | 70 | SF_FlateLzwDecode::getDecodePipeline(Pipeline* next) |
| 77 | { | 71 | { |
| 78 | std::shared_ptr<Pipeline> pipeline; | 72 | std::shared_ptr<Pipeline> pipeline; |
| 79 | - if ((this->predictor >= 10) && (this->predictor <= 15)) { | 73 | + if (predictor >= 10 && predictor <= 15) { |
| 80 | QTC::TC("qpdf", "SF_FlateLzwDecode PNG filter"); | 74 | QTC::TC("qpdf", "SF_FlateLzwDecode PNG filter"); |
| 81 | pipeline = std::make_shared<Pl_PNGFilter>( | 75 | pipeline = std::make_shared<Pl_PNGFilter>( |
| 82 | "png decode", | 76 | "png decode", |
| 83 | next, | 77 | next, |
| 84 | Pl_PNGFilter::a_decode, | 78 | Pl_PNGFilter::a_decode, |
| 85 | - QIntC::to_uint(this->columns), | ||
| 86 | - QIntC::to_uint(this->colors), | ||
| 87 | - QIntC::to_uint(this->bits_per_component)); | ||
| 88 | - this->pipelines.push_back(pipeline); | 79 | + QIntC::to_uint(columns), |
| 80 | + QIntC::to_uint(colors), | ||
| 81 | + QIntC::to_uint(bits_per_component)); | ||
| 82 | + pipelines.push_back(pipeline); | ||
| 89 | next = pipeline.get(); | 83 | next = pipeline.get(); |
| 90 | - } else if (this->predictor == 2) { | 84 | + } else if (predictor == 2) { |
| 91 | QTC::TC("qpdf", "SF_FlateLzwDecode TIFF predictor"); | 85 | QTC::TC("qpdf", "SF_FlateLzwDecode TIFF predictor"); |
| 92 | pipeline = std::make_shared<Pl_TIFFPredictor>( | 86 | pipeline = std::make_shared<Pl_TIFFPredictor>( |
| 93 | "tiff decode", | 87 | "tiff decode", |
| 94 | next, | 88 | next, |
| 95 | Pl_TIFFPredictor::a_decode, | 89 | Pl_TIFFPredictor::a_decode, |
| 96 | - QIntC::to_uint(this->columns), | ||
| 97 | - QIntC::to_uint(this->colors), | ||
| 98 | - QIntC::to_uint(this->bits_per_component)); | ||
| 99 | - this->pipelines.push_back(pipeline); | 90 | + QIntC::to_uint(columns), |
| 91 | + QIntC::to_uint(colors), | ||
| 92 | + QIntC::to_uint(bits_per_component)); | ||
| 93 | + pipelines.push_back(pipeline); | ||
| 100 | next = pipeline.get(); | 94 | next = pipeline.get(); |
| 101 | } | 95 | } |
| 102 | 96 | ||
| @@ -105,7 +99,7 @@ SF_FlateLzwDecode::getDecodePipeline(Pipeline* next) | @@ -105,7 +99,7 @@ SF_FlateLzwDecode::getDecodePipeline(Pipeline* next) | ||
| 105 | } else { | 99 | } else { |
| 106 | pipeline = std::make_shared<Pl_Flate>("stream inflate", next, Pl_Flate::a_inflate); | 100 | pipeline = std::make_shared<Pl_Flate>("stream inflate", next, Pl_Flate::a_inflate); |
| 107 | } | 101 | } |
| 108 | - this->pipelines.push_back(pipeline); | 102 | + pipelines.push_back(pipeline); |
| 109 | return pipeline.get(); | 103 | return pipeline.get(); |
| 110 | } | 104 | } |
| 111 | 105 |
libqpdf/qpdf/SF_FlateLzwDecode.hh
| @@ -5,25 +5,29 @@ | @@ -5,25 +5,29 @@ | ||
| 5 | #ifndef SF_FLATELZWDECODE_HH | 5 | #ifndef SF_FLATELZWDECODE_HH |
| 6 | # define SF_FLATELZWDECODE_HH | 6 | # define SF_FLATELZWDECODE_HH |
| 7 | 7 | ||
| 8 | -class SF_FlateLzwDecode: public QPDFStreamFilter | 8 | +class SF_FlateLzwDecode final: public QPDFStreamFilter |
| 9 | { | 9 | { |
| 10 | public: | 10 | public: |
| 11 | - SF_FlateLzwDecode(bool lzw); | ||
| 12 | - ~SF_FlateLzwDecode() override = default; | 11 | + SF_FlateLzwDecode(bool lzw) : |
| 12 | + lzw(lzw) | ||
| 13 | + { | ||
| 14 | + } | ||
| 15 | + ~SF_FlateLzwDecode() final = default; | ||
| 13 | 16 | ||
| 14 | - bool setDecodeParms(QPDFObjectHandle decode_parms) override; | ||
| 15 | - Pipeline* getDecodePipeline(Pipeline* next) override; | 17 | + bool setDecodeParms(QPDFObjectHandle decode_parms) final; |
| 18 | + Pipeline* getDecodePipeline(Pipeline* next) final; | ||
| 16 | 19 | ||
| 17 | static std::shared_ptr<QPDFStreamFilter> flate_factory(); | 20 | static std::shared_ptr<QPDFStreamFilter> flate_factory(); |
| 18 | static std::shared_ptr<QPDFStreamFilter> lzw_factory(); | 21 | static std::shared_ptr<QPDFStreamFilter> lzw_factory(); |
| 19 | 22 | ||
| 20 | private: | 23 | private: |
| 21 | - bool lzw; | ||
| 22 | - int predictor; | ||
| 23 | - int columns; | ||
| 24 | - int colors; | ||
| 25 | - int bits_per_component; | ||
| 26 | - bool early_code_change; | 24 | + bool lzw{}; |
| 25 | + // Defaults as per the PDF spec | ||
| 26 | + int predictor{1}; | ||
| 27 | + int columns{1}; | ||
| 28 | + int colors{1}; | ||
| 29 | + int bits_per_component{8}; | ||
| 30 | + bool early_code_change{true}; | ||
| 27 | std::vector<std::shared_ptr<Pipeline>> pipelines; | 31 | std::vector<std::shared_ptr<Pipeline>> pipelines; |
| 28 | }; | 32 | }; |
| 29 | 33 |