Commit 206c2fc1da0c9608bfec4e91e4b91410bba7f830

Authored by m-holger
1 parent 36e1c142

Add additional validation of document-level structures to `--check` option.

libqpdf/QPDFJob.cc
@@ -779,6 +779,14 @@ QPDFJob::doCheck(QPDF& pdf) @@ -779,6 +779,14 @@ QPDFJob::doCheck(QPDF& pdf)
779 cout << "File is not linearized\n"; 779 cout << "File is not linearized\n";
780 } 780 }
781 781
  782 + // Create all document helper to trigger any validations they carry out.
  783 + auto& pages = pdf.pages();
  784 + (void)pdf.acroform();
  785 + (void)pdf.embedded_files();
  786 + (void)pdf.page_labels();
  787 + (void)pdf.outlines().resolveNamedDest(QPDFObjectHandle::newString("dummy"));
  788 + (void)pdf.outlines().getOutlinesForPage(pages.getAllPages().at(0));
  789 +
782 // Write the file to nowhere, uncompressing streams. This causes full file traversal and 790 // Write the file to nowhere, uncompressing streams. This causes full file traversal and
783 // decoding of all streams we can decode. 791 // decoding of all streams we can decode.
784 QPDFWriter w(pdf); 792 QPDFWriter w(pdf);
@@ -789,7 +797,7 @@ QPDFJob::doCheck(QPDF&amp; pdf) @@ -789,7 +797,7 @@ QPDFJob::doCheck(QPDF&amp; pdf)
789 797
790 // Parse all content streams 798 // Parse all content streams
791 int pageno = 0; 799 int pageno = 0;
792 - for (auto& page: pdf.pages().getAllPages()) { 800 + for (auto& page: pages.getAllPages()) {
793 ++pageno; 801 ++pageno;
794 try { 802 try {
795 page.parseContents(nullptr); 803 page.parseContents(nullptr);
manual/release-notes.rst
@@ -47,6 +47,9 @@ more detail. @@ -47,6 +47,9 @@ more detail.
47 with the incompatible options :qpdf:ref:`--encrypt` or 47 with the incompatible options :qpdf:ref:`--encrypt` or
48 :qpdf:ref:`--copy-encryption`. 48 :qpdf:ref:`--copy-encryption`.
49 49
  50 + - Option :qpdf:ref:`--check` now includes additional basic checks of the
  51 + AcroForm, Dests, Outlines, and PageLabels structures.
  52 +
50 - Other enhancements 53 - Other enhancements
51 54
52 - ``QPDFWriter`` will no longer add filters when writing empty streams. 55 - ``QPDFWriter`` will no longer add filters when writing empty streams.
qpdf/qtest/outlines.test
@@ -21,7 +21,7 @@ my @outline_files = ( @@ -21,7 +21,7 @@ my @outline_files = (
21 'outlines-with-old-root-dests-dict', 21 'outlines-with-old-root-dests-dict',
22 'outlines-with-loop', 22 'outlines-with-loop',
23 ); 23 );
24 -my $n_tests = scalar(@outline_files); 24 +my $n_tests = scalar(@outline_files) + 1;
25 foreach my $f (@outline_files) 25 foreach my $f (@outline_files)
26 { 26 {
27 $td->runtest("outlines: $f", 27 $td->runtest("outlines: $f",
@@ -30,5 +30,10 @@ foreach my $f (@outline_files) @@ -30,5 +30,10 @@ foreach my $f (@outline_files)
30 $td->NORMALIZE_NEWLINES); 30 $td->NORMALIZE_NEWLINES);
31 } 31 }
32 32
  33 +$td->runtest("outlines: outlines-with-loop --check",
  34 + {$td->COMMAND => "qpdf --check outlines-with-loop.pdf"},
  35 + {$td->FILE => "outlines-with-loop-check.out", $td->EXIT_STATUS => 0},
  36 + $td->NORMALIZE_NEWLINES);
  37 +
33 cleanup(); 38 cleanup();
34 $td->report($n_tests); 39 $td->report($n_tests);
qpdf/qtest/page-labels.test
@@ -14,7 +14,7 @@ cleanup(); @@ -14,7 +14,7 @@ cleanup();
14 14
15 my $td = new TestDriver('page-labels'); 15 my $td = new TestDriver('page-labels');
16 16
17 -my $n_tests = 4; 17 +my $n_tests = 5;
18 18
19 $td->runtest("complex page labels", 19 $td->runtest("complex page labels",
20 {$td->COMMAND => "test_driver 47 page-labels-num-tree.pdf"}, 20 {$td->COMMAND => "test_driver 47 page-labels-num-tree.pdf"},
@@ -38,6 +38,11 @@ $td-&gt;runtest(&quot;damaged page labels&quot;, @@ -38,6 +38,11 @@ $td-&gt;runtest(&quot;damaged page labels&quot;,
38 {$td->FILE => "page-labels-num-tree-damaged.out", $td->EXIT_STATUS => 0}, 38 {$td->FILE => "page-labels-num-tree-damaged.out", $td->EXIT_STATUS => 0},
39 $td->NORMALIZE_NEWLINES); 39 $td->NORMALIZE_NEWLINES);
40 40
  41 +$td->runtest("damaged page labels --check",
  42 + {$td->COMMAND => "qpdf --check page-labels-num-tree-damaged.pdf"},
  43 + {$td->FILE => "page-labels-num-tree-damaged-check.out", $td->EXIT_STATUS => 3},
  44 + $td->NORMALIZE_NEWLINES);
  45 +
41 # --set-page-labels 46 # --set-page-labels
42 my @errors = ( 47 my @errors = (
43 ["quack", ".*page label spec must be.*"], 48 ["quack", ".*page label spec must be.*"],
qpdf/qtest/qpdf/outlines-with-loop-check.out 0 → 100644
  1 +checking outlines-with-loop.pdf
  2 +PDF Version: 1.3
  3 +File is not encrypted
  4 +File is not linearized
  5 +No syntax or stream encoding errors found; the file may still contain
  6 +errors that qpdf cannot detect
qpdf/qtest/qpdf/page-labels-num-tree-damaged-check.out 0 → 100644
  1 +checking page-labels-num-tree-damaged.pdf
  2 +PDF Version: 1.3
  3 +File is not encrypted
  4 +File is not linearized
  5 +WARNING: page-labels-num-tree-damaged.pdf (Name/Number tree node (object 2)): attempting to repair after error: page-labels-num-tree-damaged.pdf (Name/Number tree node (object 2)): keys are not sorted in validate
  6 +WARNING: page-labels-num-tree-damaged.pdf (Name/Number tree node (object 37)): item 1 is invalid
  7 +qpdf: operation succeeded with warnings