Commit 12837f14b6c793313778ca13ca3f8e615d41117b
1 parent
26e0bf46
In QPDFParser::parse refactor handling of array_close tokens
Showing
1 changed file
with
17 additions
and
12 deletions
libqpdf/QPDFParser.cc
| @@ -112,7 +112,20 @@ QPDFParser::parse(bool& empty, bool content_stream) | @@ -112,7 +112,20 @@ QPDFParser::parse(bool& empty, bool content_stream) | ||
| 112 | 112 | ||
| 113 | case QPDFTokenizer::tt_array_close: | 113 | case QPDFTokenizer::tt_array_close: |
| 114 | if (state == st_array) { | 114 | if (state == st_array) { |
| 115 | - state = st_stop; | 115 | + if ((state_stack.size() < 2) || (stack.size() < 2)) { |
| 116 | + throw std::logic_error("QPDFParser::parseInternal: st_stop encountered with " | ||
| 117 | + "insufficient elements in stack"); | ||
| 118 | + } | ||
| 119 | + object = QPDF_Array::create(std::move(olist), frame.null_count > 100); | ||
| 120 | + setDescription(object, offset - 1); | ||
| 121 | + // The `offset` points to the next of "[". Set the rewind offset to point to the | ||
| 122 | + // beginning of "[". This has been explicitly tested with whitespace surrounding the | ||
| 123 | + // array start delimiter. getLastOffset points to the array end token and therefore | ||
| 124 | + // can't be used here. | ||
| 125 | + set_offset = true; | ||
| 126 | + state_stack.pop_back(); | ||
| 127 | + state = state_stack.back(); | ||
| 128 | + stack.pop_back(); | ||
| 116 | } else { | 129 | } else { |
| 117 | QTC::TC("qpdf", "QPDFParser bad array close"); | 130 | QTC::TC("qpdf", "QPDFParser bad array close"); |
| 118 | warn("treating unexpected array close token as null"); | 131 | warn("treating unexpected array close token as null"); |
| @@ -273,11 +286,11 @@ QPDFParser::parse(bool& empty, bool content_stream) | @@ -273,11 +286,11 @@ QPDFParser::parse(bool& empty, bool content_stream) | ||
| 273 | if (is_null) { | 286 | if (is_null) { |
| 274 | object = null_oh; | 287 | object = null_oh; |
| 275 | // No need to set description for direct nulls - they probably will become implicit. | 288 | // No need to set description for direct nulls - they probably will become implicit. |
| 276 | - } else if (!indirect_ref) { | 289 | + } else if (!indirect_ref && !set_offset) { |
| 277 | setDescription(object, input->getLastOffset()); | 290 | setDescription(object, input->getLastOffset()); |
| 278 | } | 291 | } |
| 279 | set_offset = true; | 292 | set_offset = true; |
| 280 | - olist.push_back(object); | 293 | + stack.back().olist.push_back(object); |
| 281 | break; | 294 | break; |
| 282 | 295 | ||
| 283 | case st_top: | 296 | case st_top: |
| @@ -294,15 +307,7 @@ QPDFParser::parse(bool& empty, bool content_stream) | @@ -294,15 +307,7 @@ QPDFParser::parse(bool& empty, bool content_stream) | ||
| 294 | } | 307 | } |
| 295 | parser_state_e old_state = state_stack.back(); | 308 | parser_state_e old_state = state_stack.back(); |
| 296 | state_stack.pop_back(); | 309 | state_stack.pop_back(); |
| 297 | - if (old_state == st_array) { | ||
| 298 | - object = QPDF_Array::create(std::move(olist), frame.null_count > 100); | ||
| 299 | - setDescription(object, offset - 1); | ||
| 300 | - // The `offset` points to the next of "[". Set the rewind offset to point to the | ||
| 301 | - // beginning of "[". This has been explicitly tested with whitespace surrounding the | ||
| 302 | - // array start delimiter. getLastOffset points to the array end token and therefore | ||
| 303 | - // can't be used here. | ||
| 304 | - set_offset = true; | ||
| 305 | - } else if (old_state == st_dictionary) { | 310 | + if (old_state == st_dictionary) { |
| 306 | // Convert list to map. Alternating elements are keys. Attempt to recover more or | 311 | // Convert list to map. Alternating elements are keys. Attempt to recover more or |
| 307 | // less gracefully from invalid dictionaries. | 312 | // less gracefully from invalid dictionaries. |
| 308 | std::set<std::string> names; | 313 | std::set<std::string> names; |