Commit 3a055d5b6af5e3eab1eac33c77ccb1c8a386867f

Authored by m-holger
Committed by GitHub
2 parents a5ec9dc0 9faffb74

Merge pull request #1495 from m-holger/writer

Simplify QPDFWriter pipeline management
libqpdf/Pl_AES_PDF.cc
@@ -9,25 +9,18 @@ @@ -9,25 +9,18 @@
9 9
10 bool Pl_AES_PDF::use_static_iv = false; 10 bool Pl_AES_PDF::use_static_iv = false;
11 11
12 -Pl_AES_PDF::Pl_AES_PDF(  
13 - char const* identifier,  
14 - Pipeline* next,  
15 - bool encrypt,  
16 - unsigned char const* key,  
17 - size_t key_bytes) : 12 +Pl_AES_PDF::Pl_AES_PDF(char const* identifier, Pipeline* next, bool encrypt, std::string key) :
18 Pipeline(identifier, next), 13 Pipeline(identifier, next),
  14 + key(key),
19 crypto(QPDFCryptoProvider::getImpl()), 15 crypto(QPDFCryptoProvider::getImpl()),
20 - encrypt(encrypt),  
21 - key_bytes(key_bytes) 16 + encrypt(encrypt)
22 { 17 {
23 if (!next) { 18 if (!next) {
24 throw std::logic_error("Attempt to create Pl_AES_PDF with nullptr as next"); 19 throw std::logic_error("Attempt to create Pl_AES_PDF with nullptr as next");
25 } 20 }
26 - if (!(key_bytes == 32 || key_bytes == 16)) { 21 + if (!(key.size() == 32 || key.size() == 16)) {
27 throw std::runtime_error("unsupported key length"); 22 throw std::runtime_error("unsupported key length");
28 } 23 }
29 - this->key = std::make_unique<unsigned char[]>(key_bytes);  
30 - std::memcpy(this->key.get(), key, key_bytes);  
31 std::memset(this->inbuf, 0, this->buf_size); 24 std::memset(this->inbuf, 0, this->buf_size);
32 std::memset(this->outbuf, 0, this->buf_size); 25 std::memset(this->outbuf, 0, this->buf_size);
33 std::memset(this->cbc_block, 0, this->buf_size); 26 std::memset(this->cbc_block, 0, this->buf_size);
@@ -170,7 +163,12 @@ Pl_AES_PDF::flush(bool strip_padding) @@ -170,7 +163,12 @@ Pl_AES_PDF::flush(bool strip_padding)
170 return_after_init = true; 163 return_after_init = true;
171 } 164 }
172 } 165 }
173 - crypto->rijndael_init(encrypt, key.get(), key_bytes, cbc_mode, cbc_block); 166 + crypto->rijndael_init(
  167 + encrypt,
  168 + reinterpret_cast<const unsigned char*>(key.data()),
  169 + key.size(),
  170 + cbc_mode,
  171 + cbc_block);
