Commit ac57c049d82425039e4a46cd76401b6c45464734

Authored by m-holger
1 parent 7c148c15

Introduce `util::internal_error_if` for concise handling of internal errors

- replace repetitive error handling with utility functions in BufferInputSource, OffsetBuffer, and QPDF_objects.

- Remove some "internal error" labels from errors that could be due to user logic errors.
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 {