Commit 6fe7b704c7dfb517e4de20fb25536fab1de83d56
1 parent
2c078337
Warn rather than segv on access after closing input source (fixes #495)
Showing
5 changed files
with
65 additions
and
2 deletions
ChangeLog
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<InputSource> 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->runtest("check output", |
| 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
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 ") + | ... | ... |