Commit 04f45cf652f2ee30a677933817aef8971a1f533d

Authored by Jay Berkenbilt
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.
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&amp; 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&amp; any_errors, bool&amp; 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 &quot;\n&quot;;
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 &quot;\n&quot;;
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 &quot;\n&quot;;
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&amp; pdf, Options&amp; o, int&amp; 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&amp; pdf, Options&amp; 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
... ...