Commit 7402c02c808224932bd766a18f22b780a4d30b63

Authored by m-holger
1 parent 74162a2d

Combine stacks in QPDFParser::parse

Part of #729
Showing 1 changed file with 35 additions and 31 deletions
libqpdf/QPDFParser.cc
... ... @@ -7,6 +7,24 @@
7 7 #include <qpdf/QUtil.hh>
8 8 #include <qpdf/SparseOHArray.hh>
9 9  
  10 +namespace
  11 +{
  12 + struct StackFrame
  13 + {
  14 + StackFrame(std::shared_ptr<InputSource> input) :
  15 + offset(input->tell()),
  16 + contents_string(""),
  17 + contents_offset(-1)
  18 + {
  19 + }
  20 +
  21 + std::vector<QPDFObjectHandle> olist;
  22 + qpdf_offset_t offset;
  23 + std::string contents_string;
  24 + qpdf_offset_t contents_offset;
  25 + };
  26 +} // namespace
  27 +
10 28 QPDFObjectHandle
11 29 QPDFParser::parse(bool& empty, bool content_stream)
12 30 {
... ... @@ -17,8 +35,6 @@ QPDFParser::parse(bool&amp; empty, bool content_stream)
17 35 // this, it will cause a logic error to be thrown from
18 36 // QPDF::inParse().
19 37  
20   - using OHVector = std::vector<QPDFObjectHandle>;
21   -
22 38 QPDF::ParseGuard pg(context);
23 39  
24 40 empty = false;
... ... @@ -26,28 +42,22 @@ QPDFParser::parse(bool&amp; empty, bool content_stream)
26 42 QPDFObjectHandle object;
27 43 bool set_offset = false;
28 44  
29   - std::vector<OHVector> olist_stack;
30   - olist_stack.push_back(OHVector());
  45 + std::vector<StackFrame> stack;
  46 + stack.push_back(StackFrame(input));
31 47 std::vector<parser_state_e> state_stack;
32 48 state_stack.push_back(st_top);
33   - std::vector<qpdf_offset_t> offset_stack;
34   - qpdf_offset_t offset = input->tell();
35   - offset_stack.push_back(offset);
  49 + qpdf_offset_t offset;
36 50 bool done = false;
37 51 int bad_count = 0;
38 52 int good_count = 0;
39 53 bool b_contents = false;
40   - std::vector<std::string> contents_string_stack;
41   - contents_string_stack.push_back("");
42   - std::vector<qpdf_offset_t> contents_offset_stack;
43   - contents_offset_stack.push_back(-1);
  54 +
44 55 while (!done) {
45 56 bool bad = false;
46   - auto& olist = olist_stack.back();
  57 + auto& frame = stack.back();
  58 + auto& olist = frame.olist;
47 59 parser_state_e state = state_stack.back();
48   - offset = offset_stack.back();
49   - std::string& contents_string = contents_string_stack.back();
50   - qpdf_offset_t& contents_offset = contents_offset_stack.back();
  60 + offset = frame.offset;
51 61  
52 62 object = QPDFObjectHandle();
53 63 set_offset = false;
... ... @@ -108,23 +118,20 @@ QPDFParser::parse(bool&amp; empty, bool content_stream)
108 118  
109 119 case QPDFTokenizer::tt_array_open:
110 120 case QPDFTokenizer::tt_dict_open:
111   - if (olist_stack.size() > 500) {
  121 + if (stack.size() > 500) {
112 122 QTC::TC("qpdf", "QPDFParser too deep");
113 123 warn("ignoring excessively deeply nested data structure");
114 124 bad = true;
115 125 object = QPDFObjectHandle::newNull();
116 126 state = st_top;
117 127 } else {
118   - olist_stack.push_back(OHVector());
119 128 state = st_start;
120   - offset_stack.push_back(input->tell());
121 129 state_stack.push_back(
122 130 (token.getType() == QPDFTokenizer::tt_array_open)
123 131 ? st_array
124 132 : st_dictionary);
125 133 b_contents = false;
126   - contents_string_stack.push_back("");
127   - contents_offset_stack.push_back(-1);
  134 + stack.push_back(StackFrame(input));
128 135 }
129 136 break;
130 137  
... ... @@ -206,8 +213,8 @@ QPDFParser::parse(bool&amp; empty, bool content_stream)
206 213 std::string val = token.getValue();
207 214 if (decrypter) {
208 215 if (b_contents) {
209   - contents_string = val;
210   - contents_offset = input->getLastOffset();
  216 + frame.contents_string = val;
  217 + frame.contents_offset = input->getLastOffset();
211 218 b_contents = false;
212 219 }
213 220 decrypter->decryptString(val);
... ... @@ -279,7 +286,7 @@ QPDFParser::parse(bool&amp; empty, bool content_stream)
279 286 break;
280 287  
281 288 case st_stop:
282   - if ((state_stack.size() < 2) || (olist_stack.size() < 2)) {
  289 + if ((state_stack.size() < 2) || (stack.size() < 2)) {
283 290 throw std::logic_error(
284 291 "QPDFObjectHandle::parseInternal: st_stop encountered"
285 292 " with insufficient elements in stack");
... ... @@ -354,13 +361,13 @@ QPDFParser::parse(bool&amp; empty, bool content_stream)
354 361 }
355 362 dict[key] = val;
356 363 }
357   - if (!contents_string.empty() && dict.count("/Type") &&
  364 + if (!frame.contents_string.empty() && dict.count("/Type") &&
358 365 dict["/Type"].isNameAndEquals("/Sig") &&
359 366 dict.count("/ByteRange") && dict.count("/Contents") &&
360 367 dict["/Contents"].isString()) {
361 368 dict["/Contents"] =
362   - QPDFObjectHandle::newString(contents_string);
363   - dict["/Contents"].setParsedOffset(contents_offset);
  369 + QPDFObjectHandle::newString(frame.contents_string);
  370 + dict["/Contents"].setParsedOffset(frame.contents_offset);
364 371 }
365 372 object = QPDFObjectHandle::newDictionary(dict);
366 373 setDescriptionFromInput(object, offset);
... ... @@ -372,15 +379,12 @@ QPDFParser::parse(bool&amp; empty, bool content_stream)
372 379 object.setParsedOffset(offset - 2);
373 380 set_offset = true;
374 381 }
375   - olist_stack.pop_back();
376   - offset_stack.pop_back();
  382 + stack.pop_back();
377 383 if (state_stack.back() == st_top) {
378 384 done = true;
379 385 } else {
380   - olist_stack.back().push_back(object);
  386 + stack.back().olist.push_back(object);
381 387 }
382   - contents_string_stack.pop_back();
383   - contents_offset_stack.pop_back();
384 388 }
385 389 }
386 390  
... ...