Commit 2856b288e4d2fff3d181e367cfd9a6ef7b555efb
Committed by
GitHub
Merge pull request #1258 from m-holger/fuzz
Adjust fuzzer memory limits and refactor Pl_RunLength::decode
Showing
8 changed files
with
16 additions
and
11 deletions
fuzz/CMakeLists.txt
| @@ -100,6 +100,7 @@ set(CORPUS_OTHER | @@ -100,6 +100,7 @@ set(CORPUS_OTHER | ||
| 100 | 16953.fuzz | 100 | 16953.fuzz |
| 101 | 17630.fuzz | 101 | 17630.fuzz |
| 102 | 17630a.fuzz | 102 | 17630a.fuzz |
| 103 | + 17630b.fuzz | ||
| 103 | 18241.fuzz | 104 | 18241.fuzz |
| 104 | 18247.fuzz | 105 | 18247.fuzz |
| 105 | 23172.fuzz | 106 | 23172.fuzz |
| @@ -128,6 +129,7 @@ set(CORPUS_OTHER | @@ -128,6 +129,7 @@ set(CORPUS_OTHER | ||
| 128 | 69977b.fuzz | 129 | 69977b.fuzz |
| 129 | 69977c.fuzz | 130 | 69977c.fuzz |
| 130 | 69977d.fuzz | 131 | 69977d.fuzz |
| 132 | + 69977e.fuzz | ||
| 131 | 70055.fuzz | 133 | 70055.fuzz |
| 132 | 70245.fuzz | 134 | 70245.fuzz |
| 133 | 70306.fuzz | 135 | 70306.fuzz |
fuzz/dct_fuzzer.cc
| @@ -30,7 +30,7 @@ FuzzHelper::doChecks() | @@ -30,7 +30,7 @@ FuzzHelper::doChecks() | ||
| 30 | // fuzzing is due to corrupt JPEG data which sometimes cannot be detected before | 30 | // fuzzing is due to corrupt JPEG data which sometimes cannot be detected before |
| 31 | // jpeg_start_decompress is called. During normal use of qpdf very large JPEGs can occasionally | 31 | // jpeg_start_decompress is called. During normal use of qpdf very large JPEGs can occasionally |
| 32 | // occur legitimately and therefore must be allowed during normal operations. | 32 | // occur legitimately and therefore must be allowed during normal operations. |
| 33 | - Pl_DCT::setMemoryLimit(1'000'000'000); | 33 | + Pl_DCT::setMemoryLimit(200'000'000); |
| 34 | 34 | ||
| 35 | // Do not decompress corrupt data. This may cause extended runtime within jpeglib without | 35 | // Do not decompress corrupt data. This may cause extended runtime within jpeglib without |
| 36 | // exercising additional code paths in qpdf. | 36 | // exercising additional code paths in qpdf. |
fuzz/qpdf_extra/17630b.fuzz
0 → 100644
No preview for this file type
fuzz/qpdf_extra/69977e.fuzz
0 → 100644
No preview for this file type
fuzz/qpdf_fuzzer.cc
| @@ -180,11 +180,11 @@ FuzzHelper::doChecks() | @@ -180,11 +180,11 @@ FuzzHelper::doChecks() | ||
| 180 | // fuzzing is due to corrupt JPEG data which sometimes cannot be detected before | 180 | // fuzzing is due to corrupt JPEG data which sometimes cannot be detected before |
| 181 | // jpeg_start_decompress is called. During normal use of qpdf very large JPEGs can occasionally | 181 | // jpeg_start_decompress is called. During normal use of qpdf very large JPEGs can occasionally |
| 182 | // occur legitimately and therefore must be allowed during normal operations. | 182 | // occur legitimately and therefore must be allowed during normal operations. |
| 183 | - Pl_DCT::setMemoryLimit(1'000'000'000); | 183 | + Pl_DCT::setMemoryLimit(100'000'000); |
| 184 | 184 | ||
| 185 | Pl_PNGFilter::setMemoryLimit(1'000'000); | 185 | Pl_PNGFilter::setMemoryLimit(1'000'000); |
| 186 | Pl_TIFFPredictor::setMemoryLimit(1'000'000); | 186 | Pl_TIFFPredictor::setMemoryLimit(1'000'000); |
| 187 | - Pl_Flate::setMemoryLimit(10'000'000); | 187 | + Pl_Flate::setMemoryLimit(1'000'000); |
| 188 | 188 | ||
| 189 | // Do not decompress corrupt data. This may cause extended runtime within jpeglib without | 189 | // Do not decompress corrupt data. This may cause extended runtime within jpeglib without |
| 190 | // exercising additional code paths in qpdf, and potentially causing counterproductive timeouts. | 190 | // exercising additional code paths in qpdf, and potentially causing counterproductive timeouts. |
fuzz/qtest/fuzz.test
| @@ -21,7 +21,7 @@ my @fuzzers = ( | @@ -21,7 +21,7 @@ my @fuzzers = ( | ||
| 21 | ['pngpredictor' => 1], | 21 | ['pngpredictor' => 1], |
| 22 | ['runlength' => 6], | 22 | ['runlength' => 6], |
| 23 | ['tiffpredictor' => 2], | 23 | ['tiffpredictor' => 2], |
| 24 | - ['qpdf' => 73], # increment when adding new files | 24 | + ['qpdf' => 75], # increment when adding new files |
| 25 | ); | 25 | ); |
| 26 | 26 | ||
| 27 | my $n_tests = 0; | 27 | my $n_tests = 0; |
include/qpdf/Pl_RunLength.hh
| @@ -62,6 +62,7 @@ class QPDF_DLL_CLASS Pl_RunLength: public Pipeline | @@ -62,6 +62,7 @@ class QPDF_DLL_CLASS Pl_RunLength: public Pipeline | ||
| 62 | state_e state; | 62 | state_e state; |
| 63 | unsigned char buf[128]; | 63 | unsigned char buf[128]; |
| 64 | unsigned int length; | 64 | unsigned int length; |
| 65 | + std::string out; | ||
| 65 | }; | 66 | }; |
| 66 | 67 | ||
| 67 | std::shared_ptr<Members> m; | 68 | std::shared_ptr<Members> m; |
libqpdf/Pl_RunLength.cc
| @@ -66,8 +66,9 @@ Pl_RunLength::encode(unsigned char const* data, size_t len) | @@ -66,8 +66,9 @@ Pl_RunLength::encode(unsigned char const* data, size_t len) | ||
| 66 | void | 66 | void |
| 67 | Pl_RunLength::decode(unsigned char const* data, size_t len) | 67 | Pl_RunLength::decode(unsigned char const* data, size_t len) |
| 68 | { | 68 | { |
| 69 | + m->out.reserve(len); | ||
| 69 | for (size_t i = 0; i < len; ++i) { | 70 | for (size_t i = 0; i < len; ++i) { |
| 70 | - unsigned char ch = data[i]; | 71 | + unsigned char const& ch = data[i]; |
| 71 | switch (m->state) { | 72 | switch (m->state) { |
| 72 | case st_top: | 73 | case st_top: |
| 73 | if (ch < 128) { | 74 | if (ch < 128) { |
| @@ -85,16 +86,14 @@ Pl_RunLength::decode(unsigned char const* data, size_t len) | @@ -85,16 +86,14 @@ Pl_RunLength::decode(unsigned char const* data, size_t len) | ||
| 85 | break; | 86 | break; |
| 86 | 87 | ||
| 87 | case st_copying: | 88 | case st_copying: |
| 88 | - this->getNext()->write(&ch, 1); | 89 | + m->out.append(1, static_cast<char>(ch)); |
| 89 | if (--m->length == 0) { | 90 | if (--m->length == 0) { |
| 90 | m->state = st_top; | 91 | m->state = st_top; |
| 91 | } | 92 | } |
| 92 | break; | 93 | break; |
| 93 | 94 | ||
| 94 | case st_run: | 95 | case st_run: |
| 95 | - for (unsigned int j = 0; j < m->length; ++j) { | ||
| 96 | - this->getNext()->write(&ch, 1); | ||
| 97 | - } | 96 | + m->out.append(m->length, static_cast<char>(ch)); |
| 98 | m->state = st_top; | 97 | m->state = st_top; |
| 99 | break; | 98 | break; |
| 100 | } | 99 | } |
| @@ -137,10 +136,13 @@ Pl_RunLength::finish() | @@ -137,10 +136,13 @@ Pl_RunLength::finish() | ||
| 137 | // When decoding, we might have read a length byte not followed by data, which means the stream | 136 | // When decoding, we might have read a length byte not followed by data, which means the stream |
| 138 | // was terminated early, but we will just ignore this case since this is the only sensible thing | 137 | // was terminated early, but we will just ignore this case since this is the only sensible thing |
| 139 | // to do. | 138 | // to do. |
| 139 | + auto next = getNext(); | ||
| 140 | if (m->action == a_encode) { | 140 | if (m->action == a_encode) { |
| 141 | flush_encode(); | 141 | flush_encode(); |
| 142 | unsigned char ch = 128; | 142 | unsigned char ch = 128; |
| 143 | - this->getNext()->write(&ch, 1); | 143 | + next->write(&ch, 1); |
| 144 | + } else { | ||
| 145 | + next->writeString(m->out); | ||
| 144 | } | 146 | } |
| 145 | - this->getNext()->finish(); | 147 | + next->finish(); |
| 146 | } | 148 | } |