Commit 2b6500ea176b5d704439401f9cbd40ea733dfe13
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 | } | ... | ... |