Commit 06db6493a1776bfda78314697f2f2e4393d9dea4

Authored by m-holger
1 parent decc7d3c

Refactor `QPDFObjectHandle` warnings: replace `warnIfPossible` with centralized …

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