diff --git a/fuzz/qpdf_extra/16172.fuzz b/fuzz/qpdf_extra/16172.fuzz new file mode 100644 index 00000000..47f6cbcd --- /dev/null +++ b/fuzz/qpdf_extra/16172.fuzz @@ -0,0 +1 @@ + ÿ%PDF-1.4startxref 9223372036854775805 \ No newline at end of file diff --git a/libqpdf/OffsetInputSource.cc b/libqpdf/OffsetInputSource.cc index 2923c388..b6dae255 100644 --- a/libqpdf/OffsetInputSource.cc +++ b/libqpdf/OffsetInputSource.cc @@ -1,10 +1,20 @@ #include +#include +#include +#include OffsetInputSource::OffsetInputSource(PointerHolder proxied, qpdf_offset_t global_offset) : proxied(proxied), global_offset(global_offset) { + if (global_offset < 0) + { + throw std::logic_error( + "OffsetInputSource constructed with negative offset"); + } + this->max_safe_offset = + std::numeric_limits::max() - global_offset; } OffsetInputSource::~OffsetInputSource() @@ -34,12 +44,25 @@ OffsetInputSource::seek(qpdf_offset_t offset, int whence) { if (whence == SEEK_SET) { + if (offset > this->max_safe_offset) + { + std::ostringstream msg; + msg << "seeking to " << offset + << " offset by " << global_offset + << " would cause an overflow of the offset type"; + throw std::range_error(msg.str()); + } this->proxied->seek(offset + global_offset, whence); } else { this->proxied->seek(offset, whence); } + if (tell() < 0) + { + throw std::runtime_error( + "offset input source: seek before beginning of file"); + } } void diff --git a/libqpdf/qpdf/OffsetInputSource.hh b/libqpdf/qpdf/OffsetInputSource.hh index d541db1a..fef23760 100644 --- a/libqpdf/qpdf/OffsetInputSource.hh +++ b/libqpdf/qpdf/OffsetInputSource.hh @@ -24,6 +24,7 @@ class OffsetInputSource: public InputSource private: PointerHolder proxied; qpdf_offset_t global_offset; + qpdf_offset_t max_safe_offset; }; #endif // QPDF_OFFSETINPUTSOURCE_HH