diff --git a/ChangeLog b/ChangeLog index bcd21011..a9196159 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2019-06-20 Jay Berkenbilt + * Change out_bufsize argument to Pl_Flate's constructor for int to + unsigned int for compatibility with underlying zlib + implementation. + * Add methods to QPDFObjectHandle to return the value of Integer objects as int and unsigned int with range checking and fallback behavior to avoid silent underflow/overflow conditions. diff --git a/include/qpdf/Pl_Flate.hh b/include/qpdf/Pl_Flate.hh index fdd66996..923b33a8 100644 --- a/include/qpdf/Pl_Flate.hh +++ b/include/qpdf/Pl_Flate.hh @@ -27,13 +27,13 @@ class Pl_Flate: public Pipeline { public: - static int const def_bufsize = 65536; + static unsigned int const def_bufsize = 65536; enum action_e { a_inflate, a_deflate }; QPDF_DLL Pl_Flate(char const* identifier, Pipeline* next, - action_e action, int out_bufsize = def_bufsize); + action_e action, unsigned int out_bufsize = def_bufsize); QPDF_DLL virtual ~Pl_Flate(); @@ -43,11 +43,11 @@ class Pl_Flate: public Pipeline virtual void finish(); private: - void handleData(unsigned char* data, int len, int flush); + void handleData(unsigned char* data, size_t len, int flush); void checkError(char const* prefix, int error_code); unsigned char* outbuf; - int out_bufsize; + size_t out_bufsize; action_e action; bool initialized; void* zdata; diff --git a/libqpdf/Pl_Flate.cc b/libqpdf/Pl_Flate.cc index 4cd48046..67e02d2d 100644 --- a/libqpdf/Pl_Flate.cc +++ b/libqpdf/Pl_Flate.cc @@ -1,13 +1,15 @@ #include #include #include +#include #include +#include Pl_Flate::Pl_Flate(char const* identifier, Pipeline* next, - action_e action, int out_bufsize) : + action_e action, unsigned int out_bufsize_int) : Pipeline(identifier, next), - out_bufsize(out_bufsize), + out_bufsize(QIntC::to_size(out_bufsize_int)), action(action), initialized(false) { @@ -19,6 +21,13 @@ Pl_Flate::Pl_Flate(char const* identifier, Pipeline* next, // Windows environment. this->zdata = new z_stream; + if (out_bufsize > UINT_MAX) + { + throw std::runtime_error( + "Pl_Flate: zlib doesn't support buffer" + " sizes larger than unsigned int"); + } + z_stream& zstream = *(static_cast(this->zdata)); zstream.zalloc = 0; zstream.zfree = 0; @@ -26,7 +35,7 @@ Pl_Flate::Pl_Flate(char const* identifier, Pipeline* next, zstream.next_in = 0; zstream.avail_in = 0; zstream.next_out = this->outbuf; - zstream.avail_out = out_bufsize; + zstream.avail_out = QIntC::to_uint(out_bufsize); } Pl_Flate::~Pl_Flate() @@ -77,11 +86,17 @@ Pl_Flate::write(unsigned char* data, size_t len) } void -Pl_Flate::handleData(unsigned char* data, int len, int flush) +Pl_Flate::handleData(unsigned char* data, size_t len, int flush) { + if (len > UINT_MAX) + { + throw std::runtime_error( + "Pl_Flate: zlib doesn't support data" + " blocks larger than int"); + } z_stream& zstream = *(static_cast(this->zdata)); zstream.next_in = data; - zstream.avail_in = len; + zstream.avail_in = QIntC::to_uint(len); if (! this->initialized) { @@ -156,12 +171,13 @@ Pl_Flate::handleData(unsigned char* data, int len, int flush) // needed, so we're done for now. done = true; } - uLong ready = (this->out_bufsize - zstream.avail_out); + uLong ready = + QIntC::to_ulong(this->out_bufsize - zstream.avail_out); if (ready > 0) { this->getNext()->write(this->outbuf, ready); zstream.next_out = this->outbuf; - zstream.avail_out = this->out_bufsize; + zstream.avail_out = QIntC::to_uint(this->out_bufsize); } } break;