diff options
author | Robin Watts <robin.watts@artifex.com> | 2012-12-03 13:14:18 +0000 |
---|---|---|
committer | Robin Watts <robin.watts@artifex.com> | 2012-12-03 16:28:52 +0000 |
commit | f6b64c3e6e3c91f71c4febe35037a1cb57fe5461 (patch) | |
tree | 52c7c7407156d03ba06f7b86b21854da6e5d5a18 | |
parent | 62320204bf806686dd07d27d8110670914a874ca (diff) | |
download | mupdf-f6b64c3e6e3c91f71c4febe35037a1cb57fe5461.tar.xz |
Fix potential infinite loop in jpeg error handling code.
Turns out that jpeg_finish_decompress can throw errors, hence
can cause an infinite loop. This is fixed here by changing the
jpeg error code to be fz_throw based.
Thanks to zeniko for this patch.
This highlights something that I hadn't fully appreciated before;
anything that throws in a fz_always region will reenter that region.
I think I have a way to fix this so that any throws in the
fz_always region go immediately to the fz_catch.
-rw-r--r-- | fitz/image_jpeg.c | 34 |
1 files changed, 16 insertions, 18 deletions
diff --git a/fitz/image_jpeg.c b/fitz/image_jpeg.c index aedd48c8..925ecbfb 100644 --- a/fitz/image_jpeg.c +++ b/fitz/image_jpeg.c @@ -3,18 +3,13 @@ #include <jpeglib.h> #include <setjmp.h> -struct jpeg_error_mgr_jmp +static void error_exit(j_common_ptr cinfo) { - struct jpeg_error_mgr super; - jmp_buf env; char msg[JMSG_LENGTH_MAX]; -}; + fz_context *ctx = (fz_context *)cinfo->client_data; -static void error_exit(j_common_ptr cinfo) -{ - struct jpeg_error_mgr_jmp *err = (struct jpeg_error_mgr_jmp *)cinfo->err; - cinfo->err->format_message(cinfo, err->msg); - longjmp(err->env, 1); + cinfo->err->format_message(cinfo, msg); + fz_throw(ctx, "jpeg error: %s", msg); } static void init_source(j_decompress_ptr cinfo) @@ -53,7 +48,7 @@ fz_pixmap * fz_load_jpeg(fz_context *ctx, unsigned char *rbuf, int rlen) { struct jpeg_decompress_struct cinfo; - struct jpeg_error_mgr_jmp err; + struct jpeg_error_mgr err; struct jpeg_source_mgr src; unsigned char *row[1], *sp, *dp; fz_colorspace *colorspace; @@ -68,13 +63,8 @@ fz_load_jpeg(fz_context *ctx, unsigned char *rbuf, int rlen) fz_try(ctx) { - if (setjmp(err.env)) - { - fz_throw(ctx, "jpeg error: %s", err.msg); - } - - cinfo.err = jpeg_std_error(&err.super); - err.super.error_exit = error_exit; + cinfo.err = jpeg_std_error(&err); + err.error_exit = error_exit; jpeg_create_decompress(&cinfo); @@ -136,7 +126,15 @@ fz_load_jpeg(fz_context *ctx, unsigned char *rbuf, int rlen) { fz_free(ctx, row[0]); row[0] = NULL; - jpeg_finish_decompress(&cinfo); + fz_try(ctx) + { + /* Annoyingly, jpeg_finish_decompress can throw */ + jpeg_finish_decompress(&cinfo); + } + fz_catch(ctx) + { + /* Ignore any errors here */ + } jpeg_destroy_decompress(&cinfo); } fz_catch(ctx) |