diff options
author | Jay Berkenbilt <ejb@ql.org> | 2021-11-02 22:54:10 +0100 |
---|---|---|
committer | Jay Berkenbilt <ejb@ql.org> | 2021-11-03 14:43:17 +0100 |
commit | 532a4f3d60f6981b22beb32e6ff688ec41f87e26 (patch) | |
tree | 73800f3a6da80171152df8c9236ce390bcd581f4 /libqpdf | |
parent | c491d9f6af8dd2ecfbc5bd70b2054e03ac2521ac (diff) | |
download | qpdf-532a4f3d60f6981b22beb32e6ff688ec41f87e26.tar.zst |
Detect recoverable but invalid zlib data streams (fixes #562)
Diffstat (limited to 'libqpdf')
-rw-r--r-- | libqpdf/Pl_Flate.cc | 35 | ||||
-rw-r--r-- | libqpdf/QPDF_Stream.cc | 8 |
2 files changed, 40 insertions, 3 deletions
diff --git a/libqpdf/Pl_Flate.cc b/libqpdf/Pl_Flate.cc index 1eca837e..ee07b6f1 100644 --- a/libqpdf/Pl_Flate.cc +++ b/libqpdf/Pl_Flate.cc @@ -72,6 +72,21 @@ Pl_Flate::~Pl_Flate() } void +Pl_Flate::setWarnCallback(std::function<void(char const*, int)> callback) +{ + this->m->callback = callback; +} + +void +Pl_Flate::warn(char const* msg, int code) +{ + if (this->m->callback != nullptr) + { + this->m->callback(msg, code); + } +} + +void Pl_Flate::write(unsigned char* data, size_t len) { if (this->m->outbuf.getPointer() == 0) @@ -164,7 +179,14 @@ Pl_Flate::handleData(unsigned char* data, size_t len, int flush) // Probably shouldn't be able to happen, but possible as a // boundary condition: if the last call to inflate exactly // filled the output buffer, it's possible that the next - // call to inflate could have nothing to do. + // call to inflate could have nothing to do. There are PDF + // files in the wild that have this error (including at + // least one in qpdf's test suite). In some cases, we want + // to know about this, because it indicates incorrect + // compression, so call a callback if provided. + this->warn( + "input stream is complete but output may still be valid", + err); done = true; break; @@ -231,8 +253,15 @@ Pl_Flate::finish() } catch (std::exception& e) { - this->getNext()->finish(); - throw e; + try + { + this->getNext()->finish(); + } + catch (...) + { + // ignore secondary exception + } + throw std::runtime_error(e.what()); } this->getNext()->finish(); } diff --git a/libqpdf/QPDF_Stream.cc b/libqpdf/QPDF_Stream.cc index bc3b1b56..14659008 100644 --- a/libqpdf/QPDF_Stream.cc +++ b/libqpdf/QPDF_Stream.cc @@ -503,6 +503,14 @@ QPDF_Stream::pipeStreamData(Pipeline* pipeline, bool* filterp, { pipeline = decode_pipeline; } + Pl_Flate* flate = dynamic_cast<Pl_Flate*>(pipeline); + if (flate != nullptr) + { + flate->setWarnCallback([this](char const* msg, int code) { + warn(QPDFExc(qpdf_e_damaged_pdf, qpdf->getFilename(), + "", this->offset, msg)); + }); + } } } |