Commit 3bab4cf394f0606998e3e000f510c1e49787a3f7

Authored by m-holger
1 parent 5edb5481

Refactor Pl_RunLength::decode

Buffer output locally.
Add qpdf_fuzzer test case.
fuzz/CMakeLists.txt
@@ -129,6 +129,7 @@ set(CORPUS_OTHER @@ -129,6 +129,7 @@ set(CORPUS_OTHER
129 69977b.fuzz 129 69977b.fuzz
130 69977c.fuzz 130 69977c.fuzz
131 69977d.fuzz 131 69977d.fuzz
  132 + 69977e.fuzz
132 70055.fuzz 133 70055.fuzz
133 70245.fuzz 134 70245.fuzz
134 70306.fuzz 135 70306.fuzz
fuzz/qpdf_extra/69977e.fuzz 0 → 100644
No preview for this file type
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' => 74], # 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 }