From c916dcf9733b8fbb928b30ada7fab4d4e1b78b2b Mon Sep 17 00:00:00 2001 From: m-holger Date: Wed, 7 Aug 2024 17:20:19 +0100 Subject: [PATCH] Add new protected inline method Pipeline::next Also, tidy pipeline constructors and make subclasses final where possible. --- include/qpdf/Pipeline.hh | 8 +++++- include/qpdf/Pl_Count.hh | 4 +-- include/qpdf/Pl_Function.hh | 9 +++---- include/qpdf/Pl_QPDFTokenizer.hh | 2 +- include/qpdf/Pl_RunLength.hh | 4 +-- libqpdf/Pipeline.cc | 6 ++--- libqpdf/Pl_AES_PDF.cc | 17 +++++-------- libqpdf/Pl_ASCII85Decoder.cc | 14 +++++----- libqpdf/Pl_ASCIIHexDecoder.cc | 14 +++++----- libqpdf/Pl_Base64.cc | 15 +++++------ libqpdf/Pl_Buffer.cc | 8 +++--- libqpdf/Pl_Concatenate.cc | 9 +++++-- libqpdf/Pl_Count.cc | 11 ++++---- libqpdf/Pl_DCT.cc | 13 ++++++---- libqpdf/Pl_Flate.cc | 9 ++++--- libqpdf/Pl_Function.cc | 8 +++--- libqpdf/Pl_LZWDecoder.cc | 41 +++++++++++++----------------- libqpdf/Pl_MD5.cc | 12 ++++----- libqpdf/Pl_PNGFilter.cc | 20 +++++++-------- libqpdf/Pl_QPDFTokenizer.cc | 6 ++--- libqpdf/Pl_RC4.cc | 9 ++++--- libqpdf/Pl_RunLength.cc | 22 ++++++++-------- libqpdf/Pl_SHA2.cc | 8 +++--- libqpdf/Pl_String.cc | 8 +++--- libqpdf/Pl_TIFFPredictor.cc | 21 ++++++++------- libqpdf/QPDFLogger.cc | 13 ++++++---- libqpdf/QPDFObjectHandle.cc | 20 +++++++-------- libqpdf/qpdf/Pl_AES_PDF.hh | 23 ++++++++--------- libqpdf/qpdf/Pl_ASCII85Decoder.hh | 14 +++++----- libqpdf/qpdf/Pl_ASCIIHexDecoder.hh | 14 +++++----- libqpdf/qpdf/Pl_Base64.hh | 16 ++++++------ libqpdf/qpdf/Pl_LZWDecoder.hh | 26 +++++++++---------- libqpdf/qpdf/Pl_MD5.hh | 21 ++++++++------- libqpdf/qpdf/Pl_PNGFilter.hh | 27 ++++++++++---------- libqpdf/qpdf/Pl_RC4.hh | 8 +++--- libqpdf/qpdf/Pl_SHA2.hh | 25 +++++++++--------- libqpdf/qpdf/Pl_TIFFPredictor.hh | 1 - 37 files changed, 256 insertions(+), 250 deletions(-) diff --git a/include/qpdf/Pipeline.hh b/include/qpdf/Pipeline.hh index 50b5fa61..820b0d2f 100644 --- a/include/qpdf/Pipeline.hh +++ b/include/qpdf/Pipeline.hh @@ -98,13 +98,19 @@ class QPDF_DLL_CLASS Pipeline protected: QPDF_DLL Pipeline* getNext(bool allow_null = false); + QPDF_DLL + Pipeline* + next() const noexcept + { + return next_; + } std::string identifier; private: Pipeline(Pipeline const&) = delete; Pipeline& operator=(Pipeline const&) = delete; - Pipeline* next; + Pipeline* next_; }; #endif // PIPELINE_HH diff --git a/include/qpdf/Pl_Count.hh b/include/qpdf/Pl_Count.hh index b95ad040..633108d6 100644 --- a/include/qpdf/Pl_Count.hh +++ b/include/qpdf/Pl_Count.hh @@ -57,8 +57,8 @@ class QPDF_DLL_CLASS Pl_Count: public Pipeline Members(Members const&) = delete; // Must be qpdf_offset_t, not size_t, to handle writing more than size_t can handle. - qpdf_offset_t count; - unsigned char last_char; + qpdf_offset_t count{0}; + unsigned char last_char{'\0'}; }; std::shared_ptr m; diff --git a/include/qpdf/Pl_Function.hh b/include/qpdf/Pl_Function.hh index 9dc0b564..20f26554 100644 --- a/include/qpdf/Pl_Function.hh +++ b/include/qpdf/Pl_Function.hh @@ -19,6 +19,10 @@ #ifndef PL_FUNCTION_HH #define PL_FUNCTION_HH +#include + +#include + // This pipeline calls an arbitrary function with whatever data is passed to it. This pipeline can // be reused. // @@ -29,11 +33,6 @@ // // It is okay to keep calling write() after a previous write throws an exception as long as the // delegated function allows it. - -#include - -#include - class QPDF_DLL_CLASS Pl_Function: public Pipeline { public: diff --git a/include/qpdf/Pl_QPDFTokenizer.hh b/include/qpdf/Pl_QPDFTokenizer.hh index 79ba8435..47a9fb01 100644 --- a/include/qpdf/Pl_QPDFTokenizer.hh +++ b/include/qpdf/Pl_QPDFTokenizer.hh @@ -64,7 +64,7 @@ class QPDF_DLL_CLASS Pl_QPDFTokenizer: public Pipeline Members(); Members(Members const&) = delete; - QPDFObjectHandle::TokenFilter* filter; + QPDFObjectHandle::TokenFilter* filter{nullptr}; QPDFTokenizer tokenizer; Pl_Buffer buf; }; diff --git a/include/qpdf/Pl_RunLength.hh b/include/qpdf/Pl_RunLength.hh index 4ee8fba0..89c89c2c 100644 --- a/include/qpdf/Pl_RunLength.hh +++ b/include/qpdf/Pl_RunLength.hh @@ -59,9 +59,9 @@ class QPDF_DLL_CLASS Pl_RunLength: public Pipeline Members(Members const&) = delete; action_e action; - state_e state; + state_e state{st_top}; unsigned char buf[128]; - unsigned int length; + unsigned int length{0}; std::string out; }; diff --git a/libqpdf/Pipeline.cc b/libqpdf/Pipeline.cc index 3f5fc3bc..d7da037a 100644 --- a/libqpdf/Pipeline.cc +++ b/libqpdf/Pipeline.cc @@ -5,18 +5,18 @@ Pipeline::Pipeline(char const* identifier, Pipeline* next) : identifier(identifier), - next(next) + next_(next) { } Pipeline* Pipeline::getNext(bool allow_null) { - if ((this->next == nullptr) && (!allow_null)) { + if (!next_ && !allow_null) { throw std::logic_error( this->identifier + ": Pipeline::getNext() called on pipeline with no next"); } - return this->next; + return next_; } std::string diff --git a/libqpdf/Pl_AES_PDF.cc b/libqpdf/Pl_AES_PDF.cc index e1a3ea33..d621bdd8 100644 --- a/libqpdf/Pl_AES_PDF.cc +++ b/libqpdf/Pl_AES_PDF.cc @@ -18,14 +18,11 @@ Pl_AES_PDF::Pl_AES_PDF( Pipeline(identifier, next), crypto(QPDFCryptoProvider::getImpl()), encrypt(encrypt), - cbc_mode(true), - first(true), - offset(0), - key_bytes(key_bytes), - use_zero_iv(false), - use_specified_iv(false), - disable_padding(false) + key_bytes(key_bytes) { + if (!next) { + throw std::logic_error("Attempt to create Pl_AES_PDF with nullptr as next"); + } this->key = std::make_unique(key_bytes); std::memcpy(this->key.get(), key, key_bytes); std::memset(this->inbuf, 0, this->buf_size); @@ -120,7 +117,7 @@ Pl_AES_PDF::finish() flush(!this->disable_padding); } this->crypto->rijndael_finalize(); - getNext()->finish(); + next()->finish(); } void @@ -157,7 +154,7 @@ Pl_AES_PDF::flush(bool strip_padding) // output stream. initializeVector(); if (!(this->use_zero_iv || this->use_specified_iv)) { - getNext()->write(this->cbc_block, this->buf_size); + next()->write(this->cbc_block, this->buf_size); } } else if (this->use_zero_iv || this->use_specified_iv) { // Initialize vector with zeroes; zero vector was not written to the beginning of @@ -196,5 +193,5 @@ Pl_AES_PDF::flush(bool strip_padding) } } this->offset = 0; - getNext()->write(this->outbuf, bytes); + next()->write(this->outbuf, bytes); } diff --git a/libqpdf/Pl_ASCII85Decoder.cc b/libqpdf/Pl_ASCII85Decoder.cc index aef8718d..76b73114 100644 --- a/libqpdf/Pl_ASCII85Decoder.cc +++ b/libqpdf/Pl_ASCII85Decoder.cc @@ -5,11 +5,11 @@ #include Pl_ASCII85Decoder::Pl_ASCII85Decoder(char const* identifier, Pipeline* next) : - Pipeline(identifier, next), - pos(0), - eod(0) + Pipeline(identifier, next) { - memset(this->inbuf, 117, 5); + if (!next) { + throw std::logic_error("Attempt to create Pl_ASCII85Decoder with nullptr as next"); + } } void @@ -52,7 +52,7 @@ Pl_ASCII85Decoder::write(unsigned char const* buf, size_t len) QTC::TC("libtests", "Pl_ASCII85Decoder read z"); unsigned char zeroes[4]; memset(zeroes, '\0', 4); - getNext()->write(zeroes, 4); + next()->write(zeroes, 4); } break; @@ -97,12 +97,12 @@ Pl_ASCII85Decoder::flush() this->pos = 0; memset(this->inbuf, 117, 5); - getNext()->write(outbuf, t); + next()->write(outbuf, t); } void Pl_ASCII85Decoder::finish() { flush(); - getNext()->finish(); + next()->finish(); } diff --git a/libqpdf/Pl_ASCIIHexDecoder.cc b/libqpdf/Pl_ASCIIHexDecoder.cc index 7cc57a70..b78d5543 100644 --- a/libqpdf/Pl_ASCIIHexDecoder.cc +++ b/libqpdf/Pl_ASCIIHexDecoder.cc @@ -5,13 +5,11 @@ #include Pl_ASCIIHexDecoder::Pl_ASCIIHexDecoder(char const* identifier, Pipeline* next) : - Pipeline(identifier, next), - pos(0), - eod(false) + Pipeline(identifier, next) { - this->inbuf[0] = '0'; - this->inbuf[1] = '0'; - this->inbuf[2] = '\0'; + if (!next) { + throw std::logic_error("Attempt to create Pl_ASCIIHexDecoder with nullptr as next"); + } } void @@ -85,12 +83,12 @@ Pl_ASCIIHexDecoder::flush() this->inbuf[1] = '0'; this->inbuf[2] = '\0'; - getNext()->write(&ch, 1); + next()->write(&ch, 1); } void Pl_ASCIIHexDecoder::finish() { flush(); - getNext()->finish(); + next()->finish(); } diff --git a/libqpdf/Pl_Base64.cc b/libqpdf/Pl_Base64.cc index e42c9cb6..4fa4091b 100644 --- a/libqpdf/Pl_Base64.cc +++ b/libqpdf/Pl_Base64.cc @@ -25,12 +25,11 @@ to_i(int i) Pl_Base64::Pl_Base64(char const* identifier, Pipeline* next, action_e action) : Pipeline(identifier, next), - action(action), - pos(0), - end_of_data(false), - finished(false) + action(action) { - reset(); + if (!next) { + throw std::logic_error("Attempt to create Pl_Base64 with nullptr as next"); + } } void @@ -125,7 +124,7 @@ Pl_Base64::flush_decode() to_uc(0xff & outval), }; - getNext()->write(out, QIntC::to_size(3 - pad)); + next()->write(out, QIntC::to_size(3 - pad)); } void @@ -158,7 +157,7 @@ Pl_Base64::flush_encode() for (size_t i = 0; i < 3 - this->pos; ++i) { out[3 - i] = '='; } - getNext()->write(out, 4); + next()->write(out, 4); } void @@ -176,7 +175,7 @@ Pl_Base64::finish() flush(); } this->finished = true; - getNext()->finish(); + next()->finish(); } void diff --git a/libqpdf/Pl_Buffer.cc b/libqpdf/Pl_Buffer.cc index 1babe6e1..86389d6f 100644 --- a/libqpdf/Pl_Buffer.cc +++ b/libqpdf/Pl_Buffer.cc @@ -25,8 +25,8 @@ Pl_Buffer::write(unsigned char const* buf, size_t len) m->data.append(reinterpret_cast(buf), len); m->ready = false; - if (getNext(true)) { - getNext()->write(buf, len); + if (next()) { + next()->write(buf, len); } } @@ -34,8 +34,8 @@ void Pl_Buffer::finish() { m->ready = true; - if (getNext(true)) { - getNext()->finish(); + if (next()) { + next()->finish(); } } diff --git a/libqpdf/Pl_Concatenate.cc b/libqpdf/Pl_Concatenate.cc index 82ec0bd4..339c1c56 100644 --- a/libqpdf/Pl_Concatenate.cc +++ b/libqpdf/Pl_Concatenate.cc @@ -1,8 +1,13 @@ #include +#include + Pl_Concatenate::Pl_Concatenate(char const* identifier, Pipeline* next) : Pipeline(identifier, next) { + if (!next) { + throw std::logic_error("Attempt to create Pl_Concatenate with nullptr as next"); + } } Pl_Concatenate::~Pl_Concatenate() // NOLINT (modernize-use-equals-default) @@ -13,7 +18,7 @@ Pl_Concatenate::~Pl_Concatenate() // NOLINT (modernize-use-equals-default) void Pl_Concatenate::write(unsigned char const* data, size_t len) { - getNext()->write(data, len); + next()->write(data, len); } void @@ -24,5 +29,5 @@ Pl_Concatenate::finish() void Pl_Concatenate::manualFinish() { - getNext()->finish(); + next()->finish(); } diff --git a/libqpdf/Pl_Count.cc b/libqpdf/Pl_Count.cc index 4a0d6cef..912f44ec 100644 --- a/libqpdf/Pl_Count.cc +++ b/libqpdf/Pl_Count.cc @@ -2,9 +2,7 @@ #include -Pl_Count::Members::Members() : - count(0), - last_char('\0') +Pl_Count::Members::Members() { } @@ -12,6 +10,9 @@ Pl_Count::Pl_Count(char const* identifier, Pipeline* next) : Pipeline(identifier, next), m(new Members()) { + if (!next) { + throw std::logic_error("Attempt to create Pl_Count with nullptr as next"); + } } Pl_Count::~Pl_Count() // NOLINT (modernize-use-equals-default) @@ -25,14 +26,14 @@ Pl_Count::write(unsigned char const* buf, size_t len) if (len) { m->count += QIntC::to_offset(len); m->last_char = buf[len - 1]; - getNext()->write(buf, len); + next()->write(buf, len); } } void Pl_Count::finish() { - getNext()->finish(); + next()->finish(); } qpdf_offset_t diff --git a/libqpdf/Pl_DCT.cc b/libqpdf/Pl_DCT.cc index 3288a298..f7b37a24 100644 --- a/libqpdf/Pl_DCT.cc +++ b/libqpdf/Pl_DCT.cc @@ -78,6 +78,9 @@ Pl_DCT::Pl_DCT(char const* identifier, Pipeline* next) : Pipeline(identifier, next), m(new Members()) { + if (!next) { + throw std::logic_error("Attempt to create Pl_DCT with nullptr as next"); + } } void @@ -133,7 +136,7 @@ Pl_DCT::finish() // Special case: empty data will never succeed and probably means we're calling finish a // second time from an exception handler. delete b; - this->getNext()->finish(); + next()->finish(); return; } @@ -300,7 +303,7 @@ Pl_DCT::compress(void* cinfo_p, Buffer* b) static int const BUF_SIZE = 65536; auto outbuffer_ph = std::make_unique(BUF_SIZE); unsigned char* outbuffer = outbuffer_ph.get(); - jpeg_pipeline_dest(cinfo, outbuffer, BUF_SIZE, this->getNext()); + jpeg_pipeline_dest(cinfo, outbuffer, BUF_SIZE, next()); cinfo->image_width = m->image_width; cinfo->image_height = m->image_height; @@ -326,7 +329,7 @@ Pl_DCT::compress(void* cinfo_p, Buffer* b) (void)jpeg_write_scanlines(cinfo, row_pointer, 1); } jpeg_finish_compress(cinfo); - this->getNext()->finish(); + next()->finish(); } void @@ -370,8 +373,8 @@ Pl_DCT::decompress(void* cinfo_p, Buffer* b) (void)jpeg_start_decompress(cinfo); while (cinfo->output_scanline < cinfo->output_height) { (void)jpeg_read_scanlines(cinfo, buffer, 1); - getNext()->write(buffer[0], width * sizeof(buffer[0][0])); + next()->write(buffer[0], width * sizeof(buffer[0][0])); } (void)jpeg_finish_decompress(cinfo); - getNext()->finish(); + next()->finish(); } diff --git a/libqpdf/Pl_Flate.cc b/libqpdf/Pl_Flate.cc index ad680492..78a9b47e 100644 --- a/libqpdf/Pl_Flate.cc +++ b/libqpdf/Pl_Flate.cc @@ -61,6 +61,9 @@ Pl_Flate::Pl_Flate( Pipeline(identifier, next), m(new Members(QIntC::to_size(out_bufsize_int), action)) { + if (!next) { + throw std::logic_error("Attempt to create Pl_Flate with nullptr as next"); + } } Pl_Flate::~Pl_Flate() // NOLINT (modernize-use-equals-default) @@ -187,7 +190,7 @@ Pl_Flate::handleData(unsigned char const* data, size_t len, int flush) throw std::runtime_error("PL_Flate memory limit exceeded"); } } - this->getNext()->write(m->outbuf.get(), ready); + next()->write(m->outbuf.get(), ready); zstream.next_out = m->outbuf.get(); zstream.avail_out = QIntC::to_uint(m->out_bufsize); } @@ -228,13 +231,13 @@ Pl_Flate::finish() } } catch (std::exception& e) { try { - this->getNext()->finish(); + next()->finish(); } catch (...) { // ignore secondary exception } throw std::runtime_error(e.what()); } - this->getNext()->finish(); + next()->finish(); } void diff --git a/libqpdf/Pl_Function.cc b/libqpdf/Pl_Function.cc index 00d7f5b0..3bcef45a 100644 --- a/libqpdf/Pl_Function.cc +++ b/libqpdf/Pl_Function.cc @@ -48,15 +48,15 @@ void Pl_Function::write(unsigned char const* buf, size_t len) { m->fn(buf, len); - if (getNext(true)) { - getNext()->write(buf, len); + if (next()) { + next()->write(buf, len); } } void Pl_Function::finish() { - if (getNext(true)) { - getNext()->finish(); + if (next()) { + next()->finish(); } } diff --git a/libqpdf/Pl_LZWDecoder.cc b/libqpdf/Pl_LZWDecoder.cc index 9abb69cd..96915004 100644 --- a/libqpdf/Pl_LZWDecoder.cc +++ b/libqpdf/Pl_LZWDecoder.cc @@ -8,25 +8,20 @@ Pl_LZWDecoder::Pl_LZWDecoder(char const* identifier, Pipeline* next, bool early_code_change) : Pipeline(identifier, next), - code_size(9), - next(0), - byte_pos(0), - bit_pos(0), - bits_available(0), - code_change_delta(early_code_change), - eod(false), - last_code(256) + code_change_delta(early_code_change) { - memset(buf, 0, 3); + if (!next) { + throw std::logic_error("Attempt to create Pl_LZWDecoder with nullptr as next"); + } } void Pl_LZWDecoder::write(unsigned char const* bytes, size_t len) { for (size_t i = 0; i < len; ++i) { - this->buf[next++] = bytes[i]; - if (this->next == 3) { - this->next = 0; + buf[next_char_++] = bytes[i]; + if (next_char_ == 3) { + next_char_ = 0; } this->bits_available += 8; if (this->bits_available >= this->code_size) { @@ -38,7 +33,7 @@ Pl_LZWDecoder::write(unsigned char const* bytes, size_t len) void Pl_LZWDecoder::finish() { - getNext()->finish(); + next()->finish(); } void @@ -101,7 +96,7 @@ Pl_LZWDecoder::getFirstChar(unsigned int code) } void -Pl_LZWDecoder::addToTable(unsigned char next) +Pl_LZWDecoder::addToTable(unsigned char c) { unsigned int last_size = 0; unsigned char const* last_data = nullptr; @@ -128,7 +123,7 @@ Pl_LZWDecoder::addToTable(unsigned char next) Buffer entry(1 + last_size); unsigned char* new_data = entry.getBuffer(); memcpy(new_data, last_data, last_size); - new_data[last_size] = next; + new_data[last_size] = c; this->table.push_back(std::move(entry)); } @@ -151,11 +146,11 @@ Pl_LZWDecoder::handleCode(unsigned int code) if (this->last_code != 256) { // Add to the table from last time. New table entry would be what we read last plus the // first character of what we're reading now. - unsigned char next = '\0'; + unsigned char next_c = '\0'; unsigned int table_size = QIntC::to_uint(table.size()); if (code < 256) { - // just read < 256; last time's next was code - next = static_cast(code); + // just read < 256; last time's next_c was code + next_c = static_cast(code); } else if (code > 257) { size_t idx = code - 258; if (idx > table_size) { @@ -164,16 +159,16 @@ Pl_LZWDecoder::handleCode(unsigned int code) // The encoder would have just created this entry, so the first character of // this entry would have been the same as the first character of the last entry. QTC::TC("libtests", "Pl_LZWDecoder last was table size"); - next = getFirstChar(this->last_code); + next_c = getFirstChar(this->last_code); } else { - next = getFirstChar(code); + next_c = getFirstChar(code); } } unsigned int new_idx = 258 + table_size; if (new_idx == 4096) { throw std::runtime_error("LZWDecoder: table full"); } - addToTable(next); + addToTable(next_c); unsigned int change_idx = new_idx + code_change_delta; if ((change_idx == 511) || (change_idx == 1023) || (change_idx == 2047)) { ++this->code_size; @@ -182,14 +177,14 @@ Pl_LZWDecoder::handleCode(unsigned int code) if (code < 256) { auto ch = static_cast(code); - getNext()->write(&ch, 1); + next()->write(&ch, 1); } else { unsigned int idx = code - 258; if (idx >= table.size()) { throw std::runtime_error("Pl_LZWDecoder::handleCode: table overflow"); } Buffer& b = table.at(idx); - getNext()->write(b.getBuffer(), b.getSize()); + next()->write(b.getBuffer(), b.getSize()); } } diff --git a/libqpdf/Pl_MD5.cc b/libqpdf/Pl_MD5.cc index 8d45f17a..616d15b2 100644 --- a/libqpdf/Pl_MD5.cc +++ b/libqpdf/Pl_MD5.cc @@ -3,11 +3,11 @@ #include Pl_MD5::Pl_MD5(char const* identifier, Pipeline* next) : - Pipeline(identifier, next), - in_progress(false), - enabled(true), - persist_across_finish(false) + Pipeline(identifier, next) { + if (!next) { + throw std::logic_error("Attempt to create Pl_MD5 with nullptr as next"); + } } void @@ -31,13 +31,13 @@ Pl_MD5::write(unsigned char const* buf, size_t len) } } - this->getNext()->write(buf, len); + next()->write(buf, len); } void Pl_MD5::finish() { - this->getNext()->finish(); + next()->finish(); if (!this->persist_across_finish) { this->in_progress = false; } diff --git a/libqpdf/Pl_PNGFilter.cc b/libqpdf/Pl_PNGFilter.cc index 4d2bc71b..e3930e2a 100644 --- a/libqpdf/Pl_PNGFilter.cc +++ b/libqpdf/Pl_PNGFilter.cc @@ -26,13 +26,11 @@ Pl_PNGFilter::Pl_PNGFilter( unsigned int samples_per_pixel, unsigned int bits_per_sample) : Pipeline(identifier, next), - action(action), - cur_row(nullptr), - prev_row(nullptr), - buf1(nullptr), - buf2(nullptr), - pos(0) + action(action) { + if (!next) { + throw std::logic_error("Attempt to create Pl_PNGFilter with nullptr as next"); + } if (samples_per_pixel < 1) { throw std::runtime_error("PNGFilter created with invalid samples_per_pixel"); } @@ -130,7 +128,7 @@ Pl_PNGFilter::decodeRow() } } - getNext()->write(this->cur_row + 1, this->bytes_per_row); + next()->write(this->cur_row + 1, this->bytes_per_row); } void @@ -230,14 +228,14 @@ Pl_PNGFilter::encodeRow() { // For now, hard-code to using UP filter. unsigned char ch = 2; - getNext()->write(&ch, 1); + next()->write(&ch, 1); if (this->prev_row) { for (unsigned int i = 0; i < this->bytes_per_row; ++i) { ch = static_cast(this->cur_row[i] - this->prev_row[i]); - getNext()->write(&ch, 1); + next()->write(&ch, 1); } } else { - getNext()->write(this->cur_row, this->bytes_per_row); + next()->write(this->cur_row, this->bytes_per_row); } } @@ -253,5 +251,5 @@ Pl_PNGFilter::finish() this->pos = 0; memset(this->cur_row, 0, this->bytes_per_row + 1); - getNext()->finish(); + next()->finish(); } diff --git a/libqpdf/Pl_QPDFTokenizer.cc b/libqpdf/Pl_QPDFTokenizer.cc index 91973fc4..16a4bd09 100644 --- a/libqpdf/Pl_QPDFTokenizer.cc +++ b/libqpdf/Pl_QPDFTokenizer.cc @@ -5,7 +5,6 @@ #include Pl_QPDFTokenizer::Members::Members() : - filter(nullptr), buf("tokenizer buffer") { } @@ -56,8 +55,7 @@ Pl_QPDFTokenizer::finish() } m->filter->handleEOF(); QPDFObjectHandle::TokenFilter::PipelineAccessor::setPipeline(m->filter, nullptr); - Pipeline* next = this->getNext(true); - if (next) { - next->finish(); + if (next()) { + next()->finish(); } } diff --git a/libqpdf/Pl_RC4.cc b/libqpdf/Pl_RC4.cc index a244152b..4ea9d251 100644 --- a/libqpdf/Pl_RC4.cc +++ b/libqpdf/Pl_RC4.cc @@ -12,6 +12,9 @@ Pl_RC4::Pl_RC4( out_bufsize(out_bufsize), rc4(key_data, key_len) { + if (!next) { + throw std::logic_error("Attempt to create Pl_RC4 with nullptr as next"); + } this->outbuf = QUtil::make_shared_array(out_bufsize); } @@ -31,13 +34,13 @@ Pl_RC4::write(unsigned char const* data, size_t len) // lgtm[cpp/weak-cryptographic-algorithm] rc4.process(p, bytes, outbuf.get()); p += bytes; - getNext()->write(outbuf.get(), bytes); + next()->write(outbuf.get(), bytes); } } void Pl_RC4::finish() { - this->outbuf = nullptr; - this->getNext()->finish(); + outbuf = nullptr; + next()->finish(); } diff --git a/libqpdf/Pl_RunLength.cc b/libqpdf/Pl_RunLength.cc index 1031eb88..5969715c 100644 --- a/libqpdf/Pl_RunLength.cc +++ b/libqpdf/Pl_RunLength.cc @@ -4,9 +4,7 @@ #include Pl_RunLength::Members::Members(action_e action) : - action(action), - state(st_top), - length(0) + action(action) { } @@ -14,6 +12,9 @@ Pl_RunLength::Pl_RunLength(char const* identifier, Pipeline* next, action_e acti Pipeline(identifier, next), m(new Members(action)) { + if (!next) { + throw std::logic_error("Attempt to create Pl_RunLength with nullptr as next"); + } } Pl_RunLength::~Pl_RunLength() // NOLINT (modernize-use-equals-default) @@ -119,12 +120,12 @@ Pl_RunLength::flush_encode() throw std::logic_error("Pl_RunLength: invalid length in flush_encode for run"); } auto ch = static_cast(257 - m->length); - this->getNext()->write(&ch, 1); - this->getNext()->write(&m->buf[0], 1); + next()->write(&ch, 1); + next()->write(&m->buf[0], 1); } else if (m->length > 0) { auto ch = static_cast(m->length - 1); - this->getNext()->write(&ch, 1); - this->getNext()->write(m->buf, m->length); + next()->write(&ch, 1); + next()->write(m->buf, m->length); } m->state = st_top; m->length = 0; @@ -136,13 +137,12 @@ Pl_RunLength::finish() // When decoding, we might have read a length byte not followed by data, which means the stream // was terminated early, but we will just ignore this case since this is the only sensible thing // to do. - auto next = getNext(); if (m->action == a_encode) { flush_encode(); unsigned char ch = 128; - next->write(&ch, 1); + next()->write(&ch, 1); } else { - next->writeString(m->out); + next()->writeString(m->out); } - next->finish(); + next()->finish(); } diff --git a/libqpdf/Pl_SHA2.cc b/libqpdf/Pl_SHA2.cc index 04ef924c..090d7786 100644 --- a/libqpdf/Pl_SHA2.cc +++ b/libqpdf/Pl_SHA2.cc @@ -31,16 +31,16 @@ Pl_SHA2::write(unsigned char const* buf, size_t len) data += bytes; } - if (this->getNext(true)) { - this->getNext()->write(buf, len); + if (next()) { + next()->write(buf, len); } } void Pl_SHA2::finish() { - if (this->getNext(true)) { - this->getNext()->finish(); + if (next()) { + next()->finish(); } this->crypto->SHA2_finalize(); this->in_progress = false; diff --git a/libqpdf/Pl_String.cc b/libqpdf/Pl_String.cc index 1369c17d..c022d5cf 100644 --- a/libqpdf/Pl_String.cc +++ b/libqpdf/Pl_String.cc @@ -25,15 +25,15 @@ Pl_String::write(unsigned char const* buf, size_t len) return; } m->s.append(reinterpret_cast(buf), len); - if (getNext(true)) { - getNext()->write(buf, len); + if (next()) { + next()->write(buf, len); } } void Pl_String::finish() { - if (getNext(true)) { - getNext()->finish(); + if (next()) { + next()->finish(); } } diff --git a/libqpdf/Pl_TIFFPredictor.cc b/libqpdf/Pl_TIFFPredictor.cc index c2cc8561..ee467963 100644 --- a/libqpdf/Pl_TIFFPredictor.cc +++ b/libqpdf/Pl_TIFFPredictor.cc @@ -23,9 +23,11 @@ Pl_TIFFPredictor::Pl_TIFFPredictor( action(action), columns(columns), samples_per_pixel(samples_per_pixel), - bits_per_sample(bits_per_sample), - p_next(getNext()) + bits_per_sample(bits_per_sample) { + if (!next) { + throw std::logic_error("Attempt to create Pl_TIFFPredictor with nullptr as next"); + } if (samples_per_pixel < 1) { throw std::runtime_error("TIFFPredictor created with invalid samples_per_pixel"); } @@ -74,7 +76,7 @@ Pl_TIFFPredictor::processRow() QTC::TC("libtests", "Pl_TIFFPredictor processRow", (action == a_decode ? 0 : 1)); previous.assign(samples_per_pixel, 0); if (bits_per_sample != 8) { - BitWriter bw(p_next); + BitWriter bw(next()); BitStream in(cur_row.data(), cur_row.size()); for (unsigned int col = 0; col < this->columns; ++col) { for (auto& prev: previous) { @@ -93,13 +95,14 @@ Pl_TIFFPredictor::processRow() bw.flush(); } else { out.clear(); - auto next = cur_row.begin(); + auto next_it = cur_row.begin(); auto cr_end = cur_row.end(); auto pr_end = previous.end(); - while (next != cr_end) { - for (auto prev = previous.begin(); prev != pr_end && next != cr_end; ++prev, ++next) { - long long sample = *next; + while (next_it != cr_end) { + for (auto prev = previous.begin(); prev != pr_end && next_it != cr_end; + ++prev, ++next_it) { + long long sample = *next_it; long long new_sample = sample; if (action == a_encode) { new_sample -= *prev; @@ -111,7 +114,7 @@ Pl_TIFFPredictor::processRow() out.push_back(static_cast(255U & new_sample)); } } - p_next->write(out.data(), out.size()); + next()->write(out.data(), out.size()); } } @@ -124,5 +127,5 @@ Pl_TIFFPredictor::finish() processRow(); } cur_row.clear(); - p_next->finish(); + next()->finish(); } diff --git a/libqpdf/QPDFLogger.cc b/libqpdf/QPDFLogger.cc index a704ea75..07c08cc0 100644 --- a/libqpdf/QPDFLogger.cc +++ b/libqpdf/QPDFLogger.cc @@ -14,19 +14,22 @@ namespace Pl_Track(char const* identifier, Pipeline* next) : Pipeline(identifier, next) { + if (!next) { + throw std::logic_error("Attempt to create Pl_Track with nullptr as next"); + } } void - write(unsigned char const* data, size_t len) override + write(unsigned char const* data, size_t len) final { - this->used = true; - getNext()->write(data, len); + used = true; + next()->write(data, len); } void - finish() override + finish() final { - getNext()->finish(); + next()->finish(); } bool diff --git a/libqpdf/QPDFObjectHandle.cc b/libqpdf/QPDFObjectHandle.cc index dbe109a2..aec3e586 100644 --- a/libqpdf/QPDFObjectHandle.cc +++ b/libqpdf/QPDFObjectHandle.cc @@ -181,13 +181,13 @@ QPDFObjectHandle::ParserCallbacks::terminateParsing() namespace { - class LastChar: public Pipeline + class LastChar final: public Pipeline { public: - LastChar(Pipeline* next); - ~LastChar() override = default; - void write(unsigned char const* data, size_t len) override; - void finish() override; + LastChar(Pipeline& next); + ~LastChar() final = default; + void write(unsigned char const* data, size_t len) final; + void finish() final; unsigned char getLastChar(); private: @@ -195,8 +195,8 @@ namespace }; } // namespace -LastChar::LastChar(Pipeline* next) : - Pipeline("lastchar", next) +LastChar::LastChar(Pipeline& next) : + Pipeline("lastchar", &next) { } @@ -206,13 +206,13 @@ LastChar::write(unsigned char const* data, size_t len) if (len > 0) { this->last_char = data[len - 1]; } - getNext()->write(data, len); + next()->write(data, len); } void LastChar::finish() { - getNext()->finish(); + next()->finish(); } unsigned char @@ -2073,7 +2073,7 @@ QPDFObjectHandle::pipeContentStreams( if (need_newline) { buf.writeCStr("\n"); } - LastChar lc(&buf); + LastChar lc(buf); if (!stream.pipeStreamData(&lc, 0, qpdf_dl_specialized)) { QTC::TC("qpdf", "QPDFObjectHandle errors in parsecontent"); throw QPDFExc( diff --git a/libqpdf/qpdf/Pl_AES_PDF.hh b/libqpdf/qpdf/Pl_AES_PDF.hh index 32f4c351..f85cd979 100644 --- a/libqpdf/qpdf/Pl_AES_PDF.hh +++ b/libqpdf/qpdf/Pl_AES_PDF.hh @@ -7,8 +7,7 @@ // This pipeline implements AES-128 and AES-256 with CBC and block padding as specified in the PDF // specification. - -class Pl_AES_PDF: public Pipeline +class Pl_AES_PDF final: public Pipeline { public: // key should be a pointer to key_bytes bytes of data @@ -18,10 +17,10 @@ class Pl_AES_PDF: public Pipeline bool encrypt, unsigned char const* key, size_t key_bytes); - ~Pl_AES_PDF() override = default; + ~Pl_AES_PDF() final = default; - void write(unsigned char const* data, size_t len) override; - void finish() override; + void write(unsigned char const* data, size_t len) final; + void finish() final; // Use zero initialization vector; needed for AESV3 void useZeroIV(); @@ -45,18 +44,18 @@ class Pl_AES_PDF: public Pipeline std::shared_ptr crypto; bool encrypt; - bool cbc_mode; - bool first; - size_t offset; // offset into memory buffer + bool cbc_mode{true}; + bool first{true}; + size_t offset{0}; // offset into memory buffer std::unique_ptr key; - size_t key_bytes; + size_t key_bytes{0}; unsigned char inbuf[buf_size]; unsigned char outbuf[buf_size]; unsigned char cbc_block[buf_size]; unsigned char specified_iv[buf_size]; - bool use_zero_iv; - bool use_specified_iv; - bool disable_padding; + bool use_zero_iv{false}; + bool use_specified_iv{false}; + bool disable_padding{false}; }; #endif // PL_AES_PDF_HH diff --git a/libqpdf/qpdf/Pl_ASCII85Decoder.hh b/libqpdf/qpdf/Pl_ASCII85Decoder.hh index dd5efd06..05505c79 100644 --- a/libqpdf/qpdf/Pl_ASCII85Decoder.hh +++ b/libqpdf/qpdf/Pl_ASCII85Decoder.hh @@ -3,20 +3,20 @@ #include -class Pl_ASCII85Decoder: public Pipeline +class Pl_ASCII85Decoder final: public Pipeline { public: Pl_ASCII85Decoder(char const* identifier, Pipeline* next); - ~Pl_ASCII85Decoder() override = default; - void write(unsigned char const* buf, size_t len) override; - void finish() override; + ~Pl_ASCII85Decoder() final = default; + void write(unsigned char const* buf, size_t len) final; + void finish() final; private: void flush(); - unsigned char inbuf[5]; - size_t pos; - size_t eod; + unsigned char inbuf[5]{117, 117, 117, 117, 117}; + size_t pos{0}; + size_t eod{0}; }; #endif // PL_ASCII85DECODER_HH diff --git a/libqpdf/qpdf/Pl_ASCIIHexDecoder.hh b/libqpdf/qpdf/Pl_ASCIIHexDecoder.hh index 5edf74f0..7004ada0 100644 --- a/libqpdf/qpdf/Pl_ASCIIHexDecoder.hh +++ b/libqpdf/qpdf/Pl_ASCIIHexDecoder.hh @@ -3,20 +3,20 @@ #include -class Pl_ASCIIHexDecoder: public Pipeline +class Pl_ASCIIHexDecoder final: public Pipeline { public: Pl_ASCIIHexDecoder(char const* identifier, Pipeline* next); - ~Pl_ASCIIHexDecoder() override = default; - void write(unsigned char const* buf, size_t len) override; - void finish() override; + ~Pl_ASCIIHexDecoder() final = default; + void write(unsigned char const* buf, size_t len) final; + void finish() final; private: void flush(); - char inbuf[3]; - size_t pos; - bool eod; + char inbuf[3]{'0', '0', '\0'}; + size_t pos{0}; + bool eod{false}; }; #endif // PL_ASCIIHEXDECODER_HH diff --git a/libqpdf/qpdf/Pl_Base64.hh b/libqpdf/qpdf/Pl_Base64.hh index a084a17f..1abee882 100644 --- a/libqpdf/qpdf/Pl_Base64.hh +++ b/libqpdf/qpdf/Pl_Base64.hh @@ -3,14 +3,14 @@ #include -class Pl_Base64: public Pipeline +class Pl_Base64 final: public Pipeline { public: enum action_e { a_encode, a_decode }; Pl_Base64(char const* identifier, Pipeline* next, action_e); - ~Pl_Base64() override = default; - void write(unsigned char const* buf, size_t len) override; - void finish() override; + ~Pl_Base64() final = default; + void write(unsigned char const* buf, size_t len) final; + void finish() final; private: void decode(unsigned char const* buf, size_t len); @@ -21,10 +21,10 @@ class Pl_Base64: public Pipeline void reset(); action_e action; - unsigned char buf[4]; - size_t pos; - bool end_of_data; - bool finished; + unsigned char buf[4]{0, 0, 0, 0}; + size_t pos{0}; + bool end_of_data{false}; + bool finished{false}; }; #endif // PL_BASE64_HH diff --git a/libqpdf/qpdf/Pl_LZWDecoder.hh b/libqpdf/qpdf/Pl_LZWDecoder.hh index 792fa8ef..d4fe4a9b 100644 --- a/libqpdf/qpdf/Pl_LZWDecoder.hh +++ b/libqpdf/qpdf/Pl_LZWDecoder.hh @@ -6,13 +6,13 @@ #include #include -class Pl_LZWDecoder: public Pipeline +class Pl_LZWDecoder final: public Pipeline { public: Pl_LZWDecoder(char const* identifier, Pipeline* next, bool early_code_change); - ~Pl_LZWDecoder() override = default; - void write(unsigned char const* buf, size_t len) override; - void finish() override; + ~Pl_LZWDecoder() final = default; + void write(unsigned char const* buf, size_t len) final; + void finish() final; private: void sendNextCode(); @@ -21,18 +21,18 @@ class Pl_LZWDecoder: public Pipeline void addToTable(unsigned char next); // members used for converting bits to codes - unsigned char buf[3]; - unsigned int code_size; - unsigned int next; - unsigned int byte_pos; - unsigned int bit_pos; // left to right: 01234567 - unsigned int bits_available; + unsigned char buf[3]{0, 0, 0}; + unsigned int code_size{9}; + unsigned int next_char_{0}; + unsigned int byte_pos{0}; + unsigned int bit_pos{0}; // left to right: 01234567 + unsigned int bits_available{0}; // members used for handle LZW decompression - bool code_change_delta; - bool eod; + bool code_change_delta{false}; + bool eod{false}; std::vector table; - unsigned int last_code; + unsigned int last_code{256}; }; #endif // PL_LZWDECODER_HH diff --git a/libqpdf/qpdf/Pl_MD5.hh b/libqpdf/qpdf/Pl_MD5.hh index fb9a2184..31ae263c 100644 --- a/libqpdf/qpdf/Pl_MD5.hh +++ b/libqpdf/qpdf/Pl_MD5.hh @@ -1,22 +1,21 @@ #ifndef PL_MD5_HH #define PL_MD5_HH +#include +#include + // This pipeline sends its output to its successor unmodified. After calling finish, the MD5 // checksum of the data that passed through the pipeline is available. // This pipeline is reusable; i.e., it is safe to call write() after calling finish(). The first // call to write() after a call to finish() initializes a new MD5 object. - -#include -#include - -class Pl_MD5: public Pipeline +class Pl_MD5 final: public Pipeline { public: Pl_MD5(char const* identifier, Pipeline* next); - ~Pl_MD5() override = default; - void write(unsigned char const*, size_t) override; - void finish() override; + ~Pl_MD5() final = default; + void write(unsigned char const*, size_t) final; + void finish() final; std::string getHexDigest(); // Enable/disable. Disabling the pipeline causes it to become a pass-through. This makes it // possible to stick an MD5 pipeline in a pipeline when it may or may not be required. Disabling @@ -27,10 +26,10 @@ class Pl_MD5: public Pipeline void persistAcrossFinish(bool); private: - bool in_progress; + bool in_progress{false}; MD5 md5; - bool enabled; - bool persist_across_finish; + bool enabled{true}; + bool persist_across_finish{false}; }; #endif // PL_MD5_HH diff --git a/libqpdf/qpdf/Pl_PNGFilter.hh b/libqpdf/qpdf/Pl_PNGFilter.hh index 9f1950e9..617f51c3 100644 --- a/libqpdf/qpdf/Pl_PNGFilter.hh +++ b/libqpdf/qpdf/Pl_PNGFilter.hh @@ -1,15 +1,14 @@ #ifndef PL_PNGFILTER_HH #define PL_PNGFILTER_HH -// This pipeline applies or reverses the application of a PNG filter as described in the PNG -// specification. - -// NOTE: In its current implementation, this filter always encodes using the "up" filter, but it -// decodes all the filters. - #include -class Pl_PNGFilter: public Pipeline +// This pipeline applies or reverses the application of a PNG filter as described in the PNG +// specification. +// +// NOTE: In its current implementation, this filter always encodes using the "up" filter, but it +// decodes all the filters. +class Pl_PNGFilter final: public Pipeline { public: // Encoding is only partially supported @@ -22,14 +21,14 @@ class Pl_PNGFilter: public Pipeline unsigned int columns, unsigned int samples_per_pixel = 1, unsigned int bits_per_sample = 8); - ~Pl_PNGFilter() override = default; + ~Pl_PNGFilter() final = default; // Limit the memory used. // NB This is a static option affecting all Pl_PNGFilter instances. static void setMemoryLimit(unsigned long long limit); - void write(unsigned char const* data, size_t len) override; - void finish() override; + void write(unsigned char const* data, size_t len) final; + void finish() final; private: void decodeSub(); @@ -44,12 +43,12 @@ class Pl_PNGFilter: public Pipeline action_e action; unsigned int bytes_per_row; unsigned int bytes_per_pixel; - unsigned char* cur_row; // points to buf1 or buf2 - unsigned char* prev_row; // points to buf1 or buf2 + unsigned char* cur_row{nullptr}; // points to buf1 or buf2 + unsigned char* prev_row{nullptr}; // points to buf1 or buf2 std::shared_ptr buf1; std::shared_ptr buf2; - size_t pos; - size_t incoming; + size_t pos{0}; + size_t incoming{0}; }; #endif // PL_PNGFILTER_HH diff --git a/libqpdf/qpdf/Pl_RC4.hh b/libqpdf/qpdf/Pl_RC4.hh index 49c943b9..55172b33 100644 --- a/libqpdf/qpdf/Pl_RC4.hh +++ b/libqpdf/qpdf/Pl_RC4.hh @@ -5,7 +5,7 @@ #include -class Pl_RC4: public Pipeline +class Pl_RC4 final: public Pipeline { public: static size_t const def_bufsize = 65536; @@ -17,10 +17,10 @@ class Pl_RC4: public Pipeline unsigned char const* key_data, int key_len = -1, size_t out_bufsize = def_bufsize); - ~Pl_RC4() override = default; + ~Pl_RC4() final = default; - void write(unsigned char const* data, size_t len) override; - void finish() override; + void write(unsigned char const* data, size_t len) final; + void finish() final; private: std::shared_ptr outbuf; diff --git a/libqpdf/qpdf/Pl_SHA2.hh b/libqpdf/qpdf/Pl_SHA2.hh index 9b3275f0..ee4c5c1c 100644 --- a/libqpdf/qpdf/Pl_SHA2.hh +++ b/libqpdf/qpdf/Pl_SHA2.hh @@ -1,26 +1,25 @@ #ifndef PL_SHA2_HH #define PL_SHA2_HH -// Bits must be a supported number of bits, currently only 256, 384, or 512. Passing 0 as bits -// leaves the pipeline uncommitted, in which case resetBits must be called before the pipeline is -// used. If a next is provided, this pipeline sends its output to its successor unmodified. After -// calling finish, the SHA2 checksum of the data that passed through the pipeline is available. - -// This pipeline is reusable; i.e., it is safe to call write() after calling finish(). The first -// call to write() after a call to finish() initializes a new SHA2 object. resetBits may also be -// called between finish and the next call to write. - #include #include #include -class Pl_SHA2: public Pipeline +// Bits must be a supported number of bits, currently only 256, 384, or 512. Passing 0 as bits +// leaves the pipeline uncommitted, in which case resetBits must be called before the pipeline is +// used. If a next is provided, this pipeline sends its output to its successor unmodified. After +// calling finish, the SHA2 checksum of the data that passed through the pipeline is available. +// +// This pipeline is reusable; i.e., it is safe to call write() after calling finish(). The first +// call to write() after a call to finish() initializes a new SHA2 object. resetBits may also be +// called between finish and the next call to write. +class Pl_SHA2 final: public Pipeline { public: Pl_SHA2(int bits = 0, Pipeline* next = nullptr); - ~Pl_SHA2() override = default; - void write(unsigned char const*, size_t) override; - void finish() override; + ~Pl_SHA2() final = default; + void write(unsigned char const*, size_t) final; + void finish() final; void resetBits(int bits); std::string getHexDigest(); std::string getRawDigest(); diff --git a/libqpdf/qpdf/Pl_TIFFPredictor.hh b/libqpdf/qpdf/Pl_TIFFPredictor.hh index 4e32936f..0abc1d82 100644 --- a/libqpdf/qpdf/Pl_TIFFPredictor.hh +++ b/libqpdf/qpdf/Pl_TIFFPredictor.hh @@ -40,7 +40,6 @@ class Pl_TIFFPredictor: public Pipeline std::vector cur_row; std::vector previous; std::vector out; - Pipeline* p_next; }; #endif // PL_TIFFPREDICTOR_HH