Commit 6fe7b704c7dfb517e4de20fb25536fab1de83d56

Authored by Jay Berkenbilt
1 parent 2c078337

Warn rather than segv on access after closing input source (fixes #495)

ChangeLog
  1 +2021-01-06 Jay Berkenbilt <ejb@ql.org>
  2 +
  3 + * Give warnings instead of segfaulting if a QPDF operation is
  4 + attempted after calling closeInputSource(). Fixes #495.
  5 +
1 6 2021-01-05 Jay Berkenbilt <ejb@ql.org>
2 7  
3 8 * 10.1.0: release
... ...
libqpdf/QPDF.cc
... ... @@ -45,6 +45,51 @@ static char const* EMPTY_PDF =
45 45 "110\n"
46 46 "%%EOF\n";
47 47  
  48 +class InvalidInputSource: public InputSource
  49 +{
  50 + public:
  51 + virtual ~InvalidInputSource() = default;
  52 + virtual qpdf_offset_t findAndSkipNextEOL() override
  53 + {
  54 + throwException();
  55 + return 0;
  56 + }
  57 + virtual std::string const& getName() const override
  58 + {
  59 + static std::string name("closed input source");
  60 + return name;
  61 + }
  62 + virtual qpdf_offset_t tell() override
  63 + {
  64 + throwException();
  65 + return 0;
  66 + }
  67 + virtual void seek(qpdf_offset_t offset, int whence) override
  68 + {
  69 + throwException();
  70 + }
  71 + virtual void rewind() override
  72 + {
  73 + throwException();
  74 + }
  75 + virtual size_t read(char* buffer, size_t length) override
  76 + {
  77 + throwException();
  78 + return 0;
  79 + }
  80 + virtual void unreadCh(char ch) override
  81 + {
  82 + throwException();
  83 + }
  84 +
  85 + private:
  86 + void throwException()
  87 + {
  88 + throw std::runtime_error(
  89 + "QPDF operation attempted after closing input source");
  90 + }
  91 +};
  92 +
48 93 QPDF::ForeignStreamData::ForeignStreamData(
49 94 PointerHolder<EncryptionParameters> encp,
50 95 PointerHolder<InputSource> file,
... ... @@ -254,7 +299,7 @@ QPDF::processInputSource(PointerHolder&lt;InputSource&gt; source,
254 299 void
255 300 QPDF::closeInputSource()
256 301 {
257   - this->m->file = 0;
  302 + this->m->file = new InvalidInputSource();
258 303 }
259 304  
260 305 void
... ...
qpdf/qtest/qpdf.test
... ... @@ -1215,7 +1215,13 @@ $td-&gt;runtest(&quot;check output&quot;,
1215 1215 show_ntests();
1216 1216 # ----------
1217 1217 $td->notify("--- Invalid objects ---");
1218   -$n_tests += 2;
  1218 +$n_tests += 3;
  1219 +
  1220 +$td->runtest("closed input source",
  1221 + {$td->COMMAND => "test_driver 73 minimal.pdf"},
  1222 + {$td->FILE => "test73.out",
  1223 + $td->EXIT_STATUS => 0},
  1224 + $td->NORMALIZE_NEWLINES);
1219 1225  
1220 1226 $td->runtest("empty object",
1221 1227 {$td->COMMAND => "qpdf -show-object=7,0 empty-object.pdf"},
... ...
qpdf/qtest/qpdf/test73.out 0 → 100644
  1 +WARNING: closed input source: object 2/0: error reading object: QPDF operation attempted after closing input source
  2 +test 73 done
... ...
qpdf/test_driver.cc
... ... @@ -2300,6 +2300,11 @@ void runtest(int n, char const* filename1, char const* arg2)
2300 2300 buf->getSize());
2301 2301 assert(s.find("/bye") != std::string::npos);
2302 2302 }
  2303 + else if (n == 73)
  2304 + {
  2305 + pdf.closeInputSource();
  2306 + pdf.getRoot().getKey("/Pages").unparseResolved();
  2307 + }
2303 2308 else
2304 2309 {
2305 2310 throw std::runtime_error(std::string("invalid test ") +
... ...