Commit 1285f9767af983df74b52c4f2aadcbfaec36a6fc

Authored by m-holger
1 parent 605b1429

Add new method QPDFParser::fixMissingKeys

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&amp; 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;
... ...