Commit 04f45cf652f2ee30a677933817aef8971a1f533d
1 parent
0b45dfd3
Treat all linearization errors as warnings
This also reverts the addition of a new checkLinearization that distinguishes errors from warnings. There's no practical distinction between what was considered an error and what was considered a warning.
Showing
6 changed files
with
56 additions
and
68 deletions
include/qpdf/QPDF.hh
| ... | ... | @@ -477,15 +477,13 @@ class QPDF |
| 477 | 477 | QPDF_DLL |
| 478 | 478 | bool isLinearized(); |
| 479 | 479 | |
| 480 | - // Performs various sanity checks on a linearized file. Return | |
| 481 | - // true if no errors or warnings. Otherwise, return false and | |
| 480 | + // Performs various sanity checks on a linearized file. Return | |
| 481 | + // true if no errors or warnings. Otherwise, return false and | |
| 482 | 482 | // output errors and warnings to std::cout or the output stream |
| 483 | - // specified in a call to setOutputStreams. | |
| 483 | + // specified in a call to setOutputStreams. It is recommended for | |
| 484 | + // linearization errors to be treated as warnings. | |
| 484 | 485 | QPDF_DLL |
| 485 | 486 | bool checkLinearization(); |
| 486 | - // Separately indicate whether there were errors or warnings. | |
| 487 | - QPDF_DLL | |
| 488 | - void checkLinearization(bool& errors, bool& warnings); | |
| 489 | 487 | |
| 490 | 488 | // Calls checkLinearization() and, if possible, prints normalized |
| 491 | 489 | // contents of some of the hints tables to std::cout or the output |
| ... | ... | @@ -1229,7 +1227,7 @@ class QPDF |
| 1229 | 1227 | // methods to support linearization checking -- implemented in |
| 1230 | 1228 | // QPDF_linearization.cc |
| 1231 | 1229 | void readLinearizationData(); |
| 1232 | - void checkLinearizationInternal(bool& errors, bool& warnings); | |
| 1230 | + bool checkLinearizationInternal(); | |
| 1233 | 1231 | void dumpLinearizationDataInternal(); |
| 1234 | 1232 | QPDFObjectHandle readHintStream( |
| 1235 | 1233 | Pipeline&, qpdf_offset_t offset, size_t length); | ... | ... |
libqpdf/QPDF_linearization.cc
| ... | ... | @@ -65,25 +65,17 @@ load_vector_vector(BitStream& bit_stream, |
| 65 | 65 | bool |
| 66 | 66 | QPDF::checkLinearization() |
| 67 | 67 | { |
| 68 | - bool errors = false; | |
| 69 | - bool warnings = false; | |
| 70 | - checkLinearization(errors, warnings); | |
| 71 | - return (! (errors || warnings)); | |
| 72 | -} | |
| 73 | - | |
| 74 | -void | |
| 75 | -QPDF::checkLinearization(bool& errors, bool& warnings) | |
| 76 | -{ | |
| 68 | + bool result = false; | |
| 77 | 69 | try |
| 78 | 70 | { |
| 79 | 71 | readLinearizationData(); |
| 80 | - checkLinearizationInternal(errors, warnings); | |
| 72 | + result = checkLinearizationInternal(); | |
| 81 | 73 | } |
| 82 | 74 | catch (QPDFExc& e) |
| 83 | 75 | { |
| 84 | 76 | *this->m->out_stream << e.what() << std::endl; |
| 85 | - errors = true; | |
| 86 | 77 | } |
| 78 | + return result; | |
| 87 | 79 | } |
| 88 | 80 | |
| 89 | 81 | bool |
| ... | ... | @@ -507,8 +499,8 @@ QPDF::readHGeneric(BitStream h, HGeneric& t) |
| 507 | 499 | t.group_length = h.getBitsInt(32); // 4 |
| 508 | 500 | } |
| 509 | 501 | |
| 510 | -void | |
| 511 | -QPDF::checkLinearizationInternal(bool& any_errors, bool& any_warnings) | |
| 502 | +bool | |
| 503 | +QPDF::checkLinearizationInternal() | |
| 512 | 504 | { |
| 513 | 505 | // All comments referring to the PDF spec refer to the spec for |
| 514 | 506 | // version 1.4. |
| ... | ... | @@ -656,26 +648,34 @@ QPDF::checkLinearizationInternal(bool& any_errors, bool& any_warnings) |
| 656 | 648 | |
| 657 | 649 | // Report errors |
| 658 | 650 | |
| 659 | - any_errors = (! errors.empty()); | |
| 660 | - any_warnings = (! warnings.empty()); | |
| 651 | + bool result = true; | |
| 661 | 652 | |
| 662 | - if (any_errors) | |
| 653 | + // Treat all linearization errors as warnings. Many of them occur | |
| 654 | + // in otherwise working files, so it's really misleading to treat | |
| 655 | + // them as errors. We'll hang onto the distinction in the code for | |
| 656 | + // now in case we ever have a chance to clean up the linearization | |
| 657 | + // code. | |
| 658 | + if (! errors.empty()) | |
| 663 | 659 | { |
| 660 | + result = false; | |
| 664 | 661 | for (std::list<std::string>::iterator iter = errors.begin(); |
| 665 | 662 | iter != errors.end(); ++iter) |
| 666 | 663 | { |
| 667 | - *this->m->out_stream << "ERROR: " << (*iter) << std::endl; | |
| 664 | + *this->m->out_stream << "WARNING: " << (*iter) << std::endl; | |
| 668 | 665 | } |
| 669 | 666 | } |
| 670 | 667 | |
| 671 | - if (any_warnings) | |
| 668 | + if (! warnings.empty()) | |
| 672 | 669 | { |
| 670 | + result = false; | |
| 673 | 671 | for (std::list<std::string>::iterator iter = warnings.begin(); |
| 674 | 672 | iter != warnings.end(); ++iter) |
| 675 | 673 | { |
| 676 | 674 | *this->m->out_stream << "WARNING: " << (*iter) << std::endl; |
| 677 | 675 | } |
| 678 | 676 | } |
| 677 | + | |
| 678 | + return result; | |
| 679 | 679 | } |
| 680 | 680 | |
| 681 | 681 | qpdf_offset_t |
| ... | ... | @@ -1089,9 +1089,7 @@ QPDF::showLinearizationData() |
| 1089 | 1089 | try |
| 1090 | 1090 | { |
| 1091 | 1091 | readLinearizationData(); |
| 1092 | - bool errors = false; | |
| 1093 | - bool warnings = false; | |
| 1094 | - checkLinearizationInternal(errors, warnings); | |
| 1092 | + checkLinearizationInternal(); | |
| 1095 | 1093 | dumpLinearizationDataInternal(); |
| 1096 | 1094 | } |
| 1097 | 1095 | catch (QPDFExc& e) | ... | ... |
manual/qpdf-manual.xml
| ... | ... | @@ -4314,6 +4314,14 @@ print "\n"; |
| 4314 | 4314 | higher level methods for tokenizing content streams. |
| 4315 | 4315 | </para> |
| 4316 | 4316 | </listitem> |
| 4317 | + <listitem> | |
| 4318 | + <para> | |
| 4319 | + When <command>qpdf --check</command> or <command>qpdf | |
| 4320 | + --check-linearization</command> encounters a file with | |
| 4321 | + linearization warnings but not errors, it now properly exits | |
| 4322 | + with exit code 3 instead of 2. | |
| 4323 | + </para> | |
| 4324 | + </listitem> | |
| 4317 | 4325 | </itemizedlist> |
| 4318 | 4326 | </listitem> |
| 4319 | 4327 | <listitem> |
| ... | ... | @@ -4361,6 +4369,14 @@ print "\n"; |
| 4361 | 4369 | missing /Length keys in the encryption dictionary. |
| 4362 | 4370 | </para> |
| 4363 | 4371 | </listitem> |
| 4372 | + <listitem> | |
| 4373 | + <para> | |
| 4374 | + When <command>qpdf --check</command> or <command>qpdf | |
| 4375 | + --check-linearization</command> encounters a file with | |
| 4376 | + linearization warnings but not errors, it now properly exits | |
| 4377 | + with exit code 3 instead of 2. | |
| 4378 | + </para> | |
| 4379 | + </listitem> | |
| 4364 | 4380 | </itemizedlist> |
| 4365 | 4381 | </listitem> |
| 4366 | 4382 | <listitem> |
| ... | ... | @@ -4462,10 +4478,9 @@ print "\n"; |
| 4462 | 4478 | </listitem> |
| 4463 | 4479 | <listitem> |
| 4464 | 4480 | <para> |
| 4465 | - A new version of | |
| 4466 | - <function>QPDF::checkLinearization()</function> has been | |
| 4467 | - added that indicates separately whether there were errors or | |
| 4468 | - warnings. | |
| 4481 | + All conditions previously reported by | |
| 4482 | + <function>QPDF::checkLinearization()</function> as errors | |
| 4483 | + are now presented as warnings. | |
| 4469 | 4484 | </para> |
| 4470 | 4485 | </listitem> |
| 4471 | 4486 | </itemizedlist> | ... | ... |
qpdf/qpdf.cc
| ... | ... | @@ -3210,15 +3210,10 @@ static void do_check(QPDF& pdf, Options& o, int& exit_code) |
| 3210 | 3210 | if (pdf.isLinearized()) |
| 3211 | 3211 | { |
| 3212 | 3212 | std::cout << "File is linearized\n"; |
| 3213 | - bool lin_errors = false; | |
| 3214 | - bool lin_warnings = false; | |
| 3215 | - // any errors or warnings are reported by checkLinearization() | |
| 3216 | - pdf.checkLinearization(lin_errors, lin_warnings); | |
| 3217 | - if (lin_errors) | |
| 3218 | - { | |
| 3219 | - okay = false; | |
| 3220 | - } | |
| 3221 | - else if (lin_warnings) | |
| 3213 | + // any errors or warnings are reported by | |
| 3214 | + // checkLinearization(). We treat all issues reported here | |
| 3215 | + // as warnings. | |
| 3216 | + if (! pdf.checkLinearization()) | |
| 3222 | 3217 | { |
| 3223 | 3218 | warnings = true; |
| 3224 | 3219 | } |
| ... | ... | @@ -3796,22 +3791,15 @@ static void do_inspection(QPDF& pdf, Options& o) |
| 3796 | 3791 | } |
| 3797 | 3792 | if (o.check_linearization) |
| 3798 | 3793 | { |
| 3799 | - bool lin_errors = false; | |
| 3800 | - bool lin_warnings = false; | |
| 3801 | - pdf.checkLinearization(lin_errors, lin_warnings); | |
| 3802 | - if (lin_errors) | |
| 3794 | + if (pdf.checkLinearization()) | |
| 3803 | 3795 | { |
| 3804 | - exit_code = EXIT_ERROR; | |
| 3796 | + std::cout << o.infilename << ": no linearization errors" | |
| 3797 | + << std::endl; | |
| 3805 | 3798 | } |
| 3806 | - else if (lin_warnings && (exit_code != EXIT_ERROR)) | |
| 3799 | + else if (exit_code != EXIT_ERROR) | |
| 3807 | 3800 | { |
| 3808 | 3801 | exit_code = EXIT_WARNING; |
| 3809 | 3802 | } |
| 3810 | - else | |
| 3811 | - { | |
| 3812 | - std::cout << o.infilename << ": no linearization errors" | |
| 3813 | - << std::endl; | |
| 3814 | - } | |
| 3815 | 3803 | } |
| 3816 | 3804 | if (o.show_linearization) |
| 3817 | 3805 | { | ... | ... |
qpdf/qtest/qpdf.test
| ... | ... | @@ -1321,12 +1321,12 @@ $n_tests += 3; |
| 1321 | 1321 | $td->runtest("bounds check linearization data 1", |
| 1322 | 1322 | {$td->COMMAND => "qpdf --check linearization-bounds-1.pdf"}, |
| 1323 | 1323 | {$td->FILE => "linearization-bounds-1.out", |
| 1324 | - $td->EXIT_STATUS => 2}, | |
| 1324 | + $td->EXIT_STATUS => 3}, | |
| 1325 | 1325 | $td->NORMALIZE_NEWLINES); |
| 1326 | 1326 | $td->runtest("bounds check linearization data 2", |
| 1327 | 1327 | {$td->COMMAND => "qpdf --check linearization-bounds-2.pdf"}, |
| 1328 | 1328 | {$td->FILE => "linearization-bounds-2.out", |
| 1329 | - $td->EXIT_STATUS => 2}, | |
| 1329 | + $td->EXIT_STATUS => 3}, | |
| 1330 | 1330 | $td->NORMALIZE_NEWLINES); |
| 1331 | 1331 | # Throws logic error, not bad_alloc |
| 1332 | 1332 | $td->runtest("sanity check array size", |
| ... | ... | @@ -2855,7 +2855,7 @@ my @to_linearize = |
| 2855 | 2855 | ); |
| 2856 | 2856 | |
| 2857 | 2857 | $n_tests += @linearized_files + 6; |
| 2858 | -$n_tests += (3 * @to_linearize * 5) + 8; | |
| 2858 | +$n_tests += (3 * @to_linearize * 5) + 6; | |
| 2859 | 2859 | |
| 2860 | 2860 | foreach my $base (@linearized_files) |
| 2861 | 2861 | { |
| ... | ... | @@ -2939,17 +2939,6 @@ foreach my $base (@to_linearize) |
| 2939 | 2939 | } |
| 2940 | 2940 | } |
| 2941 | 2941 | |
| 2942 | -# Verify that we get proper exit codes for files with only warnings | |
| 2943 | -$td->runtest("linearization warnings check", | |
| 2944 | - {$td->COMMAND => "qpdf --check lin3.pdf"}, | |
| 2945 | - {$td->FILE => "lin3-check.out", $td->EXIT_STATUS => 3}, | |
| 2946 | - $td->NORMALIZE_NEWLINES); | |
| 2947 | -$td->runtest("linearization warnings check-linearization", | |
| 2948 | - {$td->COMMAND => "qpdf --check-linearization lin3.pdf"}, | |
| 2949 | - {$td->FILE => "lin3-check-linearization.out", | |
| 2950 | - $td->EXIT_STATUS => 3}, | |
| 2951 | - $td->NORMALIZE_NEWLINES); | |
| 2952 | - | |
| 2953 | 2942 | show_ntests(); |
| 2954 | 2943 | # ---------- |
| 2955 | 2944 | $td->notify("--- Encryption Tests ---"); | ... | ... |
qpdf/qtest/qpdf/badlin1.out
| 1 | -ERROR: first page object (/O) mismatch | |
| 2 | -ERROR: space before first xref item (/T) mismatch (computed = 11777; file = 11771 | |
| 1 | +WARNING: first page object (/O) mismatch | |
| 2 | +WARNING: space before first xref item (/T) mismatch (computed = 11777; file = 11771 | |
| 3 | 3 | WARNING: end of first page section (/E) mismatch: /E = 1827; computed = 3889..3891 |
| 4 | 4 | WARNING: page 0 has shared identifier entries |
| 5 | 5 | WARNING: page 0: shared object 62: in hint table but not computed list | ... | ... |