174 if (return_after_init) { 172 if (return_after_init) {
175 return; 173 return;
176 } 174 }
libqpdf/Pl_RC4.cc
@@ -2,15 +2,10 @@ @@ -2,15 +2,10 @@
2 2
3 #include <qpdf/QUtil.hh> 3 #include <qpdf/QUtil.hh>
4 4
5 -Pl_RC4::Pl_RC4(  
6 - char const* identifier,  
7 - Pipeline* next,  
8 - unsigned char const* key_data,  
9 - int key_len,  
10 - size_t out_bufsize) : 5 +Pl_RC4::Pl_RC4(char const* identifier, Pipeline* next, std::string key, size_t out_bufsize) :
11 Pipeline(identifier, next), 6 Pipeline(identifier, next),
12 out_bufsize(out_bufsize), 7 out_bufsize(out_bufsize),
13 - rc4(key_data, key_len) 8 + rc4(reinterpret_cast<unsigned char const*>(key.data()), static_cast<int>(key.size()))
14 { 9 {
15 if (!next) { 10 if (!next) {
16 throw std::logic_error("Attempt to create Pl_RC4 with nullptr as next"); 11 throw std::logic_error("Attempt to create Pl_RC4 with nullptr as next");
libqpdf/QPDFWriter.cc
@@ -141,20 +141,20 @@ namespace @@ -141,20 +141,20 @@ namespace
141 } 141 }
142 142
143 void 143 void
144 - activate(Popper& pp, std::unique_ptr<pl::Link> link) 144 + activate(Popper& pp, std::unique_ptr<Pipeline> next)
145 { 145 {
146 count_buffer.clear(); 146 count_buffer.clear();
147 - activate(pp, false, &count_buffer, std::move(link)); 147 + activate(pp, false, &count_buffer, std::move(next));
148 } 148 }
149 149
150 Popper 150 Popper
151 activate( 151 activate(
152 bool discard = false, 152 bool discard = false,
153 std::string* str = nullptr, 153 std::string* str = nullptr,
154 - std::unique_ptr<pl::Link> link = nullptr) 154 + std::unique_ptr<Pipeline> next = nullptr)
155 { 155 {
156 Popper pp{*this}; 156 Popper pp{*this};
157 - activate(pp, discard, str, std::move(link)); 157 + activate(pp, discard, str, std::move(next));
158 return pp; 158 return pp;
159 } 159 }
160 160
@@ -163,11 +163,11 @@ namespace @@ -163,11 +163,11 @@ namespace
163 Popper& pp, 163 Popper& pp,
164 bool discard = false, 164 bool discard = false,
165 std::string* str = nullptr, 165 std::string* str = nullptr,
166 - std::unique_ptr<pl::Link> link = nullptr) 166 + std::unique_ptr<Pipeline> next = nullptr)
167 { 167 {
168 std::unique_ptr<pl::Count> c; 168 std::unique_ptr<pl::Count> c;
169 - if (link) {  
170 - c = std::make_unique<pl::Count>(++last_id, count_buffer, std::move(link)); 169 + if (next) {
  170 + c = std::make_unique<pl::Count>(++last_id, count_buffer, std::move(next));
171 } else if (discard) { 171 } else if (discard) {
172 c = std::make_unique<pl::Count>(++last_id, nullptr); 172 c = std::make_unique<pl::Count>(++last_id, nullptr);
173 } else if (!str) { 173 } else if (!str) {
@@ -1109,18 +1109,9 @@ QPDFWriter::write_encrypted(std::string_view str) @@ -1109,18 +1109,9 @@ QPDFWriter::write_encrypted(std::string_view str)
1109 if (!(m->encryption && !m->cur_data_key.empty())) { 1109 if (!(m->encryption && !m->cur_data_key.empty())) {
1110 write(str); 1110 write(str);
1111 } else if (m->encrypt_use_aes) { 1111 } else if (m->encrypt_use_aes) {
1112 - write(  
1113 - pl::pipe<Pl_AES_PDF>(  
1114 - str,  
1115 - true,  
1116 - QUtil::unsigned_char_pointer(m->cur_data_key),  
1117 - m->cur_data_key.length())); 1112 + write(pl::pipe<Pl_AES_PDF>(str, true, m->cur_data_key));
1118 } else { 1113 } else {
1119 - write(  
1120 - pl::pipe<Pl_RC4>(  
1121 - str,  
1122 - QUtil::unsigned_char_pointer(m->cur_data_key),  
1123 - QIntC::to_int(m->cur_data_key.length()))); 1114 + write(pl::pipe<Pl_RC4>(str, m->cur_data_key));
1124 } 1115 }
1125 1116
1126 return *this; 1117 return *this;
@@ -1654,12 +1645,7 @@ QPDFWriter::unparseObject( @@ -1654,12 +1645,7 @@ QPDFWriter::unparseObject(
1654 val = object.getStringValue(); 1645 val = object.getStringValue();
1655 if (m->encrypt_use_aes) { 1646 if (m->encrypt_use_aes) {
1656 Pl_Buffer bufpl("encrypted string"); 1647 Pl_Buffer bufpl("encrypted string");
1657 - Pl_AES_PDF pl(  
1658 - "aes encrypt string",  
1659 - &bufpl,  
1660 - true,  
1661 - QUtil::unsigned_char_pointer(m->cur_data_key),  
1662 - m->cur_data_key.length()); 1648 + Pl_AES_PDF pl("aes encrypt string", &bufpl, true, m->cur_data_key);
1663 pl.writeString(val); 1649 pl.writeString(val);
1664 pl.finish(); 1650 pl.finish();
1665 val = QPDF_String(bufpl.getString()).unparse(true); 1651 val = QPDF_String(bufpl.getString()).unparse(true);
@@ -1768,7 +1754,6 @@ QPDFWriter::writeObjectStream(QPDFObjectHandle object) @@ -1768,7 +1754,6 @@ QPDFWriter::writeObjectStream(QPDFObjectHandle object)
1768 } 1754 }
1769 } 1755 }
1770 { 1756 {
1771 - auto pp_ostream = m->pipeline_stack.popper();  
1772 // Adjust offsets to skip over comment before first object 1757 // Adjust offsets to skip over comment before first object
1773 first = offsets.at(0); 1758 first = offsets.at(0);
1774 for (auto& iter: offsets) { 1759 for (auto& iter: offsets) {
@@ -1783,18 +1768,15 @@ QPDFWriter::writeObjectStream(QPDFObjectHandle object) @@ -1783,18 +1768,15 @@ QPDFWriter::writeObjectStream(QPDFObjectHandle object)
1783 } 1768 }
1784 1769
1785 // Set up a stream to write the stream data into a buffer. 1770 // Set up a stream to write the stream data into a buffer.
1786 - if (compressed) {  
1787 - m->pipeline_stack.activate(  
1788 - pp_ostream,  
1789 - pl::create<Pl_Flate>(  
1790 - pl::create<pl::String>(stream_buffer_pass2), Pl_Flate::a_deflate));  
1791 - } else {  
1792 - m->pipeline_stack.activate(pp_ostream, stream_buffer_pass2);  
1793 - } 1771 + auto pp_ostream = m->pipeline_stack.activate(stream_buffer_pass2);
  1772 +
1794 writeObjectStreamOffsets(offsets, first_obj); 1773 writeObjectStreamOffsets(offsets, first_obj);
1795 write(stream_buffer_pass1); 1774 write(stream_buffer_pass1);
1796 stream_buffer_pass1.clear(); 1775 stream_buffer_pass1.clear();
1797 stream_buffer_pass1.shrink_to_fit(); 1776 stream_buffer_pass1.shrink_to_fit();
  1777 + if (compressed) {
  1778 + stream_buffer_pass2 = pl::pipe<Pl_Flate>(stream_buffer_pass2, Pl_Flate::a_deflate);
  1779 + }
1798 } 1780 }
1799 1781
1800 // Write the object 1782 // Write the object
@@ -2528,20 +2510,7 @@ QPDFWriter::writeXRefStream( @@ -2528,20 +2510,7 @@ QPDFWriter::writeXRefStream(
2528 std::string xref_data; 2510 std::string xref_data;
2529 const bool compressed = m->compress_streams && !m->qdf_mode; 2511 const bool compressed = m->compress_streams && !m->qdf_mode;
2530 { 2512 {
2531 - auto pp_xref = m->pipeline_stack.popper();  
2532 - if (compressed) {  
2533 - m->pipeline_stack.clear_buffer();  
2534 - auto link = pl::create<pl::String>(xref_data);  
2535 - if (!skip_compression) {  
2536 - // Write the stream dictionary for compression but don't actually compress. This  
2537 - // helps us with computation of padding for pass 1 of linearization.  
2538 - link = pl::create<Pl_Flate>(std::move(link), Pl_Flate::a_deflate);  
2539 - }  
2540 - m->pipeline_stack.activate(  
2541 - pp_xref, pl::create<Pl_PNGFilter>(std::move(link), Pl_PNGFilter::a_encode, esize));  
2542 - } else {  
2543 - m->pipeline_stack.activate(pp_xref, xref_data);  
2544 - } 2513 + auto pp_xref = m->pipeline_stack.activate(xref_data);
2545 2514
2546 for (int i = first; i <= last; ++i) { 2515 for (int i = first; i <= last; ++i) {
2547 QPDFXRefEntry& e = m->new_obj[i].xref; 2516 QPDFXRefEntry& e = m->new_obj[i].xref;
@@ -2577,6 +2546,15 @@ QPDFWriter::writeXRefStream( @@ -2577,6 +2546,15 @@ QPDFWriter::writeXRefStream(
2577 } 2546 }
2578 } 2547 }
2579 2548
  2549 + if (compressed) {
  2550 + xref_data = pl::pipe<Pl_PNGFilter>(xref_data, Pl_PNGFilter::a_encode, esize);
  2551 + if (!skip_compression) {
  2552 + // Write the stream dictionary for compression but don't actually compress. This
  2553 + // helps us with computation of padding for pass 1 of linearization.
  2554 + xref_data = pl::pipe<Pl_Flate>(xref_data, Pl_Flate::a_deflate);
  2555 + }
  2556 + }
  2557 +
2580 openObject(xref_id); 2558 openObject(xref_id);
2581 write("<<").write_qdf("\n ").write(" /Type /XRef").write_qdf("\n "); 2559 write("<<").write_qdf("\n ").write(" /Type /XRef").write_qdf("\n ");
2582 write(" /Length ").write(xref_data.size()); 2560 write(" /Length ").write(xref_data.size());
@@ -2743,9 +2721,7 @@ QPDFWriter::writeLinearized() @@ -2743,9 +2721,7 @@ QPDFWriter::writeLinearized()
2743 lin_pass1_file = QUtil::safe_fopen(m->lin_pass1_filename.c_str(), "wb"); 2721 lin_pass1_file = QUtil::safe_fopen(m->lin_pass1_filename.c_str(), "wb");
2744 m->pipeline_stack.activate( 2722 m->pipeline_stack.activate(
2745 pp_pass1, 2723 pp_pass1,
2746 - std::make_unique<pl::Link>(  
2747 - nullptr,  
2748 - std::make_unique<Pl_StdioFile>("linearization pass1", lin_pass1_file))); 2724 + std::make_unique<Pl_StdioFile>("linearization pass1", lin_pass1_file));
2749 } else { 2725 } else {
2750 m->pipeline_stack.activate(pp_pass1, true); 2726 m->pipeline_stack.activate(pp_pass1, true);
2751 } 2727 }
libqpdf/QPDF_encryption.cc
@@ -230,8 +230,7 @@ process_with_aes( @@ -230,8 +230,7 @@ process_with_aes(
230 size_t iv_length = 0) 230 size_t iv_length = 0)
231 { 231 {
232 Pl_Buffer buffer("buffer"); 232 Pl_Buffer buffer("buffer");
233 - Pl_AES_PDF aes(  
234 - "aes", &buffer, encrypt, QUtil::unsigned_char_pointer(key), QIntC::to_uint(key.length())); 233 + Pl_AES_PDF aes("aes", &buffer, encrypt, key);
235 if (iv) { 234 if (iv) {
236 aes.setIV(iv, iv_length); 235 aes.setIV(iv, iv_length);
237 } else { 236 } else {
@@ -902,12 +901,7 @@ QPDF::decryptString(std::string&amp; str, QPDFObjGen og) @@ -902,12 +901,7 @@ QPDF::decryptString(std::string&amp; str, QPDFObjGen og)
902 if (use_aes) { 901 if (use_aes) {
903 QTC::TC("qpdf", "QPDF_encryption aes decode string"); 902 QTC::TC("qpdf", "QPDF_encryption aes decode string");
904 Pl_Buffer bufpl("decrypted string"); 903 Pl_Buffer bufpl("decrypted string");
905 - Pl_AES_PDF pl(  
906 - "aes decrypt string",  
907 - &bufpl,  
908 - false,  
909 - QUtil::unsigned_char_pointer(key),  
910 - key.length()); 904 + Pl_AES_PDF pl("aes decrypt string", &bufpl, false, key);
911 pl.writeString(str); 905 pl.writeString(str);
912 pl.finish(); 906 pl.finish();
913 str = bufpl.getString(); 907 str = bufpl.getString();
@@ -1028,19 +1022,11 @@ QPDF::decryptStream( @@ -1028,19 +1022,11 @@ QPDF::decryptStream(
1028 std::string key = getKeyForObject(encp, og, use_aes); 1022 std::string key = getKeyForObject(encp, og, use_aes);
1029 if (use_aes) { 1023 if (use_aes) {
1030 QTC::TC("qpdf", "QPDF_encryption aes decode stream"); 1024 QTC::TC("qpdf", "QPDF_encryption aes decode stream");
1031 - decrypt_pipeline = std::make_unique<Pl_AES_PDF>(  
1032 - "AES stream decryption",  
1033 - pipeline,  
1034 - false,  
1035 - QUtil::unsigned_char_pointer(key),  
1036 - key.length()); 1025 + decrypt_pipeline =
  1026 + std::make_unique<Pl_AES_PDF>("AES stream decryption", pipeline, false, key);
1037 } else { 1027 } else {
1038 QTC::TC("qpdf", "QPDF_encryption rc4 decode stream"); 1028 QTC::TC("qpdf", "QPDF_encryption rc4 decode stream");
1039 - decrypt_pipeline = std::make_unique<Pl_RC4>(  
1040 - "RC4 stream decryption",  
1041 - pipeline,  
1042 - QUtil::unsigned_char_pointer(key),  
1043 - toI(key.length())); 1029 + decrypt_pipeline = std::make_unique<Pl_RC4>("RC4 stream decryption", pipeline, key);
1044 } 1030 }
1045 pipeline = decrypt_pipeline.get(); 1031 pipeline = decrypt_pipeline.get();
1046 } 1032 }
libqpdf/QPDF_linearization.cc
@@ -1753,21 +1753,18 @@ QPDF::generateHintStream( @@ -1753,21 +1753,18 @@ QPDF::generateHintStream(
1753 1753
1754 // Write the hint stream itself into a compressed memory buffer. Write through a counter so we 1754 // Write the hint stream itself into a compressed memory buffer. Write through a counter so we
1755 // can get offsets. 1755 // can get offsets.
1756 - std::string b;  
1757 - auto c = compressed  
1758 - ? std::make_unique<pl::Count>(  
1759 - 0, b, pl::create<Pl_Flate>(pl::create<pl::String>(hint_buffer), Pl_Flate::a_deflate))  
1760 - : std::make_unique<pl::Count>(0, hint_buffer);  
1761 -  
1762 - BitWriter w(c.get()); 1756 + pl::Count c(0, hint_buffer);
  1757 + BitWriter w(&c);
1763 1758
1764 writeHPageOffset(w); 1759 writeHPageOffset(w);
1765 - S = toI(c->getCount()); 1760 + S = toI(c.getCount());
1766 writeHSharedObject(w); 1761 writeHSharedObject(w);
1767 O = 0; 1762 O = 0;
1768 if (m->outline_hints.nobjects > 0) { 1763 if (m->outline_hints.nobjects > 0) {
1769 - O = toI(c->getCount()); 1764 + O = toI(c.getCount());
1770 writeHGeneric(w, m->outline_hints); 1765 writeHGeneric(w, m->outline_hints);
1771 } 1766 }
1772 - c->finish(); 1767 + if (compressed) {
  1768 + hint_buffer = pl::pipe<Pl_Flate>(hint_buffer, Pl_Flate::a_deflate);
  1769 + }
1773 } 1770 }
libqpdf/qpdf/Pipeline_private.hh
@@ -8,35 +8,6 @@ @@ -8,35 +8,6 @@
8 8
9 namespace qpdf::pl 9 namespace qpdf::pl
10 { 10 {
11 - struct Link  
12 - {  
13 - Link(std::unique_ptr<Link> next_link, std::unique_ptr<Pipeline> next_pl) :  
14 - next_link(std::move(next_link)),  
15 - next_pl(std::move(next_pl))  
16 - {  
17 - }  
18 -  
19 - std::unique_ptr<Link> next_link{nullptr};  
20 - std::unique_ptr<Pipeline> next_pl{nullptr};  
21 - };  
22 -  
23 - template <typename P, typename... Args>  
24 - std::unique_ptr<Link>  
25 - create(Args&&... args)  
26 - {  
27 - return std::make_unique<Link>(  
28 - nullptr, std::make_unique<P>("", nullptr, std::forward<Args>(args)...));  
29 - }  
30 -  
31 - template <typename P, typename... Args>  
32 - std::unique_ptr<Link>  
33 - create(std::unique_ptr<Link> link, Args&&... args)  
34 - {  
35 - auto* next = link->next_pl.get();  
36 - return std::make_unique<Link>(  
37 - std::move(link), std::make_unique<P>("", next, std::forward<Args>(args)...));  
38 - }  
39 -  
40 class String final: public Pipeline 11 class String final: public Pipeline
41 { 12 {
42 public: 13 public:
@@ -83,20 +54,10 @@ namespace qpdf::pl @@ -83,20 +54,10 @@ namespace qpdf::pl
83 { 54 {
84 } 55 }
85 56
86 - // Count the number of characters written. If 'next' is not set, the content written will be  
87 - // discarded.  
88 - Count(unsigned long id, std::unique_ptr<Link> link) :  
89 - Pipeline("", link ? link->next_pl.get() : nullptr),  
90 - link(std::move(link)),  
91 - id_(id),  
92 - pass_immediately_to_next(link)  
93 - {  
94 - }  
95 -  
96 // Write to 'str'. If 'next' is set, 'str' will be written to 'next' when 'finish' is 57 // Write to 'str'. If 'next' is set, 'str' will be written to 'next' when 'finish' is
97 // called. 58 // called.
98 - Count(unsigned long id, std::string& str, std::unique_ptr<Link> link = nullptr) :  
99 - Pipeline("", link ? link->next_pl.get() : nullptr), 59 + Count(unsigned long id, std::string& str, std::unique_ptr<Pipeline> link = nullptr) :
  60 + Pipeline("", link.get()),
100 str(&str), 61 str(&str),
101 link(std::move(link)), 62 link(std::move(link)),
102 id_(id) 63 id_(id)
@@ -169,7 +130,7 @@ namespace qpdf::pl @@ -169,7 +130,7 @@ namespace qpdf::pl
169 private: 130 private:
170 qpdf_offset_t count{0}; 131 qpdf_offset_t count{0};
171 std::string* str{nullptr}; 132 std::string* str{nullptr};
172 - std::unique_ptr<Link> link{nullptr}; 133 + std::unique_ptr<Pipeline> link{nullptr};
173 unsigned long id_{0}; 134 unsigned long id_{0};
174 bool pass_immediately_to_next{false}; 135 bool pass_immediately_to_next{false};
175 }; 136 };
libqpdf/qpdf/Pl_AES_PDF.hh
@@ -11,12 +11,7 @@ class Pl_AES_PDF final: public Pipeline @@ -11,12 +11,7 @@ class Pl_AES_PDF final: public Pipeline
11 { 11 {
12 public: 12 public:
13 // key should be a pointer to key_bytes bytes of data 13 // key should be a pointer to key_bytes bytes of data
14 - Pl_AES_PDF(  
15 - char const* identifier,  
16 - Pipeline* next,  
17 - bool encrypt,  
18 - unsigned char const* key,  
19 - size_t key_bytes); 14 + Pl_AES_PDF(char const* identifier, Pipeline* next, bool encrypt, std::string key);
20 ~Pl_AES_PDF() final = default; 15 ~Pl_AES_PDF() final = default;
21 16
22 void write(unsigned char const* data, size_t len) final; 17 void write(unsigned char const* data, size_t len) final;
@@ -42,13 +37,12 @@ class Pl_AES_PDF final: public Pipeline @@ -42,13 +37,12 @@ class Pl_AES_PDF final: public Pipeline
42 static unsigned int const buf_size = QPDFCryptoImpl::rijndael_buf_size; 37 static unsigned int const buf_size = QPDFCryptoImpl::rijndael_buf_size;
43 static bool use_static_iv; 38 static bool use_static_iv;
44 39
  40 + std::string key;
45 std::shared_ptr<QPDFCryptoImpl> crypto; 41 std::shared_ptr<QPDFCryptoImpl> crypto;
46 bool encrypt; 42 bool encrypt;
47 bool cbc_mode{true}; 43 bool cbc_mode{true};
48 bool first{true}; 44 bool first{true};
49 size_t offset{0}; // offset into memory buffer 45 size_t offset{0}; // offset into memory buffer
50 - std::unique_ptr<unsigned char[]> key;  
51 - size_t key_bytes{0};  
52 unsigned char inbuf[buf_size]; 46 unsigned char inbuf[buf_size];
53 unsigned char outbuf[buf_size]; 47 unsigned char outbuf[buf_size];
54 unsigned char cbc_block[buf_size]; 48 unsigned char cbc_block[buf_size];
libqpdf/qpdf/Pl_RC4.hh
@@ -12,11 +12,7 @@ class Pl_RC4 final: public Pipeline @@ -12,11 +12,7 @@ class Pl_RC4 final: public Pipeline
12 12
13 // key_len of -1 means treat key_data as a null-terminated string 13 // key_len of -1 means treat key_data as a null-terminated string
14 Pl_RC4( 14 Pl_RC4(
15 - char const* identifier,  
16 - Pipeline* next,  
17 - unsigned char const* key_data,  
18 - int key_len = -1,  
19 - size_t out_bufsize = def_bufsize); 15 + char const* identifier, Pipeline* next, std::string key, size_t out_bufsize = def_bufsize);
20 ~Pl_RC4() final = default; 16 ~Pl_RC4() final = default;
21 17
22 void write(unsigned char const* data, size_t len) final; 18 void write(unsigned char const* data, size_t len) final;
libtests/aes.cc
@@ -84,8 +84,9 @@ main(int argc, char* argv[]) @@ -84,8 +84,9 @@ main(int argc, char* argv[])
84 key[i / 2] = static_cast<unsigned char>(val); 84 key[i / 2] = static_cast<unsigned char>(val);
85 } 85 }
86 86
  87 + std::string keystr(reinterpret_cast<char const*>(key), keylen);
87 auto* out = new Pl_StdioFile("stdout", outfile); 88 auto* out = new Pl_StdioFile("stdout", outfile);
88 - auto* aes = new Pl_AES_PDF("aes_128_cbc", out, encrypt, key, keylen); 89 + auto* aes = new Pl_AES_PDF("aes_128_cbc", out, encrypt, keystr);
89 delete[] key; 90 delete[] key;
90 key = nullptr; 91 key = nullptr;
91 if (!cbc_mode) { 92 if (!cbc_mode) {
libtests/rc4.cc
@@ -58,7 +58,8 @@ main(int argc, char* argv[]) @@ -58,7 +58,8 @@ main(int argc, char* argv[])
58 FILE* outfile = QUtil::safe_fopen(outfilename, "wb"); 58 FILE* outfile = QUtil::safe_fopen(outfilename, "wb");
59 auto* out = new Pl_StdioFile("stdout", outfile); 59 auto* out = new Pl_StdioFile("stdout", outfile);
60 // Use a small buffer size (64) for testing 60 // Use a small buffer size (64) for testing
61 - auto* rc4 = new Pl_RC4("rc4", out, key, QIntC::to_int(keylen), 64U); 61 + std::string keystr(reinterpret_cast<char const*>(key), keylen);
  62 + auto* rc4 = new Pl_RC4("rc4", out, keystr, 64U);
62 delete[] key; 63 delete[] key;
63 64
64 // 64 < buffer size < 512, buffer_size is not a power of 2 for testing 65 // 64 < buffer size < 512, buffer_size is not a power of 2 for testing