Commit 06db6493a1776bfda78314697f2f2e4393d9dea4
1 parent
decc7d3c
Refactor `QPDFObjectHandle` warnings: replace `warnIfPossible` with centralized …
…`warn`, streamline condition handling.
Showing
10 changed files
with
75 additions
and
87 deletions
libqpdf/QPDFAcroFormDocumentHelper.cc
| @@ -8,6 +8,7 @@ | @@ -8,6 +8,7 @@ | ||
| 8 | #include <qpdf/ResourceFinder.hh> | 8 | #include <qpdf/ResourceFinder.hh> |
| 9 | 9 | ||
| 10 | using namespace qpdf; | 10 | using namespace qpdf; |
| 11 | +using namespace std::literals; | ||
| 11 | 12 | ||
| 12 | QPDFAcroFormDocumentHelper::QPDFAcroFormDocumentHelper(QPDF& qpdf) : | 13 | QPDFAcroFormDocumentHelper::QPDFAcroFormDocumentHelper(QPDF& qpdf) : |
| 13 | QPDFDocumentHelper(qpdf), | 14 | QPDFDocumentHelper(qpdf), |
| @@ -251,7 +252,7 @@ QPDFAcroFormDocumentHelper::analyze() | @@ -251,7 +252,7 @@ QPDFAcroFormDocumentHelper::analyze() | ||
| 251 | } | 252 | } |
| 252 | } else { | 253 | } else { |
| 253 | QTC::TC("qpdf", "QPDFAcroFormDocumentHelper fields not array"); | 254 | QTC::TC("qpdf", "QPDFAcroFormDocumentHelper fields not array"); |
| 254 | - acroform.warnIfPossible("/Fields key of /AcroForm dictionary is not an array; ignoring"); | 255 | + acroform.warn("/Fields key of /AcroForm dictionary is not an array; ignoring"); |
| 255 | fields = QPDFObjectHandle::newArray(); | 256 | fields = QPDFObjectHandle::newArray(); |
| 256 | } | 257 | } |
| 257 | 258 | ||
| @@ -273,9 +274,9 @@ QPDFAcroFormDocumentHelper::analyze() | @@ -273,9 +274,9 @@ QPDFAcroFormDocumentHelper::analyze() | ||
| 273 | // case such as a PDF creator adding a self-contained annotation (merged with the | 274 | // case such as a PDF creator adding a self-contained annotation (merged with the |
| 274 | // field dictionary) to the page's /Annots array and forgetting to also put it in | 275 | // field dictionary) to the page's /Annots array and forgetting to also put it in |
| 275 | // /AcroForm. | 276 | // /AcroForm. |
| 276 | - annot.warnIfPossible( | ||
| 277 | - "this widget annotation is not" | ||
| 278 | - " reachable from /AcroForm in the document catalog"); | 277 | + annot.warn( |
| 278 | + "this widget annotation is not reachable from /AcroForm in the document " | ||
| 279 | + "catalog"); | ||
| 279 | m->annotation_to_field[og] = QPDFFormFieldObjectHelper(annot); | 280 | m->annotation_to_field[og] = QPDFFormFieldObjectHelper(annot); |
| 280 | m->field_to_annotations[og].emplace_back(annot); | 281 | m->field_to_annotations[og].emplace_back(annot); |
| 281 | } | 282 | } |
| @@ -292,16 +293,16 @@ QPDFAcroFormDocumentHelper::traverseField( | @@ -292,16 +293,16 @@ QPDFAcroFormDocumentHelper::traverseField( | ||
| 292 | // could cause stack overflow. | 293 | // could cause stack overflow. |
| 293 | return; | 294 | return; |
| 294 | } | 295 | } |
| 295 | - if (!field.isIndirect()) { | 296 | + if (!field.indirect()) { |
| 296 | QTC::TC("qpdf", "QPDFAcroFormDocumentHelper direct field"); | 297 | QTC::TC("qpdf", "QPDFAcroFormDocumentHelper direct field"); |
| 297 | - field.warnIfPossible( | 298 | + field.warn( |
| 298 | "encountered a direct object as a field or annotation while " | 299 | "encountered a direct object as a field or annotation while " |
| 299 | "traversing /AcroForm; ignoring field or annotation"); | 300 | "traversing /AcroForm; ignoring field or annotation"); |
| 300 | return; | 301 | return; |
| 301 | } | 302 | } |
| 302 | if (!field.isDictionary()) { | 303 | if (!field.isDictionary()) { |
| 303 | QTC::TC("qpdf", "QPDFAcroFormDocumentHelper non-dictionary field"); | 304 | QTC::TC("qpdf", "QPDFAcroFormDocumentHelper non-dictionary field"); |
| 304 | - field.warnIfPossible( | 305 | + field.warn( |
| 305 | "encountered a non-dictionary as a field or annotation while" | 306 | "encountered a non-dictionary as a field or annotation while" |
| 306 | " traversing /AcroForm; ignoring field or annotation"); | 307 | " traversing /AcroForm; ignoring field or annotation"); |
| 307 | return; | 308 | return; |
| @@ -309,7 +310,7 @@ QPDFAcroFormDocumentHelper::traverseField( | @@ -309,7 +310,7 @@ QPDFAcroFormDocumentHelper::traverseField( | ||
| 309 | QPDFObjGen og(field.getObjGen()); | 310 | QPDFObjGen og(field.getObjGen()); |
| 310 | if (!visited.add(og)) { | 311 | if (!visited.add(og)) { |
| 311 | QTC::TC("qpdf", "QPDFAcroFormDocumentHelper loop"); | 312 | QTC::TC("qpdf", "QPDFAcroFormDocumentHelper loop"); |
| 312 | - field.warnIfPossible("loop detected while traversing /AcroForm"); | 313 | + field.warn("loop detected while traversing /AcroForm"); |
| 313 | return; | 314 | return; |
| 314 | } | 315 | } |
| 315 | 316 | ||
| @@ -375,7 +376,7 @@ QPDFAcroFormDocumentHelper::setNeedAppearances(bool val) | @@ -375,7 +376,7 @@ QPDFAcroFormDocumentHelper::setNeedAppearances(bool val) | ||
| 375 | { | 376 | { |
| 376 | QPDFObjectHandle acroform = qpdf.getRoot().getKey("/AcroForm"); | 377 | QPDFObjectHandle acroform = qpdf.getRoot().getKey("/AcroForm"); |
| 377 | if (!acroform.isDictionary()) { | 378 | if (!acroform.isDictionary()) { |
| 378 | - qpdf.getRoot().warnIfPossible( | 379 | + qpdf.getRoot().warn( |
| 379 | "ignoring call to QPDFAcroFormDocumentHelper::setNeedAppearances" | 380 | "ignoring call to QPDFAcroFormDocumentHelper::setNeedAppearances" |
| 380 | " on a file that lacks an /AcroForm dictionary"); | 381 | " on a file that lacks an /AcroForm dictionary"); |
| 381 | return; | 382 | return; |
| @@ -592,9 +593,7 @@ QPDFAcroFormDocumentHelper::adjustDefaultAppearances( | @@ -592,9 +593,7 @@ QPDFAcroFormDocumentHelper::adjustDefaultAppearances( | ||
| 592 | } catch (std::exception& e) { | 593 | } catch (std::exception& e) { |
| 593 | // No way to reproduce in test suite right now since error conditions are converted to | 594 | // No way to reproduce in test suite right now since error conditions are converted to |
| 594 | // warnings. | 595 | // warnings. |
| 595 | - obj.warnIfPossible( | ||
| 596 | - std::string("Unable to parse /DA: ") + e.what() + | ||
| 597 | - "; this form field may not update properly"); | 596 | + obj.warn("Unable to parse /DA: "s + e.what() + "; this form field may not update properly"); |
| 598 | return; | 597 | return; |
| 599 | } | 598 | } |
| 600 | 599 | ||
| @@ -677,16 +676,17 @@ QPDFAcroFormDocumentHelper::adjustAppearanceStream( | @@ -677,16 +676,17 @@ QPDFAcroFormDocumentHelper::adjustAppearanceStream( | ||
| 677 | try { | 676 | try { |
| 678 | auto nwarnings = qpdf.numWarnings(); | 677 | auto nwarnings = qpdf.numWarnings(); |
| 679 | stream.parseAsContents(&rf); | 678 | stream.parseAsContents(&rf); |
| 680 | - if (qpdf.numWarnings() > nwarnings) { | ||
| 681 | - QTC::TC("qpdf", "QPDFAcroFormDocumentHelper AP parse error"); | ||
| 682 | - } | 679 | + QTC::TC( |
| 680 | + "qpdf", | ||
| 681 | + "QPDFAcroFormDocumentHelper AP parse error", | ||
| 682 | + qpdf.numWarnings() > nwarnings ? 0 : 1); | ||
| 683 | auto rr = new ResourceReplacer(dr_map, rf.getNamesByResourceType()); | 683 | auto rr = new ResourceReplacer(dr_map, rf.getNamesByResourceType()); |
| 684 | auto tf = std::shared_ptr<QPDFObjectHandle::TokenFilter>(rr); | 684 | auto tf = std::shared_ptr<QPDFObjectHandle::TokenFilter>(rr); |
| 685 | stream.addTokenFilter(tf); | 685 | stream.addTokenFilter(tf); |
| 686 | } catch (std::exception& e) { | 686 | } catch (std::exception& e) { |
| 687 | // No way to reproduce in test suite right now since error conditions are converted to | 687 | // No way to reproduce in test suite right now since error conditions are converted to |
| 688 | // warnings. | 688 | // warnings. |
| 689 | - stream.warnIfPossible(std::string("Unable to parse appearance stream: ") + e.what()); | 689 | + stream.warn("Unable to parse appearance stream: "s + e.what()); |
| 690 | } | 690 | } |
| 691 | } | 691 | } |
| 692 | 692 | ||
| @@ -814,7 +814,7 @@ QPDFAcroFormDocumentHelper::transformAnnotations( | @@ -814,7 +814,7 @@ QPDFAcroFormDocumentHelper::transformAnnotations( | ||
| 814 | QPDFObjGen::set added_new_fields; | 814 | QPDFObjGen::set added_new_fields; |
| 815 | for (auto annot: old_annots.aitems()) { | 815 | for (auto annot: old_annots.aitems()) { |
| 816 | if (annot.isStream()) { | 816 | if (annot.isStream()) { |
| 817 | - annot.warnIfPossible("ignoring annotation that's a stream"); | 817 | + annot.warn("ignoring annotation that's a stream"); |
| 818 | continue; | 818 | continue; |
| 819 | } | 819 | } |
| 820 | 820 | ||
| @@ -847,10 +847,10 @@ QPDFAcroFormDocumentHelper::transformAnnotations( | @@ -847,10 +847,10 @@ QPDFAcroFormDocumentHelper::transformAnnotations( | ||
| 847 | bool have_field = false; | 847 | bool have_field = false; |
| 848 | bool have_parent = false; | 848 | bool have_parent = false; |
| 849 | if (ffield_oh.isStream()) { | 849 | if (ffield_oh.isStream()) { |
| 850 | - ffield_oh.warnIfPossible("ignoring form field that's a stream"); | 850 | + ffield.warn("ignoring form field that's a stream"); |
| 851 | } else if ((!ffield_oh.isNull()) && (!ffield_oh.isIndirect())) { | 851 | } else if ((!ffield_oh.isNull()) && (!ffield_oh.isIndirect())) { |
| 852 | - ffield_oh.warnIfPossible("ignoring form field not indirect"); | ||
| 853 | - } else if (!ffield_oh.isNull()) { | 852 | + ffield.warn("ignoring form field not indirect"); |
| 853 | + } else if (!ffield.null()) { | ||
| 854 | // A field and its associated annotation can be the same object. This matters because we | 854 | // A field and its associated annotation can be the same object. This matters because we |
| 855 | // don't want to clone the annotation and field separately in this case. | 855 | // don't want to clone the annotation and field separately in this case. |
| 856 | have_field = true; | 856 | have_field = true; |
| @@ -888,7 +888,7 @@ QPDFAcroFormDocumentHelper::transformAnnotations( | @@ -888,7 +888,7 @@ QPDFAcroFormDocumentHelper::transformAnnotations( | ||
| 888 | if (orig_to_copy.contains(parent_og)) { | 888 | if (orig_to_copy.contains(parent_og)) { |
| 889 | obj.replaceKey("/Parent", orig_to_copy[parent_og]); | 889 | obj.replaceKey("/Parent", orig_to_copy[parent_og]); |
| 890 | } else { | 890 | } else { |
| 891 | - parent.warnIfPossible( | 891 | + parent.warn( |
| 892 | "while traversing field " + obj.getObjGen().unparse(',') + | 892 | "while traversing field " + obj.getObjGen().unparse(',') + |
| 893 | ", found parent (" + parent_og.unparse(',') + | 893 | ", found parent (" + parent_og.unparse(',') + |
| 894 | ") that had not been seen, indicating likely invalid field " | 894 | ") that had not been seen, indicating likely invalid field " |
libqpdf/QPDFEFStreamObjectHelper.cc
| @@ -138,7 +138,7 @@ QPDFEFStreamObjectHelper::newFromStream(QPDFObjectHandle stream) | @@ -138,7 +138,7 @@ QPDFEFStreamObjectHelper::newFromStream(QPDFObjectHandle stream) | ||
| 138 | Pl_MD5 md5("EF md5", &discard); | 138 | Pl_MD5 md5("EF md5", &discard); |
| 139 | Pl_Count count("EF size", &md5); | 139 | Pl_Count count("EF size", &md5); |
| 140 | if (!stream.pipeStreamData(&count, nullptr, 0, qpdf_dl_all)) { | 140 | if (!stream.pipeStreamData(&count, nullptr, 0, qpdf_dl_all)) { |
| 141 | - stream.warnIfPossible("unable to get stream data for new embedded file stream"); | 141 | + stream.warn("unable to get stream data for new embedded file stream"); |
| 142 | } else { | 142 | } else { |
| 143 | result.setParam("/Size", QPDFObjectHandle::newInteger(count.getCount())); | 143 | result.setParam("/Size", QPDFObjectHandle::newInteger(count.getCount())); |
| 144 | result.setParam( | 144 | result.setParam( |
libqpdf/QPDFFileSpecObjectHelper.cc
| @@ -4,32 +4,33 @@ | @@ -4,32 +4,33 @@ | ||
| 4 | #include <qpdf/QTC.hh> | 4 | #include <qpdf/QTC.hh> |
| 5 | #include <qpdf/QUtil.hh> | 5 | #include <qpdf/QUtil.hh> |
| 6 | 6 | ||
| 7 | +#include <array> | ||
| 7 | #include <string> | 8 | #include <string> |
| 8 | -#include <vector> | 9 | + |
| 10 | +using namespace std::literals; | ||
| 9 | 11 | ||
| 10 | QPDFFileSpecObjectHelper::QPDFFileSpecObjectHelper(QPDFObjectHandle oh) : | 12 | QPDFFileSpecObjectHelper::QPDFFileSpecObjectHelper(QPDFObjectHandle oh) : |
| 11 | QPDFObjectHelper(oh) | 13 | QPDFObjectHelper(oh) |
| 12 | { | 14 | { |
| 13 | if (!oh.isDictionary()) { | 15 | if (!oh.isDictionary()) { |
| 14 | - oh.warnIfPossible("Embedded file object is not a dictionary"); | 16 | + warn("Embedded file object is not a dictionary"); |
| 15 | return; | 17 | return; |
| 16 | } | 18 | } |
| 17 | if (!oh.isDictionaryOfType("/Filespec")) { | 19 | if (!oh.isDictionaryOfType("/Filespec")) { |
| 18 | - oh.warnIfPossible("Embedded file object's type is not /Filespec"); | 20 | + warn("Embedded file object's type is not /Filespec"); |
| 19 | } | 21 | } |
| 20 | } | 22 | } |
| 21 | 23 | ||
| 22 | -static std::vector<std::string> name_keys = {"/UF", "/F", "/Unix", "/DOS", "/Mac"}; | 24 | +static const std::array<std::string, 5> name_keys = {"/UF"s, "/F"s, "/Unix"s, "/DOS"s, "/Mac"s}; |
| 23 | 25 | ||
| 24 | std::string | 26 | std::string |
| 25 | QPDFFileSpecObjectHelper::getDescription() | 27 | QPDFFileSpecObjectHelper::getDescription() |
| 26 | { | 28 | { |
| 27 | - std::string result; | ||
| 28 | auto desc = oh().getKey("/Desc"); | 29 | auto desc = oh().getKey("/Desc"); |
| 29 | if (desc.isString()) { | 30 | if (desc.isString()) { |
| 30 | - result = desc.getUTF8Value(); | 31 | + return desc.getUTF8Value(); |
| 31 | } | 32 | } |
| 32 | - return result; | 33 | + return {}; |
| 33 | } | 34 | } |
| 34 | 35 | ||
| 35 | std::string | 36 | std::string |
libqpdf/QPDFFormFieldObjectHelper.cc
| @@ -317,18 +317,17 @@ QPDFFormFieldObjectHelper::setV(QPDFObjectHandle value, bool need_appearances) | @@ -317,18 +317,17 @@ QPDFFormFieldObjectHelper::setV(QPDFObjectHandle value, bool need_appearances) | ||
| 317 | setCheckBoxValue((name != "/Off")); | 317 | setCheckBoxValue((name != "/Off")); |
| 318 | } | 318 | } |
| 319 | if (!okay) { | 319 | if (!okay) { |
| 320 | - oh().warnIfPossible( | ||
| 321 | - "ignoring attempt to set a checkbox field to a value whose type is not name"); | 320 | + warn("ignoring attempt to set a checkbox field to a value whose type is not name"); |
| 322 | } | 321 | } |
| 323 | } else if (isRadioButton()) { | 322 | } else if (isRadioButton()) { |
| 324 | if (value.isName()) { | 323 | if (value.isName()) { |
| 325 | setRadioButtonValue(value); | 324 | setRadioButtonValue(value); |
| 326 | } else { | 325 | } else { |
| 327 | - oh().warnIfPossible( | 326 | + warn( |
| 328 | "ignoring attempt to set a radio button field to an object that is not a name"); | 327 | "ignoring attempt to set a radio button field to an object that is not a name"); |
| 329 | } | 328 | } |
| 330 | } else if (isPushbutton()) { | 329 | } else if (isPushbutton()) { |
| 331 | - oh().warnIfPossible("ignoring attempt set the value of a pushbutton field"); | 330 | + warn("ignoring attempt set the value of a pushbutton field"); |
| 332 | } | 331 | } |
| 333 | return; | 332 | return; |
| 334 | } | 333 | } |
| @@ -375,7 +374,7 @@ QPDFFormFieldObjectHelper::setRadioButtonValue(QPDFObjectHandle name) | @@ -375,7 +374,7 @@ QPDFFormFieldObjectHelper::setRadioButtonValue(QPDFObjectHandle name) | ||
| 375 | 374 | ||
| 376 | QPDFObjectHandle kids = oh().getKey("/Kids"); | 375 | QPDFObjectHandle kids = oh().getKey("/Kids"); |
| 377 | if (!(isRadioButton() && parent.isNull() && kids.isArray())) { | 376 | if (!(isRadioButton() && parent.isNull() && kids.isArray())) { |
| 378 | - oh().warnIfPossible("don't know how to set the value of this field as a radio button"); | 377 | + warn("don't know how to set the value of this field as a radio button"); |
| 379 | return; | 378 | return; |
| 380 | } | 379 | } |
| 381 | setFieldAttribute("/V", name); | 380 | setFieldAttribute("/V", name); |
| @@ -397,7 +396,7 @@ QPDFFormFieldObjectHelper::setRadioButtonValue(QPDFObjectHandle name) | @@ -397,7 +396,7 @@ QPDFFormFieldObjectHelper::setRadioButtonValue(QPDFObjectHandle name) | ||
| 397 | } | 396 | } |
| 398 | if (!annot) { | 397 | if (!annot) { |
| 399 | QTC::TC("qpdf", "QPDFObjectHandle broken radio button"); | 398 | QTC::TC("qpdf", "QPDFObjectHandle broken radio button"); |
| 400 | - oh().warnIfPossible("unable to set the value of this radio button"); | 399 | + warn("unable to set the value of this radio button"); |
| 401 | continue; | 400 | continue; |
| 402 | } | 401 | } |
| 403 | if (AP.isDictionary() && AP.getKey("/N").isDictionary() && | 402 | if (AP.isDictionary() && AP.getKey("/N").isDictionary() && |
| @@ -453,7 +452,7 @@ QPDFFormFieldObjectHelper::setCheckBoxValue(bool value) | @@ -453,7 +452,7 @@ QPDFFormFieldObjectHelper::setCheckBoxValue(bool value) | ||
| 453 | setFieldAttribute("/V", name); | 452 | setFieldAttribute("/V", name); |
| 454 | if (!annot) { | 453 | if (!annot) { |
| 455 | QTC::TC("qpdf", "QPDFObjectHandle broken checkbox"); | 454 | QTC::TC("qpdf", "QPDFObjectHandle broken checkbox"); |
| 456 | - oh().warnIfPossible("unable to set the value of this checkbox"); | 455 | + warn("unable to set the value of this checkbox"); |
| 457 | return; | 456 | return; |
| 458 | } | 457 | } |
| 459 | QTC::TC("qpdf", "QPDFFormFieldObjectHelper set checkbox AS"); | 458 | QTC::TC("qpdf", "QPDFFormFieldObjectHelper set checkbox AS"); |
| @@ -770,18 +769,17 @@ QPDFFormFieldObjectHelper::generateTextAppearance(QPDFAnnotationObjectHelper& ao | @@ -770,18 +769,17 @@ QPDFFormFieldObjectHelper::generateTextAppearance(QPDFAnnotationObjectHelper& ao | ||
| 770 | AP.replaceKey("/N", AS); | 769 | AP.replaceKey("/N", AS); |
| 771 | } | 770 | } |
| 772 | if (!AS.isStream()) { | 771 | if (!AS.isStream()) { |
| 773 | - aoh.getObjectHandle().warnIfPossible("unable to get normal appearance stream for update"); | 772 | + aoh.warn("unable to get normal appearance stream for update"); |
| 774 | return; | 773 | return; |
| 775 | } | 774 | } |
| 776 | 775 | ||
| 777 | if (AS.getObj().use_count() > 4) { | 776 | if (AS.getObj().use_count() > 4) { |
| 778 | - aoh.getObjectHandle().warnIfPossible( | ||
| 779 | - "unable to generate text appearance from shared appearance stream for update"); | 777 | + aoh.warn("unable to generate text appearance from shared appearance stream for update"); |
| 780 | return; | 778 | return; |
| 781 | } | 779 | } |
| 782 | QPDFObjectHandle bbox_obj = AS.getDict().getKey("/BBox"); | 780 | QPDFObjectHandle bbox_obj = AS.getDict().getKey("/BBox"); |
| 783 | if (!bbox_obj.isRectangle()) { | 781 | if (!bbox_obj.isRectangle()) { |
| 784 | - aoh.getObjectHandle().warnIfPossible("unable to get appearance stream bounding box"); | 782 | + aoh.warn("unable to get appearance stream bounding box"); |
| 785 | return; | 783 | return; |
| 786 | } | 784 | } |
| 787 | QPDFObjectHandle::Rectangle bbox = bbox_obj.getArrayAsRectangle(); | 785 | QPDFObjectHandle::Rectangle bbox = bbox_obj.getArrayAsRectangle(); |
libqpdf/QPDFObjectHandle.cc
| @@ -835,20 +835,16 @@ QPDFObjectHandle::getValueAsInt(long long& value) const | @@ -835,20 +835,16 @@ QPDFObjectHandle::getValueAsInt(long long& value) const | ||
| 835 | int | 835 | int |
| 836 | QPDFObjectHandle::getIntValueAsInt() const | 836 | QPDFObjectHandle::getIntValueAsInt() const |
| 837 | { | 837 | { |
| 838 | - int result = 0; | ||
| 839 | long long v = getIntValue(); | 838 | long long v = getIntValue(); |
| 840 | if (v < INT_MIN) { | 839 | if (v < INT_MIN) { |
| 841 | - QTC::TC("qpdf", "QPDFObjectHandle int returning INT_MIN"); | ||
| 842 | - warnIfPossible("requested value of integer is too small; returning INT_MIN"); | ||
| 843 | - result = INT_MIN; | ||
| 844 | - } else if (v > INT_MAX) { | ||
| 845 | - QTC::TC("qpdf", "QPDFObjectHandle int returning INT_MAX"); | ||
| 846 | - warnIfPossible("requested value of integer is too big; returning INT_MAX"); | ||
| 847 | - result = INT_MAX; | ||
| 848 | - } else { | ||
| 849 | - result = static_cast<int>(v); | 840 | + warn("requested value of integer is too small; returning INT_MIN"); |
| 841 | + return INT_MIN; | ||
| 850 | } | 842 | } |
| 851 | - return result; | 843 | + if (v > INT_MAX) { |
| 844 | + warn("requested value of integer is too big; returning INT_MAX"); | ||
| 845 | + return INT_MAX; | ||
| 846 | + } | ||
| 847 | + return static_cast<int>(v); | ||
| 852 | } | 848 | } |
| 853 | 849 | ||
| 854 | bool | 850 | bool |
| @@ -866,8 +862,7 @@ QPDFObjectHandle::getUIntValue() const | @@ -866,8 +862,7 @@ QPDFObjectHandle::getUIntValue() const | ||
| 866 | { | 862 | { |
| 867 | long long v = getIntValue(); | 863 | long long v = getIntValue(); |
| 868 | if (v < 0) { | 864 | if (v < 0) { |
| 869 | - QTC::TC("qpdf", "QPDFObjectHandle uint returning 0"); | ||
| 870 | - warnIfPossible("unsigned value request for negative number; returning 0"); | 865 | + warn("unsigned value request for negative number; returning 0"); |
| 871 | return 0; | 866 | return 0; |
| 872 | } else { | 867 | } else { |
| 873 | return static_cast<unsigned long long>(v); | 868 | return static_cast<unsigned long long>(v); |
| @@ -889,16 +884,14 @@ QPDFObjectHandle::getUIntValueAsUInt() const | @@ -889,16 +884,14 @@ QPDFObjectHandle::getUIntValueAsUInt() const | ||
| 889 | { | 884 | { |
| 890 | long long v = getIntValue(); | 885 | long long v = getIntValue(); |
| 891 | if (v < 0) { | 886 | if (v < 0) { |
| 892 | - QTC::TC("qpdf", "QPDFObjectHandle uint uint returning 0"); | ||
| 893 | - warnIfPossible("unsigned integer value request for negative number; returning 0"); | 887 | + warn("unsigned integer value request for negative number; returning 0"); |
| 894 | return 0; | 888 | return 0; |
| 895 | - } else if (v > UINT_MAX) { | ||
| 896 | - QTC::TC("qpdf", "QPDFObjectHandle uint returning UINT_MAX"); | ||
| 897 | - warnIfPossible("requested value of unsigned integer is too big; returning UINT_MAX"); | 889 | + } |
| 890 | + if (v > UINT_MAX) { | ||
| 891 | + warn("requested value of unsigned integer is too big; returning UINT_MAX"); | ||
| 898 | return UINT_MAX; | 892 | return UINT_MAX; |
| 899 | - } else { | ||
| 900 | - return static_cast<unsigned int>(v); | ||
| 901 | } | 893 | } |
| 894 | + return static_cast<unsigned int>(v); | ||
| 902 | } | 895 | } |
| 903 | 896 | ||
| 904 | bool | 897 | bool |
libqpdf/QPDFPageDocumentHelper.cc
| @@ -59,7 +59,7 @@ QPDFPageDocumentHelper::flattenAnnotations(int required_flags, int forbidden_fla | @@ -59,7 +59,7 @@ QPDFPageDocumentHelper::flattenAnnotations(int required_flags, int forbidden_fla | ||
| 59 | if (afdh.getNeedAppearances()) { | 59 | if (afdh.getNeedAppearances()) { |
| 60 | qpdf.getRoot() | 60 | qpdf.getRoot() |
| 61 | .getKey("/AcroForm") | 61 | .getKey("/AcroForm") |
| 62 | - .warnIfPossible( | 62 | + .warn( |
| 63 | "document does not have updated appearance streams, so form fields " | 63 | "document does not have updated appearance streams, so form fields " |
| 64 | "will not be flattened"); | 64 | "will not be flattened"); |
| 65 | } | 65 | } |
libqpdf/QPDFPageObjectHelper.cc
| @@ -12,6 +12,8 @@ | @@ -12,6 +12,8 @@ | ||
| 12 | #include <qpdf/QUtil.hh> | 12 | #include <qpdf/QUtil.hh> |
| 13 | #include <qpdf/ResourceFinder.hh> | 13 | #include <qpdf/ResourceFinder.hh> |
| 14 | 14 | ||
| 15 | +using namespace std::literals; | ||
| 16 | + | ||
| 15 | namespace | 17 | namespace |
| 16 | { | 18 | { |
| 17 | class ContentProvider: public QPDFObjectHandle::StreamDataProvider | 19 | class ContentProvider: public QPDFObjectHandle::StreamDataProvider |
| @@ -118,7 +120,7 @@ InlineImageTracker::convertIIDict(QPDFObjectHandle odict) | @@ -118,7 +120,7 @@ InlineImageTracker::convertIIDict(QPDFObjectHandle odict) | ||
| 118 | QTC::TC("qpdf", "QPDFPageObjectHelper colorspace lookup"); | 120 | QTC::TC("qpdf", "QPDFPageObjectHelper colorspace lookup"); |
| 119 | value = colorspace.getKey(name); | 121 | value = colorspace.getKey(name); |
| 120 | } else { | 122 | } else { |
| 121 | - resources.warnIfPossible("unable to resolve colorspace " + name); | 123 | + resources.warn("unable to resolve colorspace " + name); |
| 122 | } | 124 | } |
| 123 | name.clear(); | 125 | name.clear(); |
| 124 | } | 126 | } |
| @@ -414,8 +416,8 @@ QPDFPageObjectHelper::externalizeInlineImages(size_t min_size, bool shallow) | @@ -414,8 +416,8 @@ QPDFPageObjectHelper::externalizeInlineImages(size_t min_size, bool shallow) | ||
| 414 | filterContents(&iit, &b); | 416 | filterContents(&iit, &b); |
| 415 | filtered = true; | 417 | filtered = true; |
| 416 | } catch (std::exception& e) { | 418 | } catch (std::exception& e) { |
| 417 | - oh().warnIfPossible( | ||
| 418 | - std::string("Unable to filter content stream: ") + e.what() + | 419 | + warn( |
| 420 | + "Unable to filter content stream: "s + e.what() + | ||
| 419 | "; not attempting to externalize inline images from this stream"); | 421 | "; not attempting to externalize inline images from this stream"); |
| 420 | } | 422 | } |
| 421 | if (filtered && iit.any_images) { | 423 | if (filtered && iit.any_images) { |
| @@ -555,15 +557,15 @@ QPDFPageObjectHelper::removeUnreferencedResourcesHelper( | @@ -555,15 +557,15 @@ QPDFPageObjectHelper::removeUnreferencedResourcesHelper( | ||
| 555 | ph.parseContents(&rf); | 557 | ph.parseContents(&rf); |
| 556 | size_t after_nw = (q ? q->numWarnings() : 0); | 558 | size_t after_nw = (q ? q->numWarnings() : 0); |
| 557 | if (after_nw > before_nw) { | 559 | if (after_nw > before_nw) { |
| 558 | - ph.oh().warnIfPossible( | 560 | + ph.warn( |
| 559 | "Bad token found while scanning content stream; " | 561 | "Bad token found while scanning content stream; " |
| 560 | "not attempting to remove unreferenced objects from this object"); | 562 | "not attempting to remove unreferenced objects from this object"); |
| 561 | return false; | 563 | return false; |
| 562 | } | 564 | } |
| 563 | } catch (std::exception& e) { | 565 | } catch (std::exception& e) { |
| 564 | QTC::TC("qpdf", "QPDFPageObjectHelper bad token finding names"); | 566 | QTC::TC("qpdf", "QPDFPageObjectHelper bad token finding names"); |
| 565 | - ph.oh().warnIfPossible( | ||
| 566 | - std::string("Unable to parse content stream: ") + e.what() + | 567 | + ph.warn( |
| 568 | + "Unable to parse content stream: "s + e.what() + | ||
| 567 | "; not attempting to remove unreferenced objects from this object"); | 569 | "; not attempting to remove unreferenced objects from this object"); |
| 568 | return false; | 570 | return false; |
| 569 | } | 571 | } |
| @@ -719,8 +721,7 @@ QPDFPageObjectHelper::getFormXObjectForPage(bool handle_transformations) | @@ -719,8 +721,7 @@ QPDFPageObjectHelper::getFormXObjectForPage(bool handle_transformations) | ||
| 719 | newdict.replaceKey("/Group", getAttribute("/Group", false).shallowCopy()); | 721 | newdict.replaceKey("/Group", getAttribute("/Group", false).shallowCopy()); |
| 720 | QPDFObjectHandle bbox = getTrimBox(false).shallowCopy(); | 722 | QPDFObjectHandle bbox = getTrimBox(false).shallowCopy(); |
| 721 | if (!bbox.isRectangle()) { | 723 | if (!bbox.isRectangle()) { |
| 722 | - oh().warnIfPossible( | ||
| 723 | - "bounding box is invalid; form XObject created from page will not work"); | 724 | + warn("bounding box is invalid; form XObject created from page will not work"); |
| 724 | } | 725 | } |
| 725 | newdict.replaceKey("/BBox", bbox); | 726 | newdict.replaceKey("/BBox", bbox); |
| 726 | auto provider = | 727 | auto provider = |
libqpdf/QPDFWriter.cc
| @@ -1396,8 +1396,8 @@ QPDFWriter::willFilterStream( | @@ -1396,8 +1396,8 @@ QPDFWriter::willFilterStream( | ||
| 1396 | } | 1396 | } |
| 1397 | } catch (std::runtime_error& e) { | 1397 | } catch (std::runtime_error& e) { |
| 1398 | if (filter && first_attempt) { | 1398 | if (filter && first_attempt) { |
| 1399 | - stream.warnIfPossible("error while getting stream data: "s + e.what()); | ||
| 1400 | - stream.warnIfPossible("qpdf will attempt to write the damaged stream unchanged"); | 1399 | + stream.warn("error while getting stream data: "s + e.what()); |
| 1400 | + stream.warn("qpdf will attempt to write the damaged stream unchanged"); | ||
| 1401 | filter = false; | 1401 | filter = false; |
| 1402 | stream.setFilterOnWrite(false); | 1402 | stream.setFilterOnWrite(false); |
| 1403 | continue; | 1403 | continue; |
| @@ -1742,7 +1742,7 @@ QPDFWriter::writeObjectStream(QPDFObjectHandle object) | @@ -1742,7 +1742,7 @@ QPDFWriter::writeObjectStream(QPDFObjectHandle object) | ||
| 1742 | if (obj_to_write.isStream()) { | 1742 | if (obj_to_write.isStream()) { |
| 1743 | // This condition occurred in a fuzz input. Ideally we should block it at parse | 1743 | // This condition occurred in a fuzz input. Ideally we should block it at parse |
| 1744 | // time, but it's not clear to me how to construct a case for this. | 1744 | // time, but it's not clear to me how to construct a case for this. |
| 1745 | - obj_to_write.warnIfPossible("stream found inside object stream; treating as null"); | 1745 | + obj_to_write.warn("stream found inside object stream; treating as null"); |
| 1746 | obj_to_write = QPDFObjectHandle::newNull(); | 1746 | obj_to_write = QPDFObjectHandle::newNull(); |
| 1747 | } | 1747 | } |
| 1748 | writeObject(obj_to_write, count); | 1748 | writeObject(obj_to_write, count); |
libqpdf/QPDF_pages.cc
| @@ -57,7 +57,7 @@ QPDF::getAllPages() | @@ -57,7 +57,7 @@ QPDF::getAllPages() | ||
| 57 | // Files have been found in the wild where /Pages in the catalog points to the first | 57 | // Files have been found in the wild where /Pages in the catalog points to the first |
| 58 | // page. Try to work around this and similar cases with this heuristic. | 58 | // page. Try to work around this and similar cases with this heuristic. |
| 59 | if (!warned) { | 59 | if (!warned) { |
| 60 | - root.warnIfPossible( | 60 | + root.warn( |
| 61 | "document page tree root (root -> /Pages) doesn't point" | 61 | "document page tree root (root -> /Pages) doesn't point" |
| 62 | " to the root of the page tree; attempting to correct"); | 62 | " to the root of the page tree; attempting to correct"); |
| 63 | warned = true; | 63 | warned = true; |
| @@ -109,7 +109,7 @@ QPDF::getAllPagesInternal( | @@ -109,7 +109,7 @@ QPDF::getAllPagesInternal( | ||
| 109 | // During fuzzing files were encountered where the root object appeared in the pages tree. | 109 | // During fuzzing files were encountered where the root object appeared in the pages tree. |
| 110 | // Unconditionally setting the /Type to /Pages could cause problems, but trying to | 110 | // Unconditionally setting the /Type to /Pages could cause problems, but trying to |
| 111 | // accommodate the possibility may be excessive. | 111 | // accommodate the possibility may be excessive. |
| 112 | - cur_node.warnIfPossible("/Type key should be /Pages but is not; overriding"); | 112 | + cur_node.warn("/Type key should be /Pages but is not; overriding"); |
| 113 | cur_node.replaceKey("/Type", "/Pages"_qpdf); | 113 | cur_node.replaceKey("/Type", "/Pages"_qpdf); |
| 114 | } | 114 | } |
| 115 | if (!media_box) { | 115 | if (!media_box) { |
| @@ -134,13 +134,13 @@ QPDF::getAllPagesInternal( | @@ -134,13 +134,13 @@ QPDF::getAllPagesInternal( | ||
| 134 | int errors = 0; | 134 | int errors = 0; |
| 135 | 135 | ||
| 136 | if (!kid.isDictionary()) { | 136 | if (!kid.isDictionary()) { |
| 137 | - kid.warnIfPossible("Pages tree includes non-dictionary object; ignoring"); | 137 | + kid.warn("Pages tree includes non-dictionary object; ignoring"); |
| 138 | m->invalid_page_found = true; | 138 | m->invalid_page_found = true; |
| 139 | continue; | 139 | continue; |
| 140 | } | 140 | } |
| 141 | if (!kid.isIndirect()) { | 141 | if (!kid.isIndirect()) { |
| 142 | QTC::TC("qpdf", "QPDF handle direct page object"); | 142 | QTC::TC("qpdf", "QPDF handle direct page object"); |
| 143 | - cur_node.warnIfPossible( | 143 | + cur_node.warn( |
| 144 | "kid " + std::to_string(i) + " (from 0) is direct; converting to indirect"); | 144 | "kid " + std::to_string(i) + " (from 0) is direct; converting to indirect"); |
| 145 | kid = makeIndirectObject(kid); | 145 | kid = makeIndirectObject(kid); |
| 146 | ++errors; | 146 | ++errors; |
| @@ -150,7 +150,7 @@ QPDF::getAllPagesInternal( | @@ -150,7 +150,7 @@ QPDF::getAllPagesInternal( | ||
| 150 | } else { | 150 | } else { |
| 151 | if (!media_box && !kid.getKey("/MediaBox").isRectangle()) { | 151 | if (!media_box && !kid.getKey("/MediaBox").isRectangle()) { |
| 152 | QTC::TC("qpdf", "QPDF missing mediabox"); | 152 | QTC::TC("qpdf", "QPDF missing mediabox"); |
| 153 | - kid.warnIfPossible( | 153 | + kid.warn( |
| 154 | "kid " + std::to_string(i) + | 154 | "kid " + std::to_string(i) + |
| 155 | " (from 0) MediaBox is undefined; setting to letter / ANSI A"); | 155 | " (from 0) MediaBox is undefined; setting to letter / ANSI A"); |
| 156 | kid.replaceKey( | 156 | kid.replaceKey( |
| @@ -167,7 +167,7 @@ QPDF::getAllPagesInternal( | @@ -167,7 +167,7 @@ QPDF::getAllPagesInternal( | ||
| 167 | // QPDFPageObjectHelper. | 167 | // QPDFPageObjectHelper. |
| 168 | QTC::TC("qpdf", "QPDF resolve duplicated page object"); | 168 | QTC::TC("qpdf", "QPDF resolve duplicated page object"); |
| 169 | if (!m->reconstructed_xref) { | 169 | if (!m->reconstructed_xref) { |
| 170 | - cur_node.warnIfPossible( | 170 | + cur_node.warn( |
| 171 | "kid " + std::to_string(i) + | 171 | "kid " + std::to_string(i) + |
| 172 | " (from 0) appears more than once in the pages tree;" | 172 | " (from 0) appears more than once in the pages tree;" |
| 173 | " creating a new page object as a copy"); | 173 | " creating a new page object as a copy"); |
| @@ -176,7 +176,7 @@ QPDF::getAllPagesInternal( | @@ -176,7 +176,7 @@ QPDF::getAllPagesInternal( | ||
| 176 | kid = makeIndirectObject(QPDFObjectHandle(kid).shallowCopy()); | 176 | kid = makeIndirectObject(QPDFObjectHandle(kid).shallowCopy()); |
| 177 | seen.add(kid); | 177 | seen.add(kid); |
| 178 | } else { | 178 | } else { |
| 179 | - cur_node.warnIfPossible( | 179 | + cur_node.warn( |
| 180 | "kid " + std::to_string(i) + | 180 | "kid " + std::to_string(i) + |
| 181 | " (from 0) appears more than once in the pages tree; ignoring duplicate"); | 181 | " (from 0) appears more than once in the pages tree; ignoring duplicate"); |
| 182 | m->invalid_page_found = true; | 182 | m->invalid_page_found = true; |
| @@ -189,12 +189,12 @@ QPDF::getAllPagesInternal( | @@ -189,12 +189,12 @@ QPDF::getAllPagesInternal( | ||
| 189 | } | 189 | } |
| 190 | } | 190 | } |
| 191 | if (!kid.isDictionaryOfType("/Page")) { | 191 | if (!kid.isDictionaryOfType("/Page")) { |
| 192 | - kid.warnIfPossible("/Type key should be /Page but is not; overriding"); | 192 | + kid.warn("/Type key should be /Page but is not; overriding"); |
| 193 | kid.replaceKey("/Type", "/Page"_qpdf); | 193 | kid.replaceKey("/Type", "/Page"_qpdf); |
| 194 | ++errors; | 194 | ++errors; |
| 195 | } | 195 | } |
| 196 | if (m->reconstructed_xref && errors > 2) { | 196 | if (m->reconstructed_xref && errors > 2) { |
| 197 | - cur_node.warnIfPossible( | 197 | + cur_node.warn( |
| 198 | "kid " + std::to_string(i) + " (from 0) has too many errors; ignoring page"); | 198 | "kid " + std::to_string(i) + " (from 0) has too many errors; ignoring page"); |
| 199 | m->invalid_page_found = true; | 199 | m->invalid_page_found = true; |
| 200 | kid = QPDFObjectHandle::newNull(); | 200 | kid = QPDFObjectHandle::newNull(); |
qpdf/qpdf.testcov
| @@ -424,11 +424,6 @@ QPDFPageObjectHelper keep inline image 0 | @@ -424,11 +424,6 @@ QPDFPageObjectHelper keep inline image 0 | ||
| 424 | QPDFJob image optimize colorspace 0 | 424 | QPDFJob image optimize colorspace 0 |
| 425 | QPDFJob image optimize bits per component 0 | 425 | QPDFJob image optimize bits per component 0 |
| 426 | QPDFWriter remove empty DecodeParms 0 | 426 | QPDFWriter remove empty DecodeParms 0 |
| 427 | -QPDFObjectHandle uint returning 0 0 | ||
| 428 | -QPDFObjectHandle int returning INT_MIN 0 | ||
| 429 | -QPDFObjectHandle int returning INT_MAX 0 | ||
| 430 | -QPDFObjectHandle uint returning UINT_MAX 0 | ||
| 431 | -QPDFObjectHandle uint uint returning 0 0 | ||
| 432 | QPDF xref skipped space 0 | 427 | QPDF xref skipped space 0 |
| 433 | QPDF eof skipping spaces before xref 1 | 428 | QPDF eof skipping spaces before xref 1 |
| 434 | QPDF_encryption user matches owner V < 5 0 | 429 | QPDF_encryption user matches owner V < 5 0 |
| @@ -592,7 +587,7 @@ QPDFAcroFormDocumentHelper replaced DA token 0 | @@ -592,7 +587,7 @@ QPDFAcroFormDocumentHelper replaced DA token 0 | ||
| 592 | QPDFAcroFormDocumentHelper ap conflict 0 | 587 | QPDFAcroFormDocumentHelper ap conflict 0 |
| 593 | QPDFAcroFormDocumentHelper ap rename 0 | 588 | QPDFAcroFormDocumentHelper ap rename 0 |
| 594 | QPDFAcroFormDocumentHelper /DA parse error 0 | 589 | QPDFAcroFormDocumentHelper /DA parse error 0 |
| 595 | -QPDFAcroFormDocumentHelper AP parse error 0 | 590 | +QPDFAcroFormDocumentHelper AP parse error 1 |
| 596 | QPDFJob copy fields not this file 0 | 591 | QPDFJob copy fields not this file 0 |
| 597 | QPDFJob copy fields non-first from orig 0 | 592 | QPDFJob copy fields non-first from orig 0 |
| 598 | QPDF resolve duplicated page in insert 0 | 593 | QPDF resolve duplicated page in insert 0 |