From ad8081daf597b8f46696d5ddae82770ab419ad82 Mon Sep 17 00:00:00 2001 From: Jay Berkenbilt Date: Tue, 27 Aug 2019 10:46:06 -0400 Subject: Fix fuzz issue 15442 (overflow checking in BufferInputSource) --- libqpdf/BufferInputSource.cc | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) (limited to 'libqpdf') diff --git a/libqpdf/BufferInputSource.cc b/libqpdf/BufferInputSource.cc index 23bad5f0..cbb2e7f0 100644 --- a/libqpdf/BufferInputSource.cc +++ b/libqpdf/BufferInputSource.cc @@ -3,6 +3,8 @@ #include #include #include +#include +#include BufferInputSource::Members::Members(bool own_memory, std::string const& description, @@ -10,7 +12,8 @@ BufferInputSource::Members::Members(bool own_memory, own_memory(own_memory), description(description), buf(buf), - cur_offset(0) + cur_offset(0), + max_offset(buf ? QIntC::to_offset(buf->getSize()) : 0) { } @@ -29,6 +32,7 @@ BufferInputSource::BufferInputSource(std::string const& description, m(new Members(true, description, 0)) { this->m->buf = new Buffer(contents.length()); + this->m->max_offset = QIntC::to_offset(this->m->buf->getSize()); unsigned char* bp = this->m->buf->getBuffer(); memcpy(bp, contents.c_str(), contents.length()); } @@ -41,12 +45,6 @@ BufferInputSource::~BufferInputSource() } } -qpdf_offset_t const -BufferInputSource::bufSizeAsOffset() const -{ - return QIntC::to_offset(this->m->buf->getSize()); -} - qpdf_offset_t BufferInputSource::findAndSkipNextEOL() { @@ -54,7 +52,7 @@ BufferInputSource::findAndSkipNextEOL() { throw std::logic_error("INTERNAL ERROR: BufferInputSource offset < 0"); } - qpdf_offset_t end_pos = bufSizeAsOffset(); + qpdf_offset_t end_pos = this->m->max_offset; if (this->m->cur_offset >= end_pos) { this->last_offset = end_pos; @@ -102,6 +100,20 @@ BufferInputSource::tell() return this->m->cur_offset; } +void +BufferInputSource::range_check(qpdf_offset_t cur, qpdf_offset_t delta) +{ + if ((delta > 0) && + ((std::numeric_limits::max() - cur) < delta)) + { + std::ostringstream msg; + msg << "seeking forward from " << cur + << " by " << delta + << " would cause an overflow of the offset type"; + throw std::range_error(msg.str()); + } +} + void BufferInputSource::seek(qpdf_offset_t offset, int whence) { @@ -112,10 +124,12 @@ BufferInputSource::seek(qpdf_offset_t offset, int whence) break; case SEEK_END: - this->m->cur_offset = bufSizeAsOffset() + offset; + range_check(this->m->max_offset, offset); + this->m->cur_offset = this->m->max_offset + offset; break; case SEEK_CUR: + range_check(this->m->cur_offset, offset); this->m->cur_offset += offset; break; @@ -145,7 +159,7 @@ BufferInputSource::read(char* buffer, size_t length) { throw std::logic_error("INTERNAL ERROR: BufferInputSource offset < 0"); } - qpdf_offset_t end_pos = bufSizeAsOffset(); + qpdf_offset_t end_pos = this->m->max_offset; if (this->m->cur_offset >= end_pos) { this->last_offset = end_pos; -- cgit v1.2.3-54-g00ecf