Commit 2b6500ea176b5d704439401f9cbd40ea733dfe13

Authored by m-holger
1 parent 7172dbd4

In Pl_DCT::decompress refactor handling of corrupt data

If throw_on_corrupt is set, use a custom implementation of libjeg's
emit_message procedure to throw an exception when the first corrupt data
warning is encountered.
Showing 1 changed file with 14 additions and 10 deletions
libqpdf/Pl_DCT.cc
... ... @@ -35,6 +35,16 @@ error_handler(j_common_ptr cinfo)
35 35 longjmp(jerr->jmpbuf, 1);
36 36 }
37 37  
  38 +static void
  39 +emit_message(j_common_ptr cinfo, int msg_level)
  40 +{
  41 + if (msg_level == -1) {
  42 + auto* jerr = reinterpret_cast<qpdf_jpeg_error_mgr*>(cinfo->err);
  43 + jerr->msg = "Pl_DCT::decompress: JPEG data is corrupt";
  44 + longjmp(jerr->jmpbuf, 1);
  45 + }
  46 +}
  47 +
38 48 Pl_DCT::Members::Members() :
39 49 action(a_decompress),
40 50 buf("DCT compressed image")
... ... @@ -116,6 +126,9 @@ Pl_DCT::finish()
116 126 cinfo_compress.err = jpeg_std_error(&(jerr.pub));
117 127 cinfo_decompress.err = jpeg_std_error(&(jerr.pub));
118 128 jerr.pub.error_exit = error_handler;
  129 + if (m->action == a_decompress && throw_on_corrupt_data) {
  130 + jerr.pub.emit_message = emit_message;
  131 + }
119 132  
120 133 bool error = false;
121 134 // The jpeg library is a "C" library, so we use setjmp and longjmp for exception handling.
... ... @@ -319,11 +332,6 @@ Pl_DCT::decompress(void* cinfo_p, Buffer* b)
319 332 jpeg_buffer_src(cinfo, b);
320 333  
321 334 (void)jpeg_read_header(cinfo, TRUE);
322   - if (throw_on_corrupt_data && cinfo->err->num_warnings > 0) {
323   - // err->num_warnings is the number of corrupt data warnings emitted.
324   - // err->msg_code could also be the code of an informational message.
325   - throw std::runtime_error("Pl_DCT::decompress: JPEG data is corrupt");
326   - }
327 335 (void)jpeg_calc_output_dimensions(cinfo);
328 336 unsigned int width = cinfo->output_width * QIntC::to_uint(cinfo->output_components);
329 337 if (memory_limit > 0 &&
... ... @@ -336,14 +344,10 @@ Pl_DCT::decompress(void* cinfo_p, Buffer* b)
336 344 (*cinfo->mem->alloc_sarray)(reinterpret_cast<j_common_ptr>(cinfo), JPOOL_IMAGE, width, 1);
337 345  
338 346 (void)jpeg_start_decompress(cinfo);
339   - while (cinfo->output_scanline < cinfo->output_height &&
340   - (!throw_on_corrupt_data || cinfo->err->num_warnings == 0)) {
  347 + while (cinfo->output_scanline < cinfo->output_height) {
341 348 (void)jpeg_read_scanlines(cinfo, buffer, 1);
342 349 getNext()->write(buffer[0], width * sizeof(buffer[0][0]));
343 350 }
344 351 (void)jpeg_finish_decompress(cinfo);
345   - if (throw_on_corrupt_data && cinfo->err->num_warnings > 0) {
346   - throw std::runtime_error("Pl_DCT::decompress: JPEG data is corrupt");
347   - }
348 352 getNext()->finish();
349 353 }
... ...