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,8 +244,8 @@ QPDFParser::parseRemainder(bool content_stream)
244 case QPDFTokenizer::tt_dict_close: 244 case QPDFTokenizer::tt_dict_close:
245 if (frame->state <= st_dictionary_value) { 245 if (frame->state <= st_dictionary_value) {
246 // Attempt to recover more or less gracefully from invalid dictionaries. 246 // Attempt to recover more or less gracefully from invalid dictionaries.
247 -  
248 auto& dict = frame->dict; 247 auto& dict = frame->dict;
  248 +
249 if (frame->state == st_dictionary_value) { 249 if (frame->state == st_dictionary_value) {
250 QTC::TC("qpdf", "QPDFParser no val for last key"); 250 QTC::TC("qpdf", "QPDFParser no val for last key");
251 warn( 251 warn(
@@ -254,31 +254,8 @@ QPDFParser::parseRemainder(bool content_stream) @@ -254,31 +254,8 @@ QPDFParser::parseRemainder(bool content_stream)
254 dict[frame->key] = QPDF_Null::create(); 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 if (!frame->contents_string.empty() && dict.count("/Type") && 260 if (!frame->contents_string.empty() && dict.count("/Type") &&
284 dict["/Type"].isNameAndEquals("/Sig") && dict.count("/ByteRange") && 261 dict["/Type"].isNameAndEquals("/Sig") && dict.count("/ByteRange") &&
@@ -466,6 +443,32 @@ QPDFParser::setDescription(ObjectPtr&amp; obj, qpdf_offset_t parsed_offset) @@ -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 bool 472 bool
470 QPDFParser::tooManyBadTokens() 473 QPDFParser::tooManyBadTokens()
471 { 474 {
libqpdf/qpdf/QPDFParser.hh
@@ -61,6 +61,7 @@ class QPDFParser @@ -61,6 +61,7 @@ class QPDFParser
61 void addScalar(Args&&... args); 61 void addScalar(Args&&... args);
62 bool tooManyBadTokens(); 62 bool tooManyBadTokens();
63 void warnDuplicateKey(); 63 void warnDuplicateKey();
  64 + void fixMissingKeys();
64 void warn(qpdf_offset_t offset, std::string const& msg) const; 65 void warn(qpdf_offset_t offset, std::string const& msg) const;
65 void warn(std::string const& msg) const; 66 void warn(std::string const& msg) const;
66 void warn(QPDFExc const&) const; 67 void warn(QPDFExc const&) const;