Commit 119f2a4b684aae7cec8841412a5fc89bcbae404d

Authored by Jay Berkenbilt
1 parent 7be97b3e

Add method to terminate content stream parsing

ChangeLog
  1 +2013-03-03 Jay Berkenbilt <ejb@ql.org>
  2 +
  3 + * Add protected terminateParsing method to
  4 + QPDFObjectHandle::ParserCallbacks that implementor can call to
  5 + terminate parsing of a content stream.
  6 +
1 7 2013-02-28 Jay Berkenbilt <ejb@ql.org>
2 8  
3 9 * Favor fopen_s and strerror_s on MSVC to avoid CRT security
... ...
include/qpdf/QPDFObjectHandle.hh
... ... @@ -83,6 +83,13 @@ class QPDFObjectHandle
83 83 }
84 84 virtual void handleObject(QPDFObjectHandle) = 0;
85 85 virtual void handleEOF() = 0;
  86 +
  87 + protected:
  88 + // Implementors may call this method during parsing to
  89 + // terminate parsing early. This method throws an exception
  90 + // that is caught by parseContentStream, so its effect is
  91 + // immediate.
  92 + void terminateParsing();
86 93 };
87 94  
88 95  
... ...
libqpdf/QPDFObjectHandle.cc
... ... @@ -23,6 +23,16 @@
23 23 #include <stdlib.h>
24 24 #include <ctype.h>
25 25  
  26 +class TerminateParsing
  27 +{
  28 +};
  29 +
  30 +void
  31 +QPDFObjectHandle::ParserCallbacks::terminateParsing()
  32 +{
  33 + throw TerminateParsing();
  34 +}
  35 +
26 36 QPDFObjectHandle::QPDFObjectHandle() :
27 37 initialized(false),
28 38 objid(0),
... ... @@ -728,7 +738,14 @@ QPDFObjectHandle::parseContentStream(QPDFObjectHandle stream_or_array,
728 738 throw std::logic_error(
729 739 "QPDFObjectHandle: parseContentStream called on non-stream");
730 740 }
731   - parseContentStream_internal(stream, callbacks);
  741 + try
  742 + {
  743 + parseContentStream_internal(stream, callbacks);
  744 + }
  745 + catch (TerminateParsing&)
  746 + {
  747 + return;
  748 + }
732 749 }
733 750 callbacks->handleEOF();
734 751 }
... ...
qpdf/qtest/qpdf.test
... ... @@ -199,7 +199,7 @@ $td-&gt;runtest(&quot;remove page we don&#39;t have&quot;,
199 199 show_ntests();
200 200 # ----------
201 201 $td->notify("--- Miscellaneous Tests ---");
202   -$n_tests += 61;
  202 +$n_tests += 62;
203 203  
204 204 $td->runtest("qpdf version",
205 205 {$td->COMMAND => "qpdf --version"},
... ... @@ -478,6 +478,11 @@ $td-&gt;runtest(&quot;tokenize content streams&quot;,
478 478 {$td->FILE => "tokenize-content-streams.out",
479 479 $td->EXIT_STATUS => 0},
480 480 $td->NORMALIZE_NEWLINES);
  481 +$td->runtest("terminate parsing",
  482 + {$td->COMMAND => "test_driver 37 terminate-parsing.pdf"},
  483 + {$td->FILE => "terminate-parsing.out",
  484 + $td->EXIT_STATUS => 0},
  485 + $td->NORMALIZE_NEWLINES);
481 486 $td->runtest("content stream errors",
482 487 {$td->COMMAND => "qpdf --check content-stream-errors.pdf"},
483 488 {$td->FILE => "content-stream-errors.out",
... ...
qpdf/qtest/qpdf/terminate-parsing.out 0 → 100644
  1 +name: /potato
  2 +test suite: terminating parsing
  3 +real: 0.1
  4 +integer: 0
  5 +integer: 0
  6 +real: 0.1
  7 +integer: 0
  8 +integer: 0
  9 +operator: cm
  10 +operator: q
  11 +integer: 0
  12 +real: 1.1999
  13 +real: -1.1999
  14 +integer: 0
  15 +real: 121.19
  16 +real: 150.009
  17 +operator: cm
  18 +operator: BI
  19 +name: /CS
  20 +name: /G
  21 +name: /W
  22 +integer: 1
  23 +name: /H
  24 +integer: 1
  25 +name: /BPC
  26 +integer: 8
  27 +name: /F
  28 +name: /Fl
  29 +name: /DP
  30 +dictionary: << /Columns 1 /Predictor 15 >>
  31 +operator: ID
  32 +inline-image: 789c63fc0f0001030101
  33 +operator: EI
  34 +operator: Q
  35 +operator: q
  36 +integer: 0
  37 +real: 35.997
  38 +real: -128.389
  39 +integer: 0
  40 +real: 431.964
  41 +real: 7269.02
  42 +operator: cm
  43 +operator: BI
  44 +name: /CS
  45 +name: /G
  46 +name: /W
  47 +integer: 30
  48 +name: /H
  49 +integer: 107
  50 +name: /BPC
  51 +integer: 8
  52 +name: /F
  53 +name: /Fl
  54 +name: /DP
  55 +dictionary: << /Columns 30 /Predictor 15 >>
  56 +operator: ID
  57 +inline-image: 789cedd1a11100300800b1b2ffd06503148283bc8dfcf8af2a306ee352eff2e06318638c31c63b3801627b620a
  58 +operator: EI
  59 +operator: Q
  60 +operator: q
  61 +integer: 0
  62 +real: 38.3968
  63 +real: -93.5922
  64 +integer: 0
  65 +real: 431.964
  66 +real: 7567.79
  67 +operator: cm
  68 +operator: BI
  69 +name: /CS
  70 +name: /G
  71 +name: /W
  72 +integer: 32
  73 +name: /H
  74 +integer: 78
  75 +name: /BPC
  76 +integer: 8
  77 +name: /F
  78 +name: /Fl
  79 +name: /DP
  80 +dictionary: << /Columns 32 /Predictor 15 >>
  81 +operator: ID
  82 +inline-image: 789c63fccf801f308e2a185530aa60882a20203faa605401890a0643aa1e5530aa6054010d140000bdd03c13
  83 +operator: EI
  84 +operator: Q
  85 +-EOF-
  86 +test 37 done
... ...
qpdf/qtest/qpdf/terminate-parsing.pdf 0 → 100644
No preview for this file type
qpdf/test_driver.cc
... ... @@ -72,6 +72,11 @@ class ParserCallbacks: public QPDFObjectHandle::ParserCallbacks
72 72 void
73 73 ParserCallbacks::handleObject(QPDFObjectHandle obj)
74 74 {
  75 + if (obj.isName() && (obj.getName() == "/Abort"))
  76 + {
  77 + std::cout << "test suite: terminating parsing" << std::endl;
  78 + terminateParsing();
  79 + }
75 80 std::cout << obj.getTypeName() << ": ";
76 81 if (obj.isInlineImage())
77 82 {
... ...