Commit 661db7435145279ae81c87c837c4de263991ab8f

Authored by m-holger
Committed by GitHub
2 parents 0c5318eb 44f726da

Merge pull request #1481 from m-holger/pl_dct

Refactor `Pl_DCT` buffer management to use `std::string` and simplify…
include/qpdf/Pl_DCT.hh
... ... @@ -22,7 +22,6 @@
22 22  
23 23 #include <qpdf/Pipeline.hh>
24 24  
25   -#include <qpdf/Pl_Buffer.hh>
26 25 #include <cstddef>
27 26 #include <functional>
28 27  
... ... @@ -88,9 +87,9 @@ class QPDF_DLL_CLASS Pl_DCT: public Pipeline
88 87  
89 88 private:
90 89 QPDF_DLL_PRIVATE
91   - void compress(void* cinfo, Buffer*);
  90 + void compress(void* cinfo);
92 91 QPDF_DLL_PRIVATE
93   - void decompress(void* cinfo, Buffer*);
  92 + void decompress(void* cinfo);
94 93  
95 94 enum action_e { a_compress, a_decompress };
96 95  
... ...
libqpdf/Pl_DCT.cc
... ... @@ -84,7 +84,6 @@ class Pl_DCT::Members
84 84 J_COLOR_SPACE color_space,
85 85 CompressConfig* config_callback) :
86 86 action(a_compress),
87   - buf("DCT uncompressed image"),
88 87 image_width(image_width),
89 88 image_height(image_height),
90 89 components(components),
... ... @@ -95,8 +94,7 @@ class Pl_DCT::Members
95 94  
96 95 // For decompression
97 96 Members() :
98   - action(a_decompress),
99   - buf("DCT compressed image")
  97 + action(a_decompress)
100 98 {
101 99 }
102 100  
... ... @@ -105,7 +103,7 @@ class Pl_DCT::Members
105 103 ~Members() = default;
106 104  
107 105 action_e action;
108   - Pl_Buffer buf;
  106 + std::string buf;
