Commit c912af7384d5abeb281856f7122d427af5e29d73

Authored by m-holger
1 parent 172cc613

In QPDFParser remove state st_top

libqpdf/QPDFParser.cc
@@ -33,10 +33,7 @@ QPDFParser::parse(bool& empty, bool content_stream) @@ -33,10 +33,7 @@ QPDFParser::parse(bool& empty, bool content_stream)
33 empty = false; 33 empty = false;
34 34
35 std::shared_ptr<QPDFObject> object; 35 std::shared_ptr<QPDFObject> object;
36 - stack.clear();  
37 - stack.emplace_back(input, st_top);  
38 - frame = &stack.back();  
39 - object = nullptr; 36 + auto offset = input->tell();
40 37
41 if (!tokenizer.nextToken(*input, object_description)) { 38 if (!tokenizer.nextToken(*input, object_description)) {
42 warn(tokenizer.getErrorMessage()); 39 warn(tokenizer.getErrorMessage());
@@ -74,9 +71,11 @@ QPDFParser::parse(bool&amp; empty, bool content_stream) @@ -74,9 +71,11 @@ QPDFParser::parse(bool&amp; empty, bool content_stream)
74 71
75 case QPDFTokenizer::tt_array_open: 72 case QPDFTokenizer::tt_array_open:
76 case QPDFTokenizer::tt_dict_open: 73 case QPDFTokenizer::tt_dict_open:
  74 + stack.clear();
77 stack.emplace_back( 75 stack.emplace_back(
78 input, 76 input,
79 (tokenizer.getType() == QPDFTokenizer::tt_array_open) ? st_array : st_dictionary); 77 (tokenizer.getType() == QPDFTokenizer::tt_array_open) ? st_array : st_dictionary);
  78 + frame = &stack.back();
80 return parseRemainder(content_stream); 79 return parseRemainder(content_stream);
81 80
82 case QPDFTokenizer::tt_bool: 81 case QPDFTokenizer::tt_bool:
@@ -132,7 +131,7 @@ QPDFParser::parse(bool&amp; empty, bool content_stream) @@ -132,7 +131,7 @@ QPDFParser::parse(bool&amp; empty, bool content_stream)
132 return {QPDF_Null::create()}; 131 return {QPDF_Null::create()};
133 } 132 }
134 133
135 - setDescription(object, frame->offset); 134 + setDescription(object, offset);
136 return object; 135 return object;
137 } 136 }
138 137
@@ -148,14 +147,11 @@ QPDFParser::parseRemainder(bool content_stream) @@ -148,14 +147,11 @@ QPDFParser::parseRemainder(bool content_stream)
148 147
149 std::shared_ptr<QPDFObject> object; 148 std::shared_ptr<QPDFObject> object;
150 bool set_offset = false; 149 bool set_offset = false;
151 -  
152 - bool done = false;  
153 bool b_contents = false; 150 bool b_contents = false;
154 bool is_null = false; 151 bool is_null = false;
155 - frame = &stack.back(); // CHANGED  
156 bad_count = 0; 152 bad_count = 0;
157 153
158 - while (!done) { 154 + while (true) {
159 bool indirect_ref = false; 155 bool indirect_ref = false;
160 is_null = false; 156 is_null = false;
161 object = nullptr; 157 object = nullptr;
@@ -197,10 +193,6 @@ QPDFParser::parseRemainder(bool content_stream) @@ -197,10 +193,6 @@ QPDFParser::parseRemainder(bool content_stream)
197 193
198 case QPDFTokenizer::tt_array_close: 194 case QPDFTokenizer::tt_array_close:
199 if (frame->state == st_array) { 195 if (frame->state == st_array) {
200 - if (stack.size() < 2) {  
201 - throw std::logic_error("QPDFParser::parseInternal: st_stop encountered with "  
202 - "insufficient elements in stack");  
203 - }  
204 object = QPDF_Array::create(std::move(frame->olist), frame->null_count > 100); 196 object = QPDF_Array::create(std::move(frame->olist), frame->null_count > 100);
205 setDescription(object, frame->offset - 1); 197 setDescription(object, frame->offset - 1);
206 // The `offset` points to the next of "[". Set the rewind offset to point to the 198 // The `offset` points to the next of "[". Set the rewind offset to point to the
@@ -208,6 +200,9 @@ QPDFParser::parseRemainder(bool content_stream) @@ -208,6 +200,9 @@ QPDFParser::parseRemainder(bool content_stream)
208 // array start delimiter. getLastOffset points to the array end token and therefore 200 // array start delimiter. getLastOffset points to the array end token and therefore
209 // can't be used here. 201 // can't be used here.
210 set_offset = true; 202 set_offset = true;
  203 + if (stack.size() <= 1) {
  204 + return object;
  205 + }
211 stack.pop_back(); 206 stack.pop_back();
212 frame = &stack.back(); 207 frame = &stack.back();
213 } else { 208 } else {
@@ -222,11 +217,6 @@ QPDFParser::parseRemainder(bool content_stream) @@ -222,11 +217,6 @@ QPDFParser::parseRemainder(bool content_stream)
222 217
223 case QPDFTokenizer::tt_dict_close: 218 case QPDFTokenizer::tt_dict_close:
224 if (frame->state == st_dictionary) { 219 if (frame->state == st_dictionary) {
225 - if (stack.size() < 2) {  
226 - throw std::logic_error("QPDFParser::parseInternal: st_stop encountered with "  
227 - "insufficient elements in stack");  
228 - }  
229 -  
230 // Convert list to map. Alternating elements are keys. Attempt to recover more or 220 // Convert list to map. Alternating elements are keys. Attempt to recover more or
231 // less gracefully from invalid dictionaries. 221 // less gracefully from invalid dictionaries.
232 std::set<std::string> names; 222 std::set<std::string> names;
@@ -278,7 +268,7 @@ QPDFParser::parseRemainder(bool content_stream) @@ -278,7 +268,7 @@ QPDFParser::parseRemainder(bool content_stream)
278 val = QPDF_Null::create(); 268 val = QPDF_Null::create();
279 } 269 }
280 270
281 - dict[std::move(key)] = std::move(val); 271 + dict[std::move(key)] = val;
282 } 272 }
283 if (!frame->contents_string.empty() && dict.count("/Type") && 273 if (!frame->contents_string.empty() && dict.count("/Type") &&
284 dict["/Type"].isNameAndEquals("/Sig") && dict.count("/ByteRange") && 274 dict["/Type"].isNameAndEquals("/Sig") && dict.count("/ByteRange") &&
@@ -292,6 +282,9 @@ QPDFParser::parseRemainder(bool content_stream) @@ -292,6 +282,9 @@ QPDFParser::parseRemainder(bool content_stream)
292 // beginning of "<<". This has been explicitly tested with whitespace surrounding 282 // beginning of "<<". This has been explicitly tested with whitespace surrounding
293 // the dictionary start delimiter. getLastOffset points to the dictionary end token 283 // the dictionary start delimiter. getLastOffset points to the dictionary end token
294 // and therefore can't be used here. 284 // and therefore can't be used here.
  285 + if (stack.size() <= 1) {
  286 + return object;
  287 + }
295 set_offset = true; 288 set_offset = true;
296 stack.pop_back(); 289 stack.pop_back();
297 frame = &stack.back(); 290 frame = &stack.back();
@@ -307,7 +300,7 @@ QPDFParser::parseRemainder(bool content_stream) @@ -307,7 +300,7 @@ QPDFParser::parseRemainder(bool content_stream)
307 300
308 case QPDFTokenizer::tt_array_open: 301 case QPDFTokenizer::tt_array_open:
309 case QPDFTokenizer::tt_dict_open: 302 case QPDFTokenizer::tt_dict_open:
310 - if (stack.size() > 500) { 303 + if (stack.size() > 499) {
311 QTC::TC("qpdf", "QPDFParser too deep"); 304 QTC::TC("qpdf", "QPDFParser too deep");
312 warn("ignoring excessively deeply nested data structure"); 305 warn("ignoring excessively deeply nested data structure");
313 return {QPDF_Null::create()}; 306 return {QPDF_Null::create()};
@@ -328,7 +321,6 @@ QPDFParser::parseRemainder(bool content_stream) @@ -328,7 +321,6 @@ QPDFParser::parseRemainder(bool content_stream)
328 case QPDFTokenizer::tt_null: 321 case QPDFTokenizer::tt_null:
329 is_null = true; 322 is_null = true;
330 ++frame->null_count; 323 ++frame->null_count;
331 -  
332 break; 324 break;
333 325
334 case QPDFTokenizer::tt_integer: 326 case QPDFTokenizer::tt_integer:
@@ -426,32 +418,15 @@ QPDFParser::parseRemainder(bool content_stream) @@ -426,32 +418,15 @@ QPDFParser::parseRemainder(bool content_stream)
426 throw std::logic_error("QPDFParser:parseInternal: unexpected uninitialized object"); 418 throw std::logic_error("QPDFParser:parseInternal: unexpected uninitialized object");
427 } 419 }
428 420
429 - switch (frame->state) {  
430 - case st_dictionary:  
431 - case st_array:  
432 - if (is_null) {  
433 - object = null_oh;  
434 - // No need to set description for direct nulls - they probably will become implicit.  
435 - } else if (!indirect_ref && !set_offset) {  
436 - setDescription(object, input->getLastOffset());  
437 - }  
438 - set_offset = true;  
439 - frame->olist.push_back(object);  
440 - break;  
441 -  
442 - case st_top:  
443 - done = true;  
444 - break; 421 + if (is_null) {
  422 + object = null_oh;
  423 + // No need to set description for direct nulls - they probably will become implicit.
  424 + } else if (!indirect_ref && !set_offset) {
  425 + setDescription(object, input->getLastOffset());
445 } 426 }
  427 + frame->olist.push_back(object);
446 } 428 }
447 -  
448 - if (is_null) {  
449 - object = QPDF_Null::create();  
450 - }  
451 - if (!set_offset) {  
452 - setDescription(object, frame->offset);  
453 - }  
454 - return object; 429 + return {}; // unreachable
455 } 430 }
456 431
457 void 432 void
libqpdf/qpdf/QPDFParser.hh
@@ -32,7 +32,7 @@ class QPDFParser @@ -32,7 +32,7 @@ class QPDFParser
32 32
33 private: 33 private:
34 struct StackFrame; 34 struct StackFrame;
35 - enum parser_state_e { st_top, st_dictionary, st_array }; 35 + enum parser_state_e { st_dictionary, st_array };
36 36
37 struct StackFrame 37 struct StackFrame
38 { 38 {