@@ -19,6 +19,14 @@ typedef struct {
1919} gif_data_t ;
2020#endif
2121
22+ #ifdef HAVE_JPEG
23+ #include < setjmp.h>
24+
25+ struct canvas_jpeg_error_mgr : jpeg_error_mgr {
26+ jmp_buf setjmp_buffer;
27+ };
28+ #endif
29+
2230/*
2331 * Read closure used by loadFromBuffer.
2432 */
@@ -752,6 +760,17 @@ Image::decodeJPEGIntoSurface(jpeg_decompress_struct *args) {
752760 return CAIRO_STATUS_SUCCESS;
753761}
754762
763+ /*
764+ * Callback to recover from jpeg errors
765+ */
766+
767+ METHODDEF (void ) canvas_jpeg_error_exit (j_common_ptr cinfo) {
768+ canvas_jpeg_error_mgr *cjerr = static_cast <canvas_jpeg_error_mgr*>(cinfo->err );
769+
770+ // Return control to the setjmp point
771+ longjmp (cjerr->setjmp_buffer , 1 );
772+ }
773+
755774#if CAIRO_VERSION_MINOR >= 10
756775
757776/*
@@ -764,8 +783,19 @@ Image::decodeJPEGBufferIntoMimeSurface(uint8_t *buf, unsigned len) {
764783 // TODO: remove this duplicate logic
765784 // JPEG setup
766785 struct jpeg_decompress_struct args;
767- struct jpeg_error_mgr err;
786+ struct canvas_jpeg_error_mgr err;
787+
768788 args.err = jpeg_std_error (&err);
789+ args.err ->error_exit = canvas_jpeg_error_exit;
790+
791+ // Establish the setjmp return context for canvas_jpeg_error_exit to use
792+ if (setjmp (err.setjmp_buffer )) {
793+ // If we get here, the JPEG code has signaled an error.
794+ // We need to clean up the JPEG object, close the input file, and return.
795+ jpeg_destroy_decompress (&args);
796+ return CAIRO_STATUS_READ_ERROR;
797+ }
798+
769799 jpeg_create_decompress (&args);
770800
771801 jpeg_mem_src (&args, buf, len);
@@ -858,8 +888,19 @@ Image::loadJPEGFromBuffer(uint8_t *buf, unsigned len) {
858888 // TODO: remove this duplicate logic
859889 // JPEG setup
860890 struct jpeg_decompress_struct args;
861- struct jpeg_error_mgr err;
891+ struct canvas_jpeg_error_mgr err;
892+
862893 args.err = jpeg_std_error (&err);
894+ args.err ->error_exit = canvas_jpeg_error_exit;
895+
896+ // Establish the setjmp return context for canvas_jpeg_error_exit to use
897+ if (setjmp (err.setjmp_buffer )) {
898+ // If we get here, the JPEG code has signaled an error.
899+ // We need to clean up the JPEG object, close the input file, and return.
900+ jpeg_destroy_decompress (&args);
901+ return CAIRO_STATUS_READ_ERROR;
902+ }
903+
863904 jpeg_create_decompress (&args);
864905
865906 jpeg_mem_src (&args, buf, len);
@@ -883,8 +924,19 @@ Image::loadJPEG(FILE *stream) {
883924 if (data_mode == DATA_IMAGE) { // Can lazily read in the JPEG.
884925 // JPEG setup
885926 struct jpeg_decompress_struct args;
886- struct jpeg_error_mgr err;
927+ struct canvas_jpeg_error_mgr err;
928+
887929 args.err = jpeg_std_error (&err);
930+ args.err ->error_exit = canvas_jpeg_error_exit;
931+
932+ // Establish the setjmp return context for canvas_jpeg_error_exit to use
933+ if (setjmp (err.setjmp_buffer )) {
934+ // If we get here, the JPEG code has signaled an error.
935+ // We need to clean up the JPEG object, close the input file, and return.
936+ jpeg_destroy_decompress (&args);
937+ return CAIRO_STATUS_READ_ERROR;
938+ }
939+
888940 jpeg_create_decompress (&args);
889941
890942 jpeg_stdio_src (&args, stream);
0 commit comments