Commit 3a9ec47d591c721551ffb7e7e80964664646a12e
Committed by
GitHub
Merge pull request #1596 from m-holger/internal
Add `util::internal_error_if` for concise handling of internal errors
Showing
4 changed files
with
29 additions
and
34 deletions
libqpdf/BitStream.cc
| 1 | #include <qpdf/BitStream.hh> | 1 | #include <qpdf/BitStream.hh> |
| 2 | 2 | ||
| 3 | #include <qpdf/QIntC.hh> | 3 | #include <qpdf/QIntC.hh> |
| 4 | +#include <qpdf/Util.hh> | ||
| 4 | 5 | ||
| 5 | // See comments in bits_functions.hh | 6 | // See comments in bits_functions.hh |
| 6 | #define BITS_READ 1 | 7 | #define BITS_READ 1 |
| 7 | #include <qpdf/bits_functions.hh> | 8 | #include <qpdf/bits_functions.hh> |
| 8 | 9 | ||
| 10 | +using namespace qpdf; | ||
| 11 | + | ||
| 9 | BitStream::BitStream(unsigned char const* p, size_t nbytes) : | 12 | BitStream::BitStream(unsigned char const* p, size_t nbytes) : |
| 10 | start(p), | 13 | start(p), |
| 11 | nbytes(nbytes) | 14 | nbytes(nbytes) |
| @@ -56,9 +59,8 @@ BitStream::skipToNextByte() | @@ -56,9 +59,8 @@ BitStream::skipToNextByte() | ||
| 56 | { | 59 | { |
| 57 | if (bit_offset != 7) { | 60 | if (bit_offset != 7) { |
| 58 | size_t bits_to_skip = bit_offset + 1; | 61 | size_t bits_to_skip = bit_offset + 1; |
| 59 | - if (bits_available < bits_to_skip) { | ||
| 60 | - throw std::logic_error("INTERNAL ERROR: overflow skipping to next byte in bitstream"); | ||
| 61 | - } | 62 | + util::internal_error_if( |
| 63 | + bits_available < bits_to_skip, "overflow skipping to next byte in bitstream"); | ||
| 62 | bit_offset = 7; | 64 | bit_offset = 7; |
| 63 | ++p; | 65 | ++p; |
| 64 | bits_available -= bits_to_skip; | 66 | bits_available -= bits_to_skip; |
libqpdf/BufferInputSource.cc
| @@ -41,9 +41,7 @@ BufferInputSource::~BufferInputSource() | @@ -41,9 +41,7 @@ BufferInputSource::~BufferInputSource() | ||
| 41 | qpdf_offset_t | 41 | qpdf_offset_t |
| 42 | BufferInputSource::findAndSkipNextEOL() | 42 | BufferInputSource::findAndSkipNextEOL() |
| 43 | { | 43 | { |
| 44 | - if (cur_offset < 0) { | ||
| 45 | - throw std::logic_error("INTERNAL ERROR: BufferInputSource offset < 0"); | ||
| 46 | - } | 44 | + util::internal_error_if(cur_offset < 0, "BufferInputSource offset < 0"); |
| 47 | qpdf_offset_t end_pos = max_offset; | 45 | qpdf_offset_t end_pos = max_offset; |
| 48 | if (cur_offset >= end_pos) { | 46 | if (cur_offset >= end_pos) { |
| 49 | last_offset = end_pos; | 47 | last_offset = end_pos; |
| @@ -99,14 +97,10 @@ BufferInputSource::seek(qpdf_offset_t offset, int whence) | @@ -99,14 +97,10 @@ BufferInputSource::seek(qpdf_offset_t offset, int whence) | ||
| 99 | cur_offset = max_offset + offset; | 97 | cur_offset = max_offset + offset; |
| 100 | break; | 98 | break; |
| 101 | 99 | ||
| 102 | - case SEEK_CUR: | 100 | + default: |
| 101 | + util::assertion(whence == SEEK_CUR, "invalid argument to BufferInputSource::seek"); | ||
| 103 | QIntC::range_check(cur_offset, offset); | 102 | QIntC::range_check(cur_offset, offset); |
| 104 | cur_offset += offset; | 103 | cur_offset += offset; |
| 105 | - break; | ||
| 106 | - | ||
| 107 | - default: | ||
| 108 | - throw std::logic_error("INTERNAL ERROR: invalid argument to BufferInputSource::seek"); | ||
| 109 | - break; | ||
| 110 | } | 104 | } |
| 111 | 105 | ||
| 112 | if (cur_offset < 0) { | 106 | if (cur_offset < 0) { |
| @@ -123,9 +117,7 @@ BufferInputSource::rewind() | @@ -123,9 +117,7 @@ BufferInputSource::rewind() | ||
| 123 | size_t | 117 | size_t |
| 124 | BufferInputSource::read(char* buffer, size_t length) | 118 | BufferInputSource::read(char* buffer, size_t length) |
| 125 | { | 119 | { |
| 126 | - if (cur_offset < 0) { | ||
| 127 | - throw std::logic_error("INTERNAL ERROR: BufferInputSource offset < 0"); | ||
| 128 | - } | 120 | + util::internal_error_if(cur_offset < 0, "BufferInputSource offset < 0"); |
| 129 | qpdf_offset_t end_pos = max_offset; | 121 | qpdf_offset_t end_pos = max_offset; |
| 130 | if (cur_offset >= end_pos) { | 122 | if (cur_offset >= end_pos) { |
| 131 | last_offset = end_pos; | 123 | last_offset = end_pos; |
| @@ -230,9 +222,7 @@ BufferInputSource::unreadCh(char ch) | @@ -230,9 +222,7 @@ BufferInputSource::unreadCh(char ch) | ||
| 230 | qpdf_offset_t | 222 | qpdf_offset_t |
| 231 | is::OffsetBuffer::findAndSkipNextEOL() | 223 | is::OffsetBuffer::findAndSkipNextEOL() |
| 232 | { | 224 | { |
| 233 | - if (pos < 0) { | ||
| 234 | - throw std::logic_error("INTERNAL ERROR: is::OffsetBuffer offset < 0"); | ||
| 235 | - } | 225 | + util::internal_error_if(pos < 0, "is::OffsetBuffer offset < 0"); |
| 236 | auto end_pos = static_cast<qpdf_offset_t>(view_.size()); | 226 | auto end_pos = static_cast<qpdf_offset_t>(view_.size()); |
| 237 | if (pos >= end_pos) { | 227 | if (pos >= end_pos) { |
| 238 | last_offset = end_pos + global_offset; | 228 | last_offset = end_pos + global_offset; |
| @@ -276,14 +266,10 @@ is::OffsetBuffer::seek(qpdf_offset_t offset, int whence) | @@ -276,14 +266,10 @@ is::OffsetBuffer::seek(qpdf_offset_t offset, int whence) | ||
| 276 | pos = static_cast<qpdf_offset_t>(view_.size()) + offset; | 266 | pos = static_cast<qpdf_offset_t>(view_.size()) + offset; |
| 277 | break; | 267 | break; |
| 278 | 268 | ||
| 279 | - case SEEK_CUR: | 269 | + default: |
| 270 | + util::assertion(whence == SEEK_CUR, "invalid argument to BufferInputSource::seek"); | ||
| 280 | QIntC::range_check(pos, offset); | 271 | QIntC::range_check(pos, offset); |
| 281 | pos += offset; | 272 | pos += offset; |
| 282 | - break; | ||
| 283 | - | ||
| 284 | - default: | ||
| 285 | - throw std::logic_error("INTERNAL ERROR: invalid argument to BufferInputSource::seek"); | ||
| 286 | - break; | ||
| 287 | } | 273 | } |
| 288 | 274 | ||
| 289 | if (pos < 0) { | 275 | if (pos < 0) { |
| @@ -294,9 +280,7 @@ is::OffsetBuffer::seek(qpdf_offset_t offset, int whence) | @@ -294,9 +280,7 @@ is::OffsetBuffer::seek(qpdf_offset_t offset, int whence) | ||
| 294 | size_t | 280 | size_t |
| 295 | is::OffsetBuffer::read(char* buffer, size_t length) | 281 | is::OffsetBuffer::read(char* buffer, size_t length) |
| 296 | { | 282 | { |
| 297 | - if (pos < 0) { | ||
| 298 | - throw std::logic_error("INTERNAL ERROR: is::OffsetBuffer offset < 0"); | ||
| 299 | - } | 283 | + util::internal_error_if(pos < 0, "is::OffsetBuffer offset < 0"); |
| 300 | auto end_pos = static_cast<qpdf_offset_t>(view_.size()); | 284 | auto end_pos = static_cast<qpdf_offset_t>(view_.size()); |
| 301 | if (pos >= end_pos) { | 285 | if (pos >= end_pos) { |
| 302 | last_offset = end_pos + global_offset; | 286 | last_offset = end_pos + global_offset; |
libqpdf/QPDF_objects.cc
| @@ -238,13 +238,11 @@ Objects::parse(char const* password) | @@ -238,13 +238,11 @@ Objects::parse(char const* password) | ||
| 238 | void | 238 | void |
| 239 | Objects::inParse(bool v) | 239 | Objects::inParse(bool v) |
| 240 | { | 240 | { |
| 241 | - if (m->in_parse == v) { | 241 | + util::internal_error_if( |
| 242 | + m->in_parse == v, "QPDF: re-entrant parsing detected" | ||
| 242 | // This happens if QPDFParser::parse tries to resolve an indirect object while it is | 243 | // This happens if QPDFParser::parse tries to resolve an indirect object while it is |
| 243 | // parsing. | 244 | // parsing. |
| 244 | - throw std::logic_error( | ||
| 245 | - "QPDF: re-entrant parsing detected. This is a qpdf bug." | ||
| 246 | - " Please report at https://github.com/qpdf/qpdf/issues."); | ||
| 247 | - } | 245 | + ); |
| 248 | m->in_parse = v; | 246 | m->in_parse = v; |
| 249 | } | 247 | } |
| 250 | 248 | ||
| @@ -535,7 +533,7 @@ Objects::read_xref(qpdf_offset_t xref_offset, bool in_stream_recovery) | @@ -535,7 +533,7 @@ Objects::read_xref(qpdf_offset_t xref_offset, bool in_stream_recovery) | ||
| 535 | max_obj = std::max(max_obj, *(m->deleted_objects.rbegin())); | 533 | max_obj = std::max(max_obj, *(m->deleted_objects.rbegin())); |
| 536 | } | 534 | } |
| 537 | if (size < 1 || (size - 1) != max_obj) { | 535 | if (size < 1 || (size - 1) != max_obj) { |
| 538 | - if ((size - 2) == max_obj ){//&& qpdf.getObject(max_obj, 0).isStreamOfType("/XRef")) { | 536 | + if ((size - 2) == max_obj) { //&& qpdf.getObject(max_obj, 0).isStreamOfType("/XRef")) { |
| 539 | warn(damagedPDF( | 537 | warn(damagedPDF( |
| 540 | "", | 538 | "", |
| 541 | -1, | 539 | -1, |
libqpdf/qpdf/Util.hh
| @@ -7,6 +7,8 @@ | @@ -7,6 +7,8 @@ | ||
| 7 | #include <string> | 7 | #include <string> |
| 8 | #include <utility> | 8 | #include <utility> |
| 9 | 9 | ||
| 10 | +using namespace std::literals; | ||
| 11 | + | ||
| 10 | namespace qpdf::util | 12 | namespace qpdf::util |
| 11 | { | 13 | { |
| 12 | // qpdf::util is a collection of useful utility functions for qpdf internal use. It includes | 14 | // qpdf::util is a collection of useful utility functions for qpdf internal use. It includes |
| @@ -17,13 +19,22 @@ namespace qpdf::util | @@ -17,13 +19,22 @@ namespace qpdf::util | ||
| 17 | // | 19 | // |
| 18 | // DO NOT USE unless it is impractical or unnecessary to cover violations during CI Testing. | 20 | // DO NOT USE unless it is impractical or unnecessary to cover violations during CI Testing. |
| 19 | inline void | 21 | inline void |
| 20 | - assertion(bool cond, std::string const msg) | 22 | + assertion(bool cond, std::string const& msg) |
| 21 | { | 23 | { |
| 22 | if (!cond) { | 24 | if (!cond) { |
| 23 | throw std::logic_error(msg); | 25 | throw std::logic_error(msg); |
| 24 | } | 26 | } |
| 25 | } | 27 | } |
| 26 | 28 | ||
| 29 | + inline void | ||
| 30 | + internal_error_if(bool cond, std::string const& msg) | ||
| 31 | + { | ||
| 32 | + if (cond) { | ||
| 33 | + throw std::logic_error("INTERNAL ERROR: "s.append(msg).append( | ||
| 34 | + "\nThis is a qpdf bug. Please report at https://github.com/qpdf/qpdf/issues")); | ||
| 35 | + } | ||
| 36 | + } | ||
| 37 | + | ||
| 27 | inline constexpr char | 38 | inline constexpr char |
| 28 | hex_decode_char(char digit) | 39 | hex_decode_char(char digit) |
| 29 | { | 40 | { |