Commit 1285f9767af983df74b52c4f2aadcbfaec36a6fc
1 parent
605b1429
Add new method QPDFParser::fixMissingKeys
Showing
2 changed files
with
30 additions
and
26 deletions
libqpdf/QPDFParser.cc
| ... | ... | @@ -244,8 +244,8 @@ QPDFParser::parseRemainder(bool content_stream) |
| 244 | 244 | case QPDFTokenizer::tt_dict_close: |
| 245 | 245 | if (frame->state <= st_dictionary_value) { |
| 246 | 246 | // Attempt to recover more or less gracefully from invalid dictionaries. |
| 247 | - | |
| 248 | 247 | auto& dict = frame->dict; |
| 248 | + | |
| 249 | 249 | if (frame->state == st_dictionary_value) { |
| 250 | 250 | QTC::TC("qpdf", "QPDFParser no val for last key"); |
| 251 | 251 | warn( |
| ... | ... | @@ -254,31 +254,8 @@ QPDFParser::parseRemainder(bool content_stream) |
| 254 | 254 | dict[frame->key] = QPDF_Null::create(); |
| 255 | 255 | } |
| 256 | 256 | |
| 257 | - if (!frame->olist.empty()) { | |
| 258 | - std::set<std::string> names; | |
| 259 | - for (auto& obj: frame->olist) { | |
| 260 | - if (obj->getTypeCode() == ::ot_name) { | |
| 261 | - names.insert(obj->getStringValue()); | |
| 262 | - } | |
| 263 | - } | |
| 264 | - int next_fake_key = 1; | |
| 265 | - for (auto const& item: frame->olist) { | |
| 266 | - while (true) { | |
| 267 | - const std::string key = "/QPDFFake" + std::to_string(next_fake_key++); | |
| 268 | - const bool found_fake = (dict.count(key) == 0 && names.count(key) == 0); | |
| 269 | - QTC::TC("qpdf", "QPDFParser found fake", (found_fake ? 0 : 1)); | |
| 270 | - if (found_fake) { | |
| 271 | - warn( | |
| 272 | - frame->offset, | |
| 273 | - "expected dictionary key but found non-name object; inserting " | |
| 274 | - "key " + | |
| 275 | - key); | |
| 276 | - dict[key] = item; | |
| 277 | - break; | |
| 278 | - } | |
| 279 | - } | |
| 280 | - } | |
| 281 | - } | |
| 257 | + if (!frame->olist.empty()) | |
| 258 | + fixMissingKeys(); | |
| 282 | 259 | |
| 283 | 260 | if (!frame->contents_string.empty() && dict.count("/Type") && |
| 284 | 261 | dict["/Type"].isNameAndEquals("/Sig") && dict.count("/ByteRange") && |
| ... | ... | @@ -466,6 +443,32 @@ QPDFParser::setDescription(ObjectPtr& obj, qpdf_offset_t parsed_offset) |
| 466 | 443 | } |
| 467 | 444 | } |
| 468 | 445 | |
| 446 | +void | |
| 447 | +QPDFParser::fixMissingKeys() | |
| 448 | +{ | |
| 449 | + std::set<std::string> names; | |
| 450 | + for (auto& obj: frame->olist) { | |
| 451 | + if (obj->getTypeCode() == ::ot_name) { | |
| 452 | + names.insert(obj->getStringValue()); | |
| 453 | + } | |
| 454 | + } | |
| 455 | + int next_fake_key = 1; | |
| 456 | + for (auto const& item: frame->olist) { | |
| 457 | + while (true) { | |
| 458 | + const std::string key = "/QPDFFake" + std::to_string(next_fake_key++); | |
| 459 | + const bool found_fake = frame->dict.count(key) == 0 && names.count(key) == 0; | |
| 460 | + QTC::TC("qpdf", "QPDFParser found fake", (found_fake ? 0 : 1)); | |
| 461 | + if (found_fake) { | |
| 462 | + warn( | |
| 463 | + frame->offset, | |
| 464 | + "expected dictionary key but found non-name object; inserting key " + key); | |
| 465 | + frame->dict[key] = item; | |
| 466 | + break; | |
| 467 | + } | |
| 468 | + } | |
| 469 | + } | |
| 470 | +} | |
| 471 | + | |
| 469 | 472 | bool |
| 470 | 473 | QPDFParser::tooManyBadTokens() |
| 471 | 474 | { | ... | ... |
libqpdf/qpdf/QPDFParser.hh
| ... | ... | @@ -61,6 +61,7 @@ class QPDFParser |
| 61 | 61 | void addScalar(Args&&... args); |
| 62 | 62 | bool tooManyBadTokens(); |
| 63 | 63 | void warnDuplicateKey(); |
| 64 | + void fixMissingKeys(); | |
| 64 | 65 | void warn(qpdf_offset_t offset, std::string const& msg) const; |
| 65 | 66 | void warn(std::string const& msg) const; |
| 66 | 67 | void warn(QPDFExc const&) const; | ... | ... |