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