109 107  
110 108 // Used for compression
111 109 JDIMENSION image_width{0};
... ... @@ -163,21 +161,17 @@ Pl_DCT::~Pl_DCT() = default;
163 161 void
164 162 Pl_DCT::write(unsigned char const* data, size_t len)
165 163 {
166   - m->buf.write(data, len);
  164 + if (len > 0) {
  165 + m->buf.append(reinterpret_cast<char const*>(data), len);
  166 + }
167 167 }
168 168  
169 169 void
170 170 Pl_DCT::finish()
171 171 {
172   - m->buf.finish();
173   -
174   - // Using a std::shared_ptr<Buffer> here and passing it into compress and decompress causes a
175   - // memory leak with setjmp/longjmp. Just use a pointer and delete it.
176   - Buffer* b = m->buf.getBuffer();
177   - if (b->getSize() == 0) {
  172 + if (m->buf.empty()) {
178 173 // Special case: empty data will never succeed and probably means we're calling finish a
179 174 // second time from an exception handler.
180   - delete b;
181 175 next()->finish();
182 176 return;
183 177 }
... ... @@ -198,9 +192,9 @@ Pl_DCT::finish()
198 192 if (setjmp(jerr.jmpbuf) == 0) {
199 193 try {
200 194 if (m->action == a_compress) {
201   - compress(reinterpret_cast<void*>(&cinfo_compress), b);
  195 + compress(reinterpret_cast<void*>(&cinfo_compress));
202 196 } else {
203   - decompress(reinterpret_cast<void*>(&cinfo_decompress), b);
  197 + decompress(reinterpret_cast<void*>(&cinfo_decompress));
204 198 }
205 199 } catch (std::exception& e) {
206 200 // Convert an exception back to a longjmp so we can ensure that the right cleanup
... ... @@ -211,7 +205,6 @@ Pl_DCT::finish()
211 205 } else {
212 206 error = true;
213 207 }
214   - delete b;
215 208  
216 209 if (m->action == a_compress) {
217 210 jpeg_destroy_compress(&cinfo_compress);
... ... @@ -312,7 +305,7 @@ term_buffer_source(j_decompress_ptr)
312 305 }
313 306  
314 307 static void
315   -jpeg_buffer_src(j_decompress_ptr cinfo, Buffer* buffer)
  308 +jpeg_buffer_src(j_decompress_ptr cinfo, std::string& buffer)
316 309 {
317 310 cinfo->src = reinterpret_cast<jpeg_source_mgr*>(
318 311 // line-break
... ... @@ -325,12 +318,12 @@ jpeg_buffer_src(j_decompress_ptr cinfo, Buffer* buffer)
325 318 src->skip_input_data = skip_buffer_input_data;
326 319 src->resync_to_restart = jpeg_resync_to_restart; /* use default method */
327 320 src->term_source = term_buffer_source;
328   - src->bytes_in_buffer = buffer->getSize();
329   - src->next_input_byte = buffer->getBuffer();
  321 + src->bytes_in_buffer = buffer.size();
  322 + src->next_input_byte = reinterpret_cast<unsigned char*>(buffer.data());
330 323 }
331 324  
332 325 void
333   -Pl_DCT::compress(void* cinfo_p, Buffer* b)
  326 +Pl_DCT::compress(void* cinfo_p)
334 327 {
335 328 auto* cinfo = reinterpret_cast<jpeg_compress_struct*>(cinfo_p);
336 329  
... ... @@ -361,13 +354,13 @@ Pl_DCT::compress(void* cinfo_p, Buffer* b)
361 354 unsigned int width = cinfo->image_width * QIntC::to_uint(cinfo->input_components);
362 355 size_t expected_size = QIntC::to_size(cinfo->image_height) *
363 356 QIntC::to_size(cinfo->image_width) * QIntC::to_size(cinfo->input_components);
364   - if (b->getSize() != expected_size) {
  357 + if (m->buf.size() != expected_size) {
365 358 throw std::runtime_error(
366   - "Pl_DCT: image buffer size = " + std::to_string(b->getSize()) +
  359 + "Pl_DCT: image buffer size = " + std::to_string(m->buf.size()) +
367 360 "; expected size = " + std::to_string(expected_size));
368 361 }
369 362 JSAMPROW row_pointer[1];
370   - unsigned char* buffer = b->getBuffer();
  363 + auto buffer = reinterpret_cast<unsigned char*>(m->buf.data());
371 364 while (cinfo->next_scanline < cinfo->image_height) {
372 365 // We already verified that the buffer is big enough.
373 366 row_pointer[0] = &buffer[cinfo->next_scanline * width];
... ... @@ -378,7 +371,7 @@ Pl_DCT::compress(void* cinfo_p, Buffer* b)
378 371 }
379 372  
380 373 void
381   -Pl_DCT::decompress(void* cinfo_p, Buffer* b)
  374 +Pl_DCT::decompress(void* cinfo_p)
382 375 {
383 376 auto* cinfo = reinterpret_cast<jpeg_decompress_struct*>(cinfo_p);
384 377  
... ... @@ -395,10 +388,10 @@ Pl_DCT::decompress(void* cinfo_p, Buffer* b)
395 388 cinfo->mem->max_memory_to_use = memory_limit;
396 389 }
397 390  
398   - jpeg_buffer_src(cinfo, b);
  391 + jpeg_buffer_src(cinfo, m->buf);
399 392  
400 393 (void)jpeg_read_header(cinfo, TRUE);
401   - (void)jpeg_calc_output_dimensions(cinfo);
  394 + jpeg_calc_output_dimensions(cinfo);
402 395 unsigned int width = cinfo->output_width * QIntC::to_uint(cinfo->output_components);
403 396 if (memory_limit > 0 &&
404 397 width > (static_cast<unsigned long>(memory_limit) / (20U * cinfo->output_height))) {
... ...