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:
parent
7172dbd4e0
commit
2b6500ea17
@ -35,6 +35,16 @@ error_handler(j_common_ptr cinfo)
|
|||||||
longjmp(jerr->jmpbuf, 1);
|
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() :
|
Pl_DCT::Members::Members() :
|
||||||
action(a_decompress),
|
action(a_decompress),
|
||||||
buf("DCT compressed image")
|
buf("DCT compressed image")
|
||||||
@ -116,6 +126,9 @@ Pl_DCT::finish()
|
|||||||
cinfo_compress.err = jpeg_std_error(&(jerr.pub));
|
cinfo_compress.err = jpeg_std_error(&(jerr.pub));
|
||||||
cinfo_decompress.err = jpeg_std_error(&(jerr.pub));
|
cinfo_decompress.err = jpeg_std_error(&(jerr.pub));
|
||||||
jerr.pub.error_exit = error_handler;
|
jerr.pub.error_exit = error_handler;
|
||||||
|
if (m->action == a_decompress && throw_on_corrupt_data) {
|
||||||
|
jerr.pub.emit_message = emit_message;
|
||||||
|
}
|
||||||
|
|
||||||
bool error = false;
|
bool error = false;
|
||||||
// The jpeg library is a "C" library, so we use setjmp and longjmp for exception handling.
|
// 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);
|
jpeg_buffer_src(cinfo, b);
|
||||||
|
|
||||||
(void)jpeg_read_header(cinfo, TRUE);
|
(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);
|
(void)jpeg_calc_output_dimensions(cinfo);
|
||||||
unsigned int width = cinfo->output_width * QIntC::to_uint(cinfo->output_components);
|
unsigned int width = cinfo->output_width * QIntC::to_uint(cinfo->output_components);
|
||||||
if (memory_limit > 0 &&
|
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);
|
(*cinfo->mem->alloc_sarray)(reinterpret_cast<j_common_ptr>(cinfo), JPOOL_IMAGE, width, 1);
|
||||||
|
|
||||||
(void)jpeg_start_decompress(cinfo);
|
(void)jpeg_start_decompress(cinfo);
|
||||||
while (cinfo->output_scanline < cinfo->output_height &&
|
while (cinfo->output_scanline < cinfo->output_height) {
|
||||||
(!throw_on_corrupt_data || cinfo->err->num_warnings == 0)) {
|
|
||||||
(void)jpeg_read_scanlines(cinfo, buffer, 1);
|
(void)jpeg_read_scanlines(cinfo, buffer, 1);
|
||||||
getNext()->write(buffer[0], width * sizeof(buffer[0][0]));
|
getNext()->write(buffer[0], width * sizeof(buffer[0][0]));
|
||||||
}
|
}
|
||||||
(void)jpeg_finish_decompress(cinfo);
|
(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();
|
getNext()->finish();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user