Commit d825e00076826de87105efca9b57551d45f94cf7

Authored by m-holger
1 parent 5a8ba44b

Fix misleading warning/error messages in `pushInheritedAttributesToPage`: the ex…

…isting code used 'last_object_description' and reported the error against a random unrelated object.
libqpdf/QPDF_pages.cc
@@ -349,38 +349,39 @@ Pages::pushInheritedAttributesToPageInternal( @@ -349,38 +349,39 @@ Pages::pushInheritedAttributesToPageInternal(
349 throw QPDFExc( 349 throw QPDFExc(
350 qpdf_e_internal, 350 qpdf_e_internal,
351 m->file->getName(), 351 m->file->getName(),
352 - m->last_object_description,  
353 - m->file->getLastOffset(),  
354 - "optimize detected an inheritable attribute when called in no-change mode"); 352 + "/Pages object " + cur_pages.id_gen().unparse(' '),
  353 + cur_pages.offset(),
  354 + "pushInheritedAttributesToPage detected an inheritable attribute when called "
  355 + "in no-change mode");
355 } 356 }
356 357
357 // This is an inheritable resource 358 // This is an inheritable resource
358 inheritable_keys.insert(key); 359 inheritable_keys.insert(key);
359 - QPDFObjectHandle oh = cur_pages.getKey(key); 360 + auto oh = cur_pages[key];
360 QTC::TC("qpdf", "QPDF opt direct pages resource", oh.indirect() ? 0 : 1); 361 QTC::TC("qpdf", "QPDF opt direct pages resource", oh.indirect() ? 0 : 1);
361 if (!oh.indirect()) { 362 if (!oh.indirect()) {
362 if (!oh.isScalar()) { 363 if (!oh.isScalar()) {
363 // Replace shared direct object non-scalar resources with indirect objects to 364 // Replace shared direct object non-scalar resources with indirect objects to
364 // avoid copying large structures around. 365 // avoid copying large structures around.
365 cur_pages.replaceKey(key, qpdf.makeIndirectObject(oh)); 366 cur_pages.replaceKey(key, qpdf.makeIndirectObject(oh));
366 - oh = cur_pages.getKey(key); 367 + oh = cur_pages[key];
367 } else { 368 } else {
368 // It's okay to copy scalars. 369 // It's okay to copy scalars.
369 } 370 }
370 } 371 }
371 - key_ancestors[key].push_back(oh); 372 + key_ancestors[key].emplace_back(oh);
372 if (key_ancestors[key].size() > 1) { 373 if (key_ancestors[key].size() > 1) {
373 } 374 }
374 // Remove this resource from this node. It will be reattached at the page level. 375 // Remove this resource from this node. It will be reattached at the page level.
375 - cur_pages.removeKey(key); 376 + cur_pages.erase(key);
376 } else if (!(key == "/Type" || key == "/Parent" || key == "/Kids" || key == "/Count")) { 377 } else if (!(key == "/Type" || key == "/Parent" || key == "/Kids" || key == "/Count")) {
377 // Warn when flattening, but not if the key is at the top level (i.e. "/Parent" not 378 // Warn when flattening, but not if the key is at the top level (i.e. "/Parent" not
378 // set), as we don't change these; but flattening removes intermediate /Pages nodes. 379 // set), as we don't change these; but flattening removes intermediate /Pages nodes.
379 - if (warn_skipped_keys && cur_pages.hasKey("/Parent")) { 380 + if (warn_skipped_keys && cur_pages.contains("/Parent")) {
380 warn( 381 warn(
381 qpdf_e_pages, 382 qpdf_e_pages,
382 "Pages object: object " + cur_pages.id_gen().unparse(' '), 383 "Pages object: object " + cur_pages.id_gen().unparse(' '),
383 - 0, 384 + cur_pages.offset(),
384 ("Unknown key " + key + 385 ("Unknown key " + key +
385 " in /Pages object is being discarded as a result of flattening the /Pages " 386 " in /Pages object is being discarded as a result of flattening the /Pages "
386 "tree")); 387 "tree"));
@@ -391,16 +392,15 @@ Pages::pushInheritedAttributesToPageInternal( @@ -391,16 +392,15 @@ Pages::pushInheritedAttributesToPageInternal(
391 // Process descendant nodes. This method does not perform loop detection because all code paths 392 // Process descendant nodes. This method does not perform loop detection because all code paths
392 // that lead here follow a call to getAllPages, which already throws an exception in the event 393 // that lead here follow a call to getAllPages, which already throws an exception in the event
393 // of a loop in the pages tree. 394 // of a loop in the pages tree.
394 - for (auto& kid: cur_pages.getKey("/Kids").aitems()) { 395 + for (auto& kid: Array(cur_pages["/Kids"])) {
395 if (kid.isDictionaryOfType("/Pages")) { 396 if (kid.isDictionaryOfType("/Pages")) {
396 pushInheritedAttributesToPageInternal( 397 pushInheritedAttributesToPageInternal(
397 kid, key_ancestors, allow_changes, warn_skipped_keys); 398 kid, key_ancestors, allow_changes, warn_skipped_keys);
398 } else { 399 } else {
399 // Add all available inheritable attributes not present in this object to this object. 400 // Add all available inheritable attributes not present in this object to this object.
400 - for (auto const& iter: key_ancestors) {  
401 - std::string const& key = iter.first;  
402 - if (!kid.hasKey(key)) {  
403 - kid.replaceKey(key, iter.second.back()); 401 + for (auto const& [key, values]: key_ancestors) {
  402 + if (!kid.contains(key)) {
  403 + kid.replaceKey(key, values.back());
404 } else { 404 } else {
405 QTC::TC("qpdf", "QPDF opt page resource hides ancestor"); 405 QTC::TC("qpdf", "QPDF opt page resource hides ancestor");
406 } 406 }
qpdf/qtest/qpdf/issue-99.out
@@ -19,6 +19,5 @@ WARNING: issue-99.pdf (object 11 0, offset 4497): unexpected array close token; @@ -19,6 +19,5 @@ WARNING: issue-99.pdf (object 11 0, offset 4497): unexpected array close token;
19 WARNING: issue-99.pdf (object 11 0, offset 4499): expected endobj 19 WARNING: issue-99.pdf (object 11 0, offset 4499): expected endobj
20 WARNING: issue-99.pdf: unable to find trailer dictionary while recovering damaged file 20 WARNING: issue-99.pdf: unable to find trailer dictionary while recovering damaged file
21 WARNING: object 1 0: Pages tree includes non-dictionary object; ignoring 21 WARNING: object 1 0: Pages tree includes non-dictionary object; ignoring
22 -WARNING: object 1 0: operation for dictionary attempted on object of type null: returning false for a key containment request  
23 WARNING: object 1 0: operation for dictionary attempted on object of type null: ignoring key replacement request 22 WARNING: object 1 0: operation for dictionary attempted on object of type null: ignoring key replacement request
24 qpdf: issue-99.pdf: unable to find any pages while recovering damaged file 23 qpdf: issue-99.pdf: unable to find any pages while recovering damaged file
qpdf/qtest/qpdf/pages-warning.out
1 -WARNING: lin-special.pdf (Pages object: object 6 0): Unknown key /Quack in /Pages object is being discarded as a result of flattening the /Pages tree 1 +WARNING: lin-special.pdf (Pages object: object 6 0, offset 1857): Unknown key /Quack in /Pages object is being discarded as a result of flattening the /Pages tree
2 test 23 done 2 test 23 done