JPEGLoader: Fix infinite loop on incomplete data

If the image data to decode is incomplete, e.g. a corrupt image missing
its last scanlines the decoder would previously keep looping for ever.
By breaking out of the loop if no more scanlines were produced we can at
least display the partial image up to that point.
This commit is contained in:
0x4261756D 2024-10-12 17:53:41 +02:00 committed by Andreas Kling
parent 02da288413
commit 6923008a55
Notes: github-actions[bot] 2024-10-12 17:21:54 +00:00

View file

@ -90,18 +90,29 @@ ErrorOr<void> JPEGLoadingContext::decode()
}
jpeg_start_decompress(&cinfo);
bool could_read_all_scanlines = true;
if (cinfo.out_color_space == JCS_EXT_BGRX) {
rgb_bitmap = TRY(Gfx::Bitmap::create(Gfx::BitmapFormat::BGRx8888, { static_cast<int>(cinfo.output_width), static_cast<int>(cinfo.output_height) }));
while (cinfo.output_scanline < cinfo.output_height) {
auto* row_ptr = (u8*)rgb_bitmap->scanline(cinfo.output_scanline);
jpeg_read_scanlines(&cinfo, &row_ptr, 1);
auto out_size = jpeg_read_scanlines(&cinfo, &row_ptr, 1);
if (cinfo.output_scanline < cinfo.output_height && out_size == 0) {
dbgln("JPEG Warning: Decoding produced no more scanlines in scanline {}/{}.", cinfo.output_scanline, cinfo.output_height);
could_read_all_scanlines = false;
break;
}
}
} else {
cmyk_bitmap = TRY(CMYKBitmap::create_with_size({ static_cast<int>(cinfo.output_width), static_cast<int>(cinfo.output_height) }));
while (cinfo.output_scanline < cinfo.output_height) {
auto* row_ptr = (u8*)cmyk_bitmap->scanline(cinfo.output_scanline);
jpeg_read_scanlines(&cinfo, &row_ptr, 1);
auto out_size = jpeg_read_scanlines(&cinfo, &row_ptr, 1);
if (cinfo.output_scanline < cinfo.output_height && out_size == 0) {
dbgln("JPEG Warning: Decoding produced no more scanlines in scanline {}/{}.", cinfo.output_scanline, cinfo.output_height);
could_read_all_scanlines = false;
break;
}
}
}
@ -113,7 +124,10 @@ ErrorOr<void> JPEGLoadingContext::decode()
free(icc_data_ptr);
}
if (could_read_all_scanlines)
jpeg_finish_decompress(&cinfo);
else
jpeg_abort_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
if (cmyk_bitmap && !rgb_bitmap)