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 33 empty = false;
34 34  
35 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 38 if (!tokenizer.nextToken(*input, object_description)) {
42 39 warn(tokenizer.getErrorMessage());
... ... @@ -74,9 +71,11 @@ QPDFParser::parse(bool&amp; empty, bool content_stream)
74 71  
75 72 case QPDFTokenizer::tt_array_open:
76 73 case QPDFTokenizer::tt_dict_open:
  74 + stack.clear();
77 75 stack.emplace_back(
78 76 input,
79 77 (tokenizer.getType() == QPDFTokenizer::tt_array_open) ? st_array : st_dictionary);
  78 + frame = &stack.back();
80 79 return parseRemainder(content_stream);
81 80  
82 81 case QPDFTokenizer::tt_bool:
... ... @@ -132,7 +131,7 @@ QPDFParser::parse(bool&amp; empty, bool content_stream)
132 131 return {QPDF_Null::create()};
133 132 }
134 133  
135   - setDescription(object, frame->offset);
  134 + setDescription(object, offset);
136 135 return object;
137 136 }
138 137  
... ... @@ -148,14 +147,11 @@ QPDFParser::parseRemainder(bool content_stream)
148 147  
149 148 std::shared_ptr<QPDFObject> object;
150 149 bool set_offset = false;
151   -
152   - bool done = false;
153 150 bool b_contents = false;
154 151 bool is_null = false;
155   - frame = &stack.back(); // CHANGED
156 152 bad_count = 0;
157 153  
158   - while (!done) {
  154 + while (true) {
159 155 bool indirect_ref = false;
160 156 is_null = false;
161 157 object = nullptr;
... ... @@ -197,10 +193,6 @@ QPDFParser::parseRemainder(bool content_stream)
197 193  
198 194 case QPDFTokenizer::tt_array_close:
199 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 196 object = QPDF_Array::create(std::move(frame->olist), frame->null_count > 100);
205 197 setDescription(object, frame->offset - 1);
206 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 200 // array start delimiter. getLastOffset points to the array end token and therefore
209 201 // can't be used here.
210 202 set_offset = true;
  203 + if (stack.size() <= 1) {
  204 + return object;
  205 + }
211 206 stack.pop_back();
212 207 frame = &stack.back();
213 208 } else {
... ... @@ -222,11 +217,6 @@ QPDFParser::parseRemainder(bool content_stream)
222 217  
223 218 case QPDFTokenizer::tt_dict_close:
224 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 220 // Convert list to map. Alternating elements are keys. Attempt to recover more or
231 221 // less gracefully from invalid dictionaries.
232 222 std::set<std::string> names;
... ... @@ -278,7 +268,7 @@ QPDFParser::parseRemainder(bool content_stream)
278 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 273 if (!frame->contents_string.empty() && dict.count("/Type") &&
284 274 dict["/Type"].isNameAndEquals("/Sig") && dict.count("/ByteRange") &&
... ... @@ -292,6 +282,9 @@ QPDFParser::parseRemainder(bool content_stream)
292 282 // beginning of "<<". This has been explicitly tested with whitespace surrounding
293 283 // the dictionary start delimiter. getLastOffset points to the dictionary end token
294 284 // and therefore can't be used here.
  285 + if (stack.size() <= 1) {
  286 + return object;
  287 + }
295 288 set_offset = true;
296 289 stack.pop_back();
297 290 frame = &stack.back();
... ... @@ -307,7 +300,7 @@ QPDFParser::parseRemainder(bool content_stream)
307 300  
308 301 case QPDFTokenizer::tt_array_open:
309 302 case QPDFTokenizer::tt_dict_open:
310   - if (stack.size() > 500) {
  303 + if (stack.size() > 499) {
311 304 QTC::TC("qpdf", "QPDFParser too deep");
312 305 warn("ignoring excessively deeply nested data structure");
313 306 return {QPDF_Null::create()};
... ... @@ -328,7 +321,6 @@ QPDFParser::parseRemainder(bool content_stream)
328 321 case QPDFTokenizer::tt_null:
329 322 is_null = true;
330 323 ++frame->null_count;
331   -
332 324 break;
333 325  
334 326 case QPDFTokenizer::tt_integer:
... ... @@ -426,32 +418,15 @@ QPDFParser::parseRemainder(bool content_stream)
426 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 432 void
... ...
libqpdf/qpdf/QPDFParser.hh
... ... @@ -32,7 +32,7 @@ class QPDFParser
32 32  
33 33 private:
34 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 37 struct StackFrame
38 38 {
... ...