2
1
mirror of https://github.com/qpdf/qpdf.git synced 2024-12-22 10:58:58 +00:00

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.
This commit is contained in:
m-holger 2024-07-09 20:55:51 +01:00
parent 7172dbd4e0
commit 2b6500ea17

View File

@ -35,6 +35,16 @@ error_handler(j_common_ptr cinfo)
longjmp(jerr->jmpbuf, 1);
}
static void
emit_message(j_common_ptr cinfo, int msg_level)
{
if (msg_level == -1) {
auto* jerr = reinterpret_cast<qpdf_jpeg_error_mgr*>(cinfo->err);
jerr->msg = "Pl_DCT::decompress: JPEG data is corrupt";
longjmp(jerr->jmpbuf, 1);
}
}
Pl_DCT::Members::Members() :
action(a_decompress),
buf("DCT compressed image")
@ -116,6 +126,9 @@ Pl_DCT::finish()
cinfo_compress.err = jpeg_std_error(&(jerr.pub));
cinfo_decompress.err = jpeg_std_error(&(jerr.pub));
jerr.pub.error_exit = error_handler;
if (m->action == a_decompress && throw_on_corrupt_data) {
jerr.pub.emit_message = emit_message;
}
bool error = false;
// 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)
jpeg_buffer_src(cinfo, b);
(void)jpeg_read_header(cinfo, TRUE);
if (throw_on_corrupt_data && cinfo->err->num_warnings > 0) {
// err->num_warnings is the number of corrupt data warnings emitted.
// err->msg_code could also be the code of an informational message.
throw std::runtime_error("Pl_DCT::decompress: JPEG data is corrupt");
}
(void)jpeg_calc_output_dimensions(cinfo);
unsigned int width = cinfo->output_width * QIntC::to_uint(cinfo->output_components);
if (memory_limit > 0 &&
@ -336,14 +344,10 @@ Pl_DCT::decompress(void* cinfo_p, Buffer* b)
(*cinfo->mem->alloc_sarray)(reinterpret_cast<j_common_ptr>(cinfo), JPOOL_IMAGE, width, 1);
(void)jpeg_start_decompress(cinfo);
while (cinfo->output_scanline < cinfo->output_height &&
(!throw_on_corrupt_data || cinfo->err->num_warnings == 0)) {
while (cinfo->output_scanline < cinfo->output_height) {
(void)jpeg_read_scanlines(cinfo, buffer, 1);
getNext()->write(buffer[0], width * sizeof(buffer[0][0]));
}
(void)jpeg_finish_decompress(cinfo);
if (throw_on_corrupt_data && cinfo->err->num_warnings > 0) {
throw std::runtime_error("Pl_DCT::decompress: JPEG data is corrupt");
}
getNext()->finish();
}