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,15 +477,13 @@ class QPDF | ||
| 477 | QPDF_DLL | 477 | QPDF_DLL |
| 478 | bool isLinearized(); | 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 | // output errors and warnings to std::cout or the output stream | 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 | QPDF_DLL | 485 | QPDF_DLL |
| 485 | bool checkLinearization(); | 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 | // Calls checkLinearization() and, if possible, prints normalized | 488 | // Calls checkLinearization() and, if possible, prints normalized |
| 491 | // contents of some of the hints tables to std::cout or the output | 489 | // contents of some of the hints tables to std::cout or the output |
| @@ -1229,7 +1227,7 @@ class QPDF | @@ -1229,7 +1227,7 @@ class QPDF | ||
| 1229 | // methods to support linearization checking -- implemented in | 1227 | // methods to support linearization checking -- implemented in |
| 1230 | // QPDF_linearization.cc | 1228 | // QPDF_linearization.cc |
| 1231 | void readLinearizationData(); | 1229 | void readLinearizationData(); |
| 1232 | - void checkLinearizationInternal(bool& errors, bool& warnings); | 1230 | + bool checkLinearizationInternal(); |
| 1233 | void dumpLinearizationDataInternal(); | 1231 | void dumpLinearizationDataInternal(); |
| 1234 | QPDFObjectHandle readHintStream( | 1232 | QPDFObjectHandle readHintStream( |
| 1235 | Pipeline&, qpdf_offset_t offset, size_t length); | 1233 | Pipeline&, qpdf_offset_t offset, size_t length); |
libqpdf/QPDF_linearization.cc
| @@ -65,25 +65,17 @@ load_vector_vector(BitStream& bit_stream, | @@ -65,25 +65,17 @@ load_vector_vector(BitStream& bit_stream, | ||
| 65 | bool | 65 | bool |
| 66 | QPDF::checkLinearization() | 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 | try | 69 | try |
| 78 | { | 70 | { |
| 79 | readLinearizationData(); | 71 | readLinearizationData(); |
| 80 | - checkLinearizationInternal(errors, warnings); | 72 | + result = checkLinearizationInternal(); |
| 81 | } | 73 | } |
| 82 | catch (QPDFExc& e) | 74 | catch (QPDFExc& e) |
| 83 | { | 75 | { |
| 84 | *this->m->out_stream << e.what() << std::endl; | 76 | *this->m->out_stream << e.what() << std::endl; |
| 85 | - errors = true; | ||
| 86 | } | 77 | } |
| 78 | + return result; | ||
| 87 | } | 79 | } |
| 88 | 80 | ||
| 89 | bool | 81 | bool |
| @@ -507,8 +499,8 @@ QPDF::readHGeneric(BitStream h, HGeneric& t) | @@ -507,8 +499,8 @@ QPDF::readHGeneric(BitStream h, HGeneric& t) | ||
| 507 | t.group_length = h.getBitsInt(32); // 4 | 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 | // All comments referring to the PDF spec refer to the spec for | 505 | // All comments referring to the PDF spec refer to the spec for |
| 514 | // version 1.4. | 506 | // version 1.4. |
| @@ -656,26 +648,34 @@ QPDF::checkLinearizationInternal(bool& any_errors, bool& any_warnings) | @@ -656,26 +648,34 @@ QPDF::checkLinearizationInternal(bool& any_errors, bool& any_warnings) | ||
| 656 | 648 | ||
| 657 | // Report errors | 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 | for (std::list<std::string>::iterator iter = errors.begin(); | 661 | for (std::list<std::string>::iterator iter = errors.begin(); |
| 665 | iter != errors.end(); ++iter) | 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 | for (std::list<std::string>::iterator iter = warnings.begin(); | 671 | for (std::list<std::string>::iterator iter = warnings.begin(); |
| 674 | iter != warnings.end(); ++iter) | 672 | iter != warnings.end(); ++iter) |
| 675 | { | 673 | { |
| 676 | *this->m->out_stream << "WARNING: " << (*iter) << std::endl; | 674 | *this->m->out_stream << "WARNING: " << (*iter) << std::endl; |
| 677 | } | 675 | } |
| 678 | } | 676 | } |
| 677 | + | ||
| 678 | + return result; | ||
| 679 | } | 679 | } |
| 680 | 680 | ||
| 681 | qpdf_offset_t | 681 | qpdf_offset_t |
| @@ -1089,9 +1089,7 @@ QPDF::showLinearizationData() | @@ -1089,9 +1089,7 @@ QPDF::showLinearizationData() | ||
| 1089 | try | 1089 | try |
| 1090 | { | 1090 | { |
| 1091 | readLinearizationData(); | 1091 | readLinearizationData(); |
| 1092 | - bool errors = false; | ||
| 1093 | - bool warnings = false; | ||
| 1094 | - checkLinearizationInternal(errors, warnings); | 1092 | + checkLinearizationInternal(); |
| 1095 | dumpLinearizationDataInternal(); | 1093 | dumpLinearizationDataInternal(); |
| 1096 | } | 1094 | } |
| 1097 | catch (QPDFExc& e) | 1095 | catch (QPDFExc& e) |
manual/qpdf-manual.xml
| @@ -4314,6 +4314,14 @@ print "\n"; | @@ -4314,6 +4314,14 @@ print "\n"; | ||
| 4314 | higher level methods for tokenizing content streams. | 4314 | higher level methods for tokenizing content streams. |
| 4315 | </para> | 4315 | </para> |
| 4316 | </listitem> | 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 | </itemizedlist> | 4325 | </itemizedlist> |
| 4318 | </listitem> | 4326 | </listitem> |
| 4319 | <listitem> | 4327 | <listitem> |
| @@ -4361,6 +4369,14 @@ print "\n"; | @@ -4361,6 +4369,14 @@ print "\n"; | ||
| 4361 | missing /Length keys in the encryption dictionary. | 4369 | missing /Length keys in the encryption dictionary. |
| 4362 | </para> | 4370 | </para> |
| 4363 | </listitem> | 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 | </itemizedlist> | 4380 | </itemizedlist> |
| 4365 | </listitem> | 4381 | </listitem> |
| 4366 | <listitem> | 4382 | <listitem> |
| @@ -4462,10 +4478,9 @@ print "\n"; | @@ -4462,10 +4478,9 @@ print "\n"; | ||
| 4462 | </listitem> | 4478 | </listitem> |
| 4463 | <listitem> | 4479 | <listitem> |
| 4464 | <para> | 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 | </para> | 4484 | </para> |
| 4470 | </listitem> | 4485 | </listitem> |
| 4471 | </itemizedlist> | 4486 | </itemizedlist> |
qpdf/qpdf.cc
| @@ -3210,15 +3210,10 @@ static void do_check(QPDF& pdf, Options& o, int& exit_code) | @@ -3210,15 +3210,10 @@ static void do_check(QPDF& pdf, Options& o, int& exit_code) | ||
| 3210 | if (pdf.isLinearized()) | 3210 | if (pdf.isLinearized()) |
| 3211 | { | 3211 | { |
| 3212 | std::cout << "File is linearized\n"; | 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 | warnings = true; | 3218 | warnings = true; |
| 3224 | } | 3219 | } |
| @@ -3796,22 +3791,15 @@ static void do_inspection(QPDF& pdf, Options& o) | @@ -3796,22 +3791,15 @@ static void do_inspection(QPDF& pdf, Options& o) | ||
| 3796 | } | 3791 | } |
| 3797 | if (o.check_linearization) | 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 | exit_code = EXIT_WARNING; | 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 | if (o.show_linearization) | 3804 | if (o.show_linearization) |
| 3817 | { | 3805 | { |
qpdf/qtest/qpdf.test
| @@ -1321,12 +1321,12 @@ $n_tests += 3; | @@ -1321,12 +1321,12 @@ $n_tests += 3; | ||
| 1321 | $td->runtest("bounds check linearization data 1", | 1321 | $td->runtest("bounds check linearization data 1", |
| 1322 | {$td->COMMAND => "qpdf --check linearization-bounds-1.pdf"}, | 1322 | {$td->COMMAND => "qpdf --check linearization-bounds-1.pdf"}, |
| 1323 | {$td->FILE => "linearization-bounds-1.out", | 1323 | {$td->FILE => "linearization-bounds-1.out", |
| 1324 | - $td->EXIT_STATUS => 2}, | 1324 | + $td->EXIT_STATUS => 3}, |
| 1325 | $td->NORMALIZE_NEWLINES); | 1325 | $td->NORMALIZE_NEWLINES); |
| 1326 | $td->runtest("bounds check linearization data 2", | 1326 | $td->runtest("bounds check linearization data 2", |
| 1327 | {$td->COMMAND => "qpdf --check linearization-bounds-2.pdf"}, | 1327 | {$td->COMMAND => "qpdf --check linearization-bounds-2.pdf"}, |
| 1328 | {$td->FILE => "linearization-bounds-2.out", | 1328 | {$td->FILE => "linearization-bounds-2.out", |
| 1329 | - $td->EXIT_STATUS => 2}, | 1329 | + $td->EXIT_STATUS => 3}, |
| 1330 | $td->NORMALIZE_NEWLINES); | 1330 | $td->NORMALIZE_NEWLINES); |
| 1331 | # Throws logic error, not bad_alloc | 1331 | # Throws logic error, not bad_alloc |
| 1332 | $td->runtest("sanity check array size", | 1332 | $td->runtest("sanity check array size", |
| @@ -2855,7 +2855,7 @@ my @to_linearize = | @@ -2855,7 +2855,7 @@ my @to_linearize = | ||
| 2855 | ); | 2855 | ); |
| 2856 | 2856 | ||
| 2857 | $n_tests += @linearized_files + 6; | 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 | foreach my $base (@linearized_files) | 2860 | foreach my $base (@linearized_files) |
| 2861 | { | 2861 | { |
| @@ -2939,17 +2939,6 @@ foreach my $base (@to_linearize) | @@ -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 | show_ntests(); | 2942 | show_ntests(); |
| 2954 | # ---------- | 2943 | # ---------- |
| 2955 | $td->notify("--- Encryption Tests ---"); | 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 | WARNING: end of first page section (/E) mismatch: /E = 1827; computed = 3889..3891 | 3 | WARNING: end of first page section (/E) mismatch: /E = 1827; computed = 3889..3891 |
| 4 | WARNING: page 0 has shared identifier entries | 4 | WARNING: page 0 has shared identifier entries |
| 5 | WARNING: page 0: shared object 62: in hint table but not computed list | 5 | WARNING: page 0: shared object 62: in hint table but not computed list |