Commit 59f3e09edfc71556208a866bb97ed9e173bd827f

Authored by Jay Berkenbilt
1 parent d55c7ac5

Make Pipeline::write take an unsigned char const* (API change)

Showing 59 changed files with 108 additions and 101 deletions
ChangeLog
  1 +2022-05-03 Jay Berkenbilt <ejb@ql.org>
  2 +
  3 + * API change: Pipeline::write now takes "unsigned char const *"
  4 + instead of "unsigned char*". Callers shouldn't have to change
  5 + anything, though can stop using writable strings or
  6 + QUtil::unsigned_char_pointer. If you have implemented your own
  7 + pipelines, you should change your write method to take a const
  8 + pointer.
  9 +
1 10 2022-05-01 Jay Berkenbilt <ejb@ql.org>
2 11  
3 12 * JSON: add reactors to the JSON parser, making it possible to
... ...
examples/pdf-custom-filter.cc
... ... @@ -49,7 +49,7 @@ class Pl_XOR: public Pipeline
49 49 public:
50 50 Pl_XOR(char const* identifier, Pipeline* next, unsigned char key);
51 51 virtual ~Pl_XOR() = default;
52   - virtual void write(unsigned char* data, size_t len) override;
  52 + virtual void write(unsigned char const* data, size_t len) override;
53 53 virtual void finish() override;
54 54  
55 55 private:
... ... @@ -63,7 +63,7 @@ Pl_XOR::Pl_XOR(char const* identifier, Pipeline* next, unsigned char key) :
63 63 }
64 64  
65 65 void
66   -Pl_XOR::write(unsigned char* data, size_t len)
  66 +Pl_XOR::write(unsigned char const* data, size_t len)
67 67 {
68 68 for (size_t i = 0; i < len; ++i) {
69 69 unsigned char p = data[i] ^ this->key;
... ...
include/qpdf/Pipeline.hh
... ... @@ -63,15 +63,9 @@ class QPDF_DLL_CLASS Pipeline
63 63  
64 64 // Subclasses should implement write and finish to do their jobs
65 65 // and then, if they are not end-of-line pipelines, call
66   - // getNext()->write or getNext()->finish. It would be really nice
67   - // if write could take unsigned char const*, but this would make
68   - // it much more difficult to write pipelines around legacy
69   - // interfaces whose calls don't want pointers to const data. As a
70   - // rule, pipelines should generally not be modifying the data
71   - // passed to them. They should, instead, create new data to pass
72   - // downstream.
  66 + // getNext()->write or getNext()->finish.
73 67 QPDF_DLL
74   - virtual void write(unsigned char* data, size_t len) = 0;
  68 + virtual void write(unsigned char const* data, size_t len) = 0;
75 69 QPDF_DLL
76 70 virtual void finish() = 0;
77 71 QPDF_DLL
... ...
include/qpdf/Pl_Buffer.hh
... ... @@ -47,7 +47,7 @@ class QPDF_DLL_CLASS Pl_Buffer: public Pipeline
47 47 QPDF_DLL
48 48 virtual ~Pl_Buffer();
49 49 QPDF_DLL
50   - virtual void write(unsigned char*, size_t);
  50 + virtual void write(unsigned char const*, size_t);
51 51 QPDF_DLL
52 52 virtual void finish();
53 53  
... ...
include/qpdf/Pl_Concatenate.hh
... ... @@ -39,7 +39,7 @@ class QPDF_DLL_CLASS Pl_Concatenate: public Pipeline
39 39 virtual ~Pl_Concatenate();
40 40  
41 41 QPDF_DLL
42   - virtual void write(unsigned char* data, size_t len);
  42 + virtual void write(unsigned char const* data, size_t len);
43 43  
44 44 QPDF_DLL
45 45 virtual void finish();
... ...
include/qpdf/Pl_Count.hh
... ... @@ -36,7 +36,7 @@ class QPDF_DLL_CLASS Pl_Count: public Pipeline
36 36 QPDF_DLL
37 37 virtual ~Pl_Count();
38 38 QPDF_DLL
39   - virtual void write(unsigned char*, size_t);
  39 + virtual void write(unsigned char const*, size_t);
40 40 QPDF_DLL
41 41 virtual void finish();
42 42 // Returns the number of bytes written
... ...
include/qpdf/Pl_DCT.hh
... ... @@ -61,7 +61,7 @@ class QPDF_DLL_CLASS Pl_DCT: public Pipeline
61 61 virtual ~Pl_DCT();
62 62  
63 63 QPDF_DLL
64   - virtual void write(unsigned char* data, size_t len);
  64 + virtual void write(unsigned char const* data, size_t len);
65 65 QPDF_DLL
66 66 virtual void finish();
67 67  
... ...
include/qpdf/Pl_Discard.hh
... ... @@ -38,7 +38,7 @@ class QPDF_DLL_CLASS Pl_Discard: public Pipeline
38 38 QPDF_DLL
39 39 virtual ~Pl_Discard();
40 40 QPDF_DLL
41   - virtual void write(unsigned char*, size_t);
  41 + virtual void write(unsigned char const*, size_t);
42 42 QPDF_DLL
43 43 virtual void finish();
44 44  
... ...
include/qpdf/Pl_Flate.hh
... ... @@ -43,7 +43,7 @@ class QPDF_DLL_CLASS Pl_Flate: public Pipeline
43 43 virtual ~Pl_Flate();
44 44  
45 45 QPDF_DLL
46   - virtual void write(unsigned char* data, size_t len);
  46 + virtual void write(unsigned char const* data, size_t len);
47 47 QPDF_DLL
48 48 virtual void finish();
49 49  
... ... @@ -61,7 +61,7 @@ class QPDF_DLL_CLASS Pl_Flate: public Pipeline
61 61  
62 62 private:
63 63 QPDF_DLL_PRIVATE
64   - void handleData(unsigned char* data, size_t len, int flush);
  64 + void handleData(unsigned char const* data, size_t len, int flush);
65 65 QPDF_DLL_PRIVATE
66 66 void checkError(char const* prefix, int error_code);
67 67 QPDF_DLL_PRIVATE
... ...
include/qpdf/Pl_QPDFTokenizer.hh
... ... @@ -55,7 +55,7 @@ class QPDF_DLL_CLASS Pl_QPDFTokenizer: public Pipeline
55 55 QPDF_DLL
56 56 virtual ~Pl_QPDFTokenizer();
57 57 QPDF_DLL
58   - virtual void write(unsigned char* buf, size_t len);
  58 + virtual void write(unsigned char const* buf, size_t len);
59 59 QPDF_DLL
60 60 virtual void finish();
61 61  
... ...
include/qpdf/Pl_RunLength.hh
... ... @@ -35,15 +35,15 @@ class QPDF_DLL_CLASS Pl_RunLength: public Pipeline
35 35 virtual ~Pl_RunLength();
36 36  
37 37 QPDF_DLL
38   - virtual void write(unsigned char* data, size_t len);
  38 + virtual void write(unsigned char const* data, size_t len);
39 39 QPDF_DLL
40 40 virtual void finish();
41 41  
42 42 private:
43 43 QPDF_DLL_PRIVATE
44   - void encode(unsigned char* data, size_t len);
  44 + void encode(unsigned char const* data, size_t len);
45 45 QPDF_DLL_PRIVATE
46   - void decode(unsigned char* data, size_t len);
  46 + void decode(unsigned char const* data, size_t len);
47 47 QPDF_DLL_PRIVATE
48 48 void flush_encode();
49 49  
... ...
include/qpdf/Pl_StdioFile.hh
... ... @@ -43,7 +43,7 @@ class QPDF_DLL_CLASS Pl_StdioFile: public Pipeline
43 43 virtual ~Pl_StdioFile();
44 44  
45 45 QPDF_DLL
46   - virtual void write(unsigned char* buf, size_t len);
  46 + virtual void write(unsigned char const* buf, size_t len);
47 47 QPDF_DLL
48 48 virtual void finish();
49 49  
... ...
include/qpdf/QPDFCryptoImpl.hh
... ... @@ -78,7 +78,9 @@ class QPDF_DLL_CLASS QPDFCryptoImpl
78 78 // out_data = 0 means to encrypt/decrypt in place
79 79 QPDF_DLL
80 80 virtual void RC4_process(
81   - unsigned char* in_data, size_t len, unsigned char* out_data = 0) = 0;
  81 + unsigned char const* in_data,
  82 + size_t len,
  83 + unsigned char* out_data = 0) = 0;
82 84 QPDF_DLL
83 85 virtual void RC4_finalize() = 0;
84 86  
... ...
libqpdf/Pipeline.cc
1 1 #include <qpdf/Pipeline.hh>
2 2  
  3 +#include <cstring>
3 4 #include <stdexcept>
4 5  
5 6 Pipeline::Pipeline(char const* identifier, Pipeline* next) :
... ...
libqpdf/Pl_AES_PDF.cc
... ... @@ -72,10 +72,10 @@ Pl_AES_PDF::useStaticIV()
72 72 }
73 73  
74 74 void
75   -Pl_AES_PDF::write(unsigned char* data, size_t len)
  75 +Pl_AES_PDF::write(unsigned char const* data, size_t len)
76 76 {
77 77 size_t bytes_left = len;
78   - unsigned char* p = data;
  78 + unsigned char const* p = data;
79 79  
80 80 while (bytes_left > 0) {
81 81 if (this->offset == this->buf_size) {
... ...
libqpdf/Pl_ASCII85Decoder.cc
... ... @@ -13,7 +13,7 @@ Pl_ASCII85Decoder::Pl_ASCII85Decoder(char const* identifier, Pipeline* next) :
13 13 }
14 14  
15 15 void
16   -Pl_ASCII85Decoder::write(unsigned char* buf, size_t len)
  16 +Pl_ASCII85Decoder::write(unsigned char const* buf, size_t len)
17 17 {
18 18 if (eod > 1) {
19 19 return;
... ...
libqpdf/Pl_ASCIIHexDecoder.cc
... ... @@ -16,7 +16,7 @@ Pl_ASCIIHexDecoder::Pl_ASCIIHexDecoder(char const* identifier, Pipeline* next) :
16 16 }
17 17  
18 18 void
19   -Pl_ASCIIHexDecoder::write(unsigned char* buf, size_t len)
  19 +Pl_ASCIIHexDecoder::write(unsigned char const* buf, size_t len)
20 20 {
21 21 if (this->eod) {
22 22 return;
... ...
libqpdf/Pl_Base64.cc
... ... @@ -35,7 +35,7 @@ Pl_Base64::Pl_Base64(char const* identifier, Pipeline* next, action_e action) :
35 35 }
36 36  
37 37 void
38   -Pl_Base64::write(unsigned char* data, size_t len)
  38 +Pl_Base64::write(unsigned char const* data, size_t len)
39 39 {
40 40 if (finished) {
41 41 throw std::logic_error("Pl_Base64 used after finished");
... ... @@ -48,9 +48,9 @@ Pl_Base64::write(unsigned char* data, size_t len)
48 48 }
49 49  
50 50 void
51   -Pl_Base64::decode(unsigned char* data, size_t len)
  51 +Pl_Base64::decode(unsigned char const* data, size_t len)
52 52 {
53   - unsigned char* p = data;
  53 + unsigned char const* p = data;
54 54 while (len > 0) {
55 55 if (!QUtil::is_space(to_c(*p))) {
56 56 this->buf[this->pos++] = *p;
... ... @@ -64,9 +64,9 @@ Pl_Base64::decode(unsigned char* data, size_t len)
64 64 }
65 65  
66 66 void
67   -Pl_Base64::encode(unsigned char* data, size_t len)
  67 +Pl_Base64::encode(unsigned char const* data, size_t len)
68 68 {
69   - unsigned char* p = data;
  69 + unsigned char const* p = data;
70 70 while (len > 0) {
71 71 this->buf[this->pos++] = *p;
72 72 if (this->pos == 3) {
... ...
libqpdf/Pl_Buffer.cc
... ... @@ -24,7 +24,7 @@ Pl_Buffer::~Pl_Buffer()
24 24 }
25 25  
26 26 void
27   -Pl_Buffer::write(unsigned char* buf, size_t len)
  27 +Pl_Buffer::write(unsigned char const* buf, size_t len)
28 28 {
29 29 if (this->m->data.get() == 0) {
30 30 this->m->data = std::make_shared<Buffer>(len);
... ...
libqpdf/Pl_Concatenate.cc
... ... @@ -12,7 +12,7 @@ Pl_Concatenate::~Pl_Concatenate()
12 12 }
13 13  
14 14 void
15   -Pl_Concatenate::write(unsigned char* data, size_t len)
  15 +Pl_Concatenate::write(unsigned char const* data, size_t len)
16 16 {
17 17 getNext()->write(data, len);
18 18 }
... ...
libqpdf/Pl_Count.cc
... ... @@ -21,7 +21,7 @@ Pl_Count::~Pl_Count()
21 21 }
22 22  
23 23 void
24   -Pl_Count::write(unsigned char* buf, size_t len)
  24 +Pl_Count::write(unsigned char const* buf, size_t len)
25 25 {
26 26 if (len) {
27 27 this->m->count += QIntC::to_offset(len);
... ...
libqpdf/Pl_DCT.cc
... ... @@ -86,7 +86,7 @@ Pl_DCT::~Pl_DCT()
86 86 }
87 87  
88 88 void
89   -Pl_DCT::write(unsigned char* data, size_t len)
  89 +Pl_DCT::write(unsigned char const* data, size_t len)
90 90 {
91 91 this->m->buf.write(data, len);
92 92 }
... ...
libqpdf/Pl_Discard.cc
... ... @@ -14,7 +14,7 @@ Pl_Discard::~Pl_Discard()
14 14 }
15 15  
16 16 void
17   -Pl_Discard::write(unsigned char* buf, size_t len)
  17 +Pl_Discard::write(unsigned char const* buf, size_t len)
18 18 {
19 19 }
20 20  
... ...
libqpdf/Pl_Flate.cc
... ... @@ -84,7 +84,7 @@ Pl_Flate::warn(char const* msg, int code)
84 84 }
85 85  
86 86 void
87   -Pl_Flate::write(unsigned char* data, size_t len)
  87 +Pl_Flate::write(unsigned char const* data, size_t len)
88 88 {
89 89 if (this->m->outbuf.get() == 0) {
90 90 throw std::logic_error(
... ... @@ -96,7 +96,7 @@ Pl_Flate::write(unsigned char* data, size_t len)
96 96 // Assume int is at least 32 bits.
97 97 static size_t const max_bytes = 1 << 30;
98 98 size_t bytes_left = len;
99   - unsigned char* buf = data;
  99 + unsigned char const* buf = data;
100 100 while (bytes_left > 0) {
101 101 size_t bytes = (bytes_left >= max_bytes ? max_bytes : bytes_left);
102 102 handleData(
... ... @@ -109,14 +109,16 @@ Pl_Flate::write(unsigned char* data, size_t len)
109 109 }
110 110  
111 111 void
112   -Pl_Flate::handleData(unsigned char* data, size_t len, int flush)
  112 +Pl_Flate::handleData(unsigned char const* data, size_t len, int flush)
113 113 {
114 114 if (len > UINT_MAX) {
115 115 throw std::runtime_error("Pl_Flate: zlib doesn't support data"
116 116 " blocks larger than int");
117 117 }
118 118 z_stream& zstream = *(static_cast<z_stream*>(this->m->zdata));
119   - zstream.next_in = data;
  119 + // zlib is known not to modify the data pointed to by next_in but
  120 + // doesn't declare the field value const unless compiled to do so.
  121 + zstream.next_in = const_cast<unsigned char*>(data);
120 122 zstream.avail_in = QIntC::to_uint(len);
121 123  
122 124 if (!this->m->initialized) {
... ...
libqpdf/Pl_LZWDecoder.cc
... ... @@ -22,7 +22,7 @@ Pl_LZWDecoder::Pl_LZWDecoder(
22 22 }
23 23  
24 24 void
25   -Pl_LZWDecoder::write(unsigned char* bytes, size_t len)
  25 +Pl_LZWDecoder::write(unsigned char const* bytes, size_t len)
26 26 {
27 27 for (size_t i = 0; i < len; ++i) {
28 28 this->buf[next++] = bytes[i];
... ...
libqpdf/Pl_MD5.cc
... ... @@ -11,7 +11,7 @@ Pl_MD5::Pl_MD5(char const* identifier, Pipeline* next) :
11 11 }
12 12  
13 13 void
14   -Pl_MD5::write(unsigned char* buf, size_t len)
  14 +Pl_MD5::write(unsigned char const* buf, size_t len)
15 15 {
16 16 if (this->enabled) {
17 17 if (!this->in_progress) {
... ... @@ -23,11 +23,11 @@ Pl_MD5::write(unsigned char* buf, size_t len)
23 23 // Assume int is at least 32 bits.
24 24 static size_t const max_bytes = 1 << 30;
25 25 size_t bytes_left = len;
26   - unsigned char* data = buf;
  26 + unsigned char const* data = buf;
27 27 while (bytes_left > 0) {
28 28 size_t bytes = (bytes_left >= max_bytes ? max_bytes : bytes_left);
29 29 this->md5.encodeDataIncrementally(
30   - reinterpret_cast<char*>(data), bytes);
  30 + reinterpret_cast<char const*>(data), bytes);
31 31 bytes_left -= bytes;
32 32 data += bytes;
33 33 }
... ...
libqpdf/Pl_PNGFilter.cc
... ... @@ -62,7 +62,7 @@ Pl_PNGFilter::Pl_PNGFilter(
62 62 }
63 63  
64 64 void
65   -Pl_PNGFilter::write(unsigned char* data, size_t len)
  65 +Pl_PNGFilter::write(unsigned char const* data, size_t len)
66 66 {
67 67 size_t left = this->incoming - this->pos;
68 68 size_t offset = 0;
... ...
libqpdf/Pl_QPDFTokenizer.cc
... ... @@ -33,7 +33,7 @@ Pl_QPDFTokenizer::~Pl_QPDFTokenizer()
33 33 }
34 34  
35 35 void
36   -Pl_QPDFTokenizer::write(unsigned char* data, size_t len)
  36 +Pl_QPDFTokenizer::write(unsigned char const* data, size_t len)
37 37 {
38 38 this->m->buf.write(data, len);
39 39 }
... ...
libqpdf/Pl_RC4.cc
... ... @@ -16,7 +16,7 @@ Pl_RC4::Pl_RC4(
16 16 }
17 17  
18 18 void
19   -Pl_RC4::write(unsigned char* data, size_t len)
  19 +Pl_RC4::write(unsigned char const* data, size_t len)
20 20 {
21 21 if (this->outbuf.get() == 0) {
22 22 throw std::logic_error(
... ... @@ -25,7 +25,7 @@ Pl_RC4::write(unsigned char* data, size_t len)
25 25 }
26 26  
27 27 size_t bytes_left = len;
28   - unsigned char* p = data;
  28 + unsigned char const* p = data;
29 29  
30 30 while (bytes_left > 0) {
31 31 size_t bytes =
... ...
libqpdf/Pl_RunLength.cc
... ... @@ -24,7 +24,7 @@ Pl_RunLength::~Pl_RunLength()
24 24 }
25 25  
26 26 void
27   -Pl_RunLength::write(unsigned char* data, size_t len)
  27 +Pl_RunLength::write(unsigned char const* data, size_t len)
28 28 {
29 29 if (this->m->action == a_encode) {
30 30 encode(data, len);
... ... @@ -34,7 +34,7 @@ Pl_RunLength::write(unsigned char* data, size_t len)
34 34 }
35 35  
36 36 void
37   -Pl_RunLength::encode(unsigned char* data, size_t len)
  37 +Pl_RunLength::encode(unsigned char const* data, size_t len)
38 38 {
39 39 for (size_t i = 0; i < len; ++i) {
40 40 if ((this->m->state == st_top) != (this->m->length <= 1)) {
... ... @@ -71,7 +71,7 @@ Pl_RunLength::encode(unsigned char* data, size_t len)
71 71 }
72 72  
73 73 void
74   -Pl_RunLength::decode(unsigned char* data, size_t len)
  74 +Pl_RunLength::decode(unsigned char const* data, size_t len)
75 75 {
76 76 for (size_t i = 0; i < len; ++i) {
77 77 unsigned char ch = data[i];
... ...
libqpdf/Pl_SHA2.cc
... ... @@ -15,7 +15,7 @@ Pl_SHA2::Pl_SHA2(int bits, Pipeline* next) :
15 15 }
16 16  
17 17 void
18   -Pl_SHA2::write(unsigned char* buf, size_t len)
  18 +Pl_SHA2::write(unsigned char const* buf, size_t len)
19 19 {
20 20 if (!this->in_progress) {
21 21 this->in_progress = true;
... ... @@ -25,7 +25,7 @@ Pl_SHA2::write(unsigned char* buf, size_t len)
25 25 // Assume int is at least 32 bits.
26 26 static size_t const max_bytes = 1 << 30;
27 27 size_t bytes_left = len;
28   - unsigned char* data = buf;
  28 + unsigned char const* data = buf;
29 29 while (bytes_left > 0) {
30 30 size_t bytes = (bytes_left >= max_bytes ? max_bytes : bytes_left);
31 31 this->crypto->SHA2_update(data, bytes);
... ...
libqpdf/Pl_StdioFile.cc
... ... @@ -24,7 +24,7 @@ Pl_StdioFile::~Pl_StdioFile()
24 24 }
25 25  
26 26 void
27   -Pl_StdioFile::write(unsigned char* buf, size_t len)
  27 +Pl_StdioFile::write(unsigned char const* buf, size_t len)
28 28 {
29 29 size_t so_far = 0;
30 30 while (len > 0) {
... ...
libqpdf/Pl_TIFFPredictor.cc
... ... @@ -46,7 +46,7 @@ Pl_TIFFPredictor::Pl_TIFFPredictor(
46 46 }
47 47  
48 48 void
49   -Pl_TIFFPredictor::write(unsigned char* data, size_t len)
  49 +Pl_TIFFPredictor::write(unsigned char const* data, size_t len)
50 50 {
51 51 size_t left = this->bytes_per_row - this->pos;
52 52 size_t offset = 0;
... ...
libqpdf/QPDFCrypto_gnutls.cc
... ... @@ -97,11 +97,8 @@ QPDFCrypto_gnutls::RC4_init(unsigned char const* key_data, int key_len)
97 97  
98 98 void
99 99 QPDFCrypto_gnutls::RC4_process(
100   - unsigned char* in_data, size_t len, unsigned char* out_data)
  100 + unsigned char const* in_data, size_t len, unsigned char* out_data)
101 101 {
102   - if (nullptr == out_data) {
103   - out_data = in_data;
104   - }
105 102 gnutls_cipher_encrypt2(this->cipher_ctx, in_data, len, out_data, len);
106 103 }
107 104  
... ...
libqpdf/QPDFCrypto_native.cc
... ... @@ -69,7 +69,7 @@ QPDFCrypto_native::RC4_init(unsigned char const* key_data, int key_len)
69 69  
70 70 void
71 71 QPDFCrypto_native::RC4_process(
72   - unsigned char* in_data, size_t len, unsigned char* out_data)
  72 + unsigned char const* in_data, size_t len, unsigned char* out_data)
73 73 {
74 74 this->rc4->process(in_data, len, out_data);
75 75 }
... ...
libqpdf/QPDFCrypto_openssl.cc
... ... @@ -217,11 +217,8 @@ QPDFCrypto_openssl::rijndael_init(
217 217  
218 218 void
219 219 QPDFCrypto_openssl::RC4_process(
220   - unsigned char* in_data, size_t len, unsigned char* out_data)
  220 + unsigned char const* in_data, size_t len, unsigned char* out_data)
221 221 {
222   - if (nullptr == out_data) {
223   - out_data = in_data;
224   - }
225 222 int out_len = static_cast<int>(len);
226 223 check_openssl(
227 224 EVP_EncryptUpdate(cipher_ctx, out_data, &out_len, in_data, out_len));
... ...
libqpdf/QPDFObjectHandle.cc
... ... @@ -180,7 +180,7 @@ namespace
180 180 public:
181 181 LastChar(Pipeline* next);
182 182 virtual ~LastChar() = default;
183   - virtual void write(unsigned char* data, size_t len);
  183 + virtual void write(unsigned char const* data, size_t len);
184 184 virtual void finish();
185 185 unsigned char getLastChar();
186 186  
... ... @@ -196,7 +196,7 @@ LastChar::LastChar(Pipeline* next) :
196 196 }
197 197  
198 198 void
199   -LastChar::write(unsigned char* data, size_t len)
  199 +LastChar::write(unsigned char const* data, size_t len)
200 200 {
201 201 if (len > 0) {
202 202 this->last_char = data[len - 1];
... ...
libqpdf/QPDFWriter.cc
... ... @@ -1750,7 +1750,8 @@ QPDFWriter::unparseObject(
1750 1750 RC4 rc4(
1751 1751 QUtil::unsigned_char_pointer(this->m->cur_data_key),
1752 1752 QIntC::to_int(this->m->cur_data_key.length()));
1753   - rc4.process(QUtil::unsigned_char_pointer(tmp), vlen);
  1753 + auto data = QUtil::unsigned_char_pointer(tmp);
  1754 + rc4.process(data, vlen, data);
1754 1755 val = QPDF_String(std::string(tmp, vlen)).unparse();
1755 1756 }
1756 1757 } else if (flags & f_hex_string) {
... ...
libqpdf/QPDF_encryption.cc
... ... @@ -207,7 +207,7 @@ iterate_rc4(
207 207 key[j] = static_cast<unsigned char>(okey[j] ^ xor_value);
208 208 }
209 209 RC4 rc4(key, QIntC::to_int(key_len));
210   - rc4.process(data, data_len);
  210 + rc4.process(data, data_len, data);
211 211 }
212 212 }
213 213  
... ... @@ -1163,7 +1163,8 @@ QPDF::decryptString(std::string&amp; str, int objid, int generation)
1163 1163 // be freed even if rc4.process throws an exception.
1164 1164 auto tmp = QUtil::make_unique_cstr(str);
1165 1165 RC4 rc4(QUtil::unsigned_char_pointer(key), toI(key.length()));
1166   - rc4.process(QUtil::unsigned_char_pointer(tmp.get()), vlen);
  1166 + auto data = QUtil::unsigned_char_pointer(tmp.get());
  1167 + rc4.process(data, vlen, data);
1167 1168 str = std::string(tmp.get(), vlen);
1168 1169 }
1169 1170 } catch (QPDFExc&) {
... ...
libqpdf/RC4.cc
... ... @@ -11,7 +11,7 @@ RC4::RC4(unsigned char const* key_data, int key_len) :
11 11 }
12 12  
13 13 void
14   -RC4::process(unsigned char* in_data, size_t len, unsigned char* out_data)
  14 +RC4::process(unsigned char const* in_data, size_t len, unsigned char* out_data)
15 15 {
16 16 this->crypto->RC4_process(in_data, len, out_data);
17 17 }
... ...
libqpdf/RC4_native.cc
... ... @@ -37,13 +37,9 @@ RC4_native::RC4_native(unsigned char const* key_data, int key_len)
37 37 }
38 38  
39 39 void
40   -RC4_native::process(unsigned char* in_data, size_t len, unsigned char* out_data)
  40 +RC4_native::process(
  41 + unsigned char const* in_data, size_t len, unsigned char* out_data)
41 42 {
42   - if (out_data == 0) {
43   - // Convert in place
44   - out_data = in_data;
45   - }
46   -
47 43 for (size_t i = 0; i < len; ++i) {
48 44 key.x = static_cast<unsigned char>((key.x + 1) % 256);
49 45 key.y = static_cast<unsigned char>((key.state[key.x] + key.y) % 256);
... ...
libqpdf/qpdf/Pl_AES_PDF.hh
... ... @@ -20,7 +20,7 @@ class Pl_AES_PDF: public Pipeline
20 20 size_t key_bytes);
21 21 virtual ~Pl_AES_PDF() = default;
22 22  
23   - virtual void write(unsigned char* data, size_t len);
  23 + virtual void write(unsigned char const* data, size_t len);
24 24 virtual void finish();
25 25  
26 26 // Use zero initialization vector; needed for AESV3
... ...
libqpdf/qpdf/Pl_ASCII85Decoder.hh
... ... @@ -8,7 +8,7 @@ class Pl_ASCII85Decoder: public Pipeline
8 8 public:
9 9 Pl_ASCII85Decoder(char const* identifier, Pipeline* next);
10 10 virtual ~Pl_ASCII85Decoder() = default;
11   - virtual void write(unsigned char* buf, size_t len);
  11 + virtual void write(unsigned char const* buf, size_t len);
12 12 virtual void finish();
13 13  
14 14 private:
... ...
libqpdf/qpdf/Pl_ASCIIHexDecoder.hh
... ... @@ -8,7 +8,7 @@ class Pl_ASCIIHexDecoder: public Pipeline
8 8 public:
9 9 Pl_ASCIIHexDecoder(char const* identifier, Pipeline* next);
10 10 virtual ~Pl_ASCIIHexDecoder() = default;
11   - virtual void write(unsigned char* buf, size_t len);
  11 + virtual void write(unsigned char const* buf, size_t len);
12 12 virtual void finish();
13 13  
14 14 private:
... ...
libqpdf/qpdf/Pl_Base64.hh
... ... @@ -9,12 +9,12 @@ class Pl_Base64: public Pipeline
9 9 enum action_e { a_encode, a_decode };
10 10 Pl_Base64(char const* identifier, Pipeline* next, action_e);
11 11 virtual ~Pl_Base64() = default;
12   - virtual void write(unsigned char* buf, size_t len) override;
  12 + virtual void write(unsigned char const* buf, size_t len) override;
13 13 virtual void finish() override;
14 14  
15 15 private:
16   - void decode(unsigned char* buf, size_t len);
17   - void encode(unsigned char* buf, size_t len);
  16 + void decode(unsigned char const* buf, size_t len);
  17 + void encode(unsigned char const* buf, size_t len);
18 18 void flush();
19 19 void flush_decode();
20 20 void flush_encode();
... ...
libqpdf/qpdf/Pl_LZWDecoder.hh
... ... @@ -12,7 +12,7 @@ class Pl_LZWDecoder: public Pipeline
12 12 Pl_LZWDecoder(
13 13 char const* identifier, Pipeline* next, bool early_code_change);
14 14 virtual ~Pl_LZWDecoder() = default;
15   - virtual void write(unsigned char* buf, size_t len);
  15 + virtual void write(unsigned char const* buf, size_t len);
16 16 virtual void finish();
17 17  
18 18 private:
... ...
libqpdf/qpdf/Pl_MD5.hh
... ... @@ -17,7 +17,7 @@ class Pl_MD5: public Pipeline
17 17 public:
18 18 Pl_MD5(char const* identifier, Pipeline* next);
19 19 virtual ~Pl_MD5() = default;
20   - virtual void write(unsigned char*, size_t);
  20 + virtual void write(unsigned char const*, size_t);
21 21 virtual void finish();
22 22 std::string getHexDigest();
23 23 // Enable/disable. Disabling the pipeline causes it to become a
... ...
libqpdf/qpdf/Pl_PNGFilter.hh
... ... @@ -24,7 +24,7 @@ class Pl_PNGFilter: public Pipeline
24 24 unsigned int bits_per_sample = 8);
25 25 virtual ~Pl_PNGFilter() = default;
26 26  
27   - virtual void write(unsigned char* data, size_t len);
  27 + virtual void write(unsigned char const* data, size_t len);
28 28 virtual void finish();
29 29  
30 30 private:
... ...
libqpdf/qpdf/Pl_RC4.hh
... ... @@ -19,7 +19,7 @@ class Pl_RC4: public Pipeline
19 19 size_t out_bufsize = def_bufsize);
20 20 virtual ~Pl_RC4() = default;
21 21  
22   - virtual void write(unsigned char* data, size_t len);
  22 + virtual void write(unsigned char const* data, size_t len);
23 23 virtual void finish();
24 24  
25 25 private:
... ...
libqpdf/qpdf/Pl_SHA2.hh
... ... @@ -22,7 +22,7 @@ class Pl_SHA2: public Pipeline
22 22 public:
23 23 Pl_SHA2(int bits = 0, Pipeline* next = 0);
24 24 virtual ~Pl_SHA2() = default;
25   - virtual void write(unsigned char*, size_t);
  25 + virtual void write(unsigned char const*, size_t);
26 26 virtual void finish();
27 27 void resetBits(int bits);
28 28 std::string getHexDigest();
... ...
libqpdf/qpdf/Pl_TIFFPredictor.hh
... ... @@ -20,7 +20,7 @@ class Pl_TIFFPredictor: public Pipeline
20 20 unsigned int bits_per_sample = 8);
21 21 virtual ~Pl_TIFFPredictor() = default;
22 22  
23   - virtual void write(unsigned char* data, size_t len);
  23 + virtual void write(unsigned char const* data, size_t len);
24 24 virtual void finish();
25 25  
26 26 private:
... ...
libqpdf/qpdf/QPDFCrypto_gnutls.hh
... ... @@ -26,7 +26,7 @@ class QPDFCrypto_gnutls: public QPDFCryptoImpl
26 26  
27 27 virtual void RC4_init(unsigned char const* key_data, int key_len = -1);
28 28 virtual void RC4_process(
29   - unsigned char* in_data, size_t len, unsigned char* out_data = 0);
  29 + unsigned char const* in_data, size_t len, unsigned char* out_data = 0);
30 30 virtual void RC4_finalize();
31 31  
32 32 virtual void SHA2_init(int bits);
... ...
libqpdf/qpdf/QPDFCrypto_native.hh
... ... @@ -24,7 +24,7 @@ class QPDFCrypto_native: public QPDFCryptoImpl
24 24  
25 25 virtual void RC4_init(unsigned char const* key_data, int key_len = -1);
26 26 virtual void RC4_process(
27   - unsigned char* in_data, size_t len, unsigned char* out_data = 0);
  27 + unsigned char const* in_data, size_t len, unsigned char* out_data = 0);
28 28 virtual void RC4_finalize();
29 29  
30 30 virtual void SHA2_init(int bits);
... ...
libqpdf/qpdf/QPDFCrypto_openssl.hh
... ... @@ -37,7 +37,7 @@ class QPDFCrypto_openssl: public QPDFCryptoImpl
37 37  
38 38 void RC4_init(unsigned char const* key_data, int key_len = -1) override;
39 39 void RC4_process(
40   - unsigned char* in_data,
  40 + unsigned char const* in_data,
41 41 size_t len,
42 42 unsigned char* out_data = 0) override;
43 43 void RC4_finalize() override;
... ...
libqpdf/qpdf/RC4.hh
... ... @@ -11,9 +11,10 @@ class RC4
11 11 // key_len of -1 means treat key_data as a null-terminated string
12 12 RC4(unsigned char const* key_data, int key_len = -1);
13 13  
14   - // out_data = 0 means to encrypt/decrypt in place
  14 + // It is safe to pass the same pointer to in_data and out_data to
  15 + // encrypt/decrypt in place
15 16 void
16   - process(unsigned char* in_data, size_t len, unsigned char* out_data = 0);
  17 + process(unsigned char const* in_data, size_t len, unsigned char* out_data);
17 18  
18 19 private:
19 20 std::shared_ptr<QPDFCryptoImpl> crypto;
... ...
libqpdf/qpdf/RC4_native.hh
... ... @@ -10,8 +10,8 @@ class RC4_native
10 10 RC4_native(unsigned char const* key_data, int key_len = -1);
11 11  
12 12 // out_data = 0 means to encrypt/decrypt in place
13   - void
14   - process(unsigned char* in_data, size_t len, unsigned char* out_data = 0);
  13 + void process(
  14 + unsigned char const* in_data, size_t len, unsigned char* out_data = 0);
15 15  
16 16 private:
17 17 class RC4Key
... ...
libtests/rc4.cc
... ... @@ -18,7 +18,7 @@ other_tests()
18 18 RC4 r(reinterpret_cast<unsigned char const*>("quack"));
19 19 auto data = std::make_unique<unsigned char[]>(6);
20 20 memcpy(data.get(), "potato", 6);
21   - r.process(data.get(), 6);
  21 + r.process(data.get(), 6, data.get());
22 22 assert(memcmp(data.get(), "\xa5\x6f\xe7\x27\x2b\x5c", 6) == 0);
23 23 std::cout << "passed" << std::endl;
24 24 }
... ...
manual/release-notes.rst
... ... @@ -68,12 +68,18 @@ For a detailed list of changes, please see the file
68 68  
69 69 - API: breaking changes
70 70  
71   - - Remove
  71 + - Pipeline::write now takes ``unsigned char const*`` instead of
  72 + ``unsigned char*``. Callers don't need to change anything, but
  73 + you no longer have to pass writable pointers to pipelines. If
  74 + you've implemented your own pipeline classes, you will need to
  75 + update them.
  76 +
  77 + - Remove deprecated
72 78 ``QPDFAcroFormDocumentHelper::copyFieldsFromForeignPage``. This
73 79 method never worked and only did something in qpdf version
74 80 10.2.x.
75 81  
76   - - Remove ``QPDFNameTreeObjectHelper`` and
  82 + - Remove deprecated ``QPDFNameTreeObjectHelper`` and
77 83 ``QPDFNumberTreeObjectHelper`` constructors that don't take a
78 84 ``QPDF&`` argument.
79 85  
... ...
qpdf/test_large_file.cc
... ... @@ -63,7 +63,7 @@ class ImageChecker: public Pipeline
63 63 public:
64 64 ImageChecker(size_t n);
65 65 virtual ~ImageChecker() = default;
66   - virtual void write(unsigned char* data, size_t len);
  66 + virtual void write(unsigned char const* data, size_t len);
67 67 virtual void finish();
68 68  
69 69 private:
... ... @@ -81,7 +81,7 @@ ImageChecker::ImageChecker(size_t n) :
81 81 }
82 82  
83 83 void
84   -ImageChecker::write(unsigned char* data, size_t len)
  84 +ImageChecker::write(unsigned char const* data, size_t len)
85 85 {
86 86 for (size_t i = 0; i < len; ++i) {
87 87 size_t y = (this->offset + i) / width / stripesize;
... ...