fix jpeg decode for corrupt jpeg data

This commit is contained in:
houzh 2023-12-06 16:58:07 +08:00
parent 98a51c9349
commit 2fb8fd05bd
2 changed files with 22 additions and 8 deletions

View File

@ -49,6 +49,7 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <setjmp.h>
#include <cairo.h>
#include <jpeglib.h>
#include <turbojpeg.h>
@ -104,7 +105,7 @@ static boolean fill_buffer (j_decompress_ptr cinfo) {
src->pub.next_input_byte = src->buffer;
src->pub.bytes_in_buffer = src->stream->gcount();// How many yo could read
return (!src->stream->eof())||src->pub.bytes_in_buffer;
return (!src->stream->eof())&&src->pub.bytes_in_buffer;
}
static void skip (j_decompress_ptr cinfo, long num_bytes) {
@ -358,14 +359,27 @@ cairo_status_t cairo_image_surface_write_to_jpeg(cairo_surface_t *sfc, const cha
* @return Returns a pointer to a cairo_surface_t structure. It should be
* checked with cairo_surface_status() for errors. */
#define MIN(a,b)((a)>(b)?(b):(a))
struct decoder_error_mgr {
struct jpeg_error_mgr pub; // "public" fields for IJG library
jmp_buf setjmp_buffer; // For handling catastropic errors
};
static void handle_jpeg_error(j_common_ptr cinfo) {
struct decoder_error_mgr *err = (struct decoder_error_mgr*)(cinfo->err);
longjmp(err->setjmp_buffer, 1);
}
cairo_surface_t *cairo_image_surface_create_from_jpeg_stdstream(std::istream&is) {
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
struct decoder_error_mgr jerr;
JSAMPROW row_pointer[1];
cairo_surface_t *sfc;
// initialize jpeg decompression structures
cinfo.err = jpeg_std_error(&jerr);
if (setjmp(jerr.setjmp_buffer)){
LOGE("JPEG read/write error");
return sfc;
}
cinfo.err = jpeg_std_error(&jerr.pub);
jerr.pub.error_exit = handle_jpeg_error;
jpeg_create_decompress(&cinfo);
make_jpeg_stream(&cinfo,&is);
(void) jpeg_read_header(&cinfo, TRUE);
@ -397,7 +411,7 @@ cairo_surface_t *cairo_image_surface_create_from_jpeg_stdstream(std::istream&is)
unsigned char *row_address = cairo_image_surface_get_data(sfc) +
(cinfo.output_scanline * cairo_image_surface_get_stride(sfc));
row_pointer[0] = row_address;
(void) jpeg_read_scanlines(&cinfo, row_pointer, 1);
if(0==jpeg_read_scanlines(&cinfo, row_pointer, 1))break;
#ifndef LIBJPEG_TURBO_VERSION
pix_conv(row_address, 4, row_address, 3, cinfo.output_width);
#endif

View File

@ -360,7 +360,7 @@ static const char*pakGetFileType(const char*filebuf) {
}
using namespace std::chrono;
RefPtr<ImageSurface> ImageSurface::create_from_stream(std::istream& stream){
RefPtr<ImageSurface>ImageSurface:: create_from_stream(std::istream& stream){
unsigned char head[8]={0};
RefPtr<ImageSurface>img;
steady_clock::time_point t2,t1=steady_clock::now();
@ -377,9 +377,9 @@ RefPtr<ImageSurface> ImageSurface::create_from_stream(std::istream& stream){
cobject = cairo_image_surface_create_from_turbojpeg_stdstream(stream);
#endif
#ifdef ENABLE_JPEG
if(nullptr==cobject )cobject=cairo_image_surface_create_from_jpeg_stdstream(stream);
if(nullptr==cobject )cobject = cairo_image_surface_create_from_jpeg_stdstream(stream);
#endif
img=RefPtr<ImageSurface>(new ImageSurface(cobject, true /* has reference */));
if(cobject) img = RefPtr<ImageSurface>(new ImageSurface(cobject, true /* has reference */));
}else if(memcmp("png",ftype,3)==0){
img=create_from_png(stream_read,&stream);
}/*else if(memcmp("bmp",ftype,3)==0){