diff options
author | Sebastian Rasmussen <sebras@gmail.com> | 2016-09-28 15:54:05 +0800 |
---|---|---|
committer | Sebastian Rasmussen <sebras@gmail.com> | 2016-10-14 00:11:01 +0800 |
commit | 0a9480a1a98a98d1d3bc75c42380b6bdfd872ff6 (patch) | |
tree | be960e4f01da45a95f093f37e241d9953f65cb22 /source | |
parent | de5084270e282de0290613da70719a0d752d9deb (diff) | |
download | mupdf-0a9480a1a98a98d1d3bc75c42380b6bdfd872ff6.tar.xz |
pnm: Throw exception if image is too big.
Diffstat (limited to 'source')
-rw-r--r-- | source/fitz/load-pnm.c | 138 |
1 files changed, 82 insertions, 56 deletions
diff --git a/source/fitz/load-pnm.c b/source/fitz/load-pnm.c index 0e2350ce..782abbdc 100644 --- a/source/fitz/load-pnm.c +++ b/source/fitz/load-pnm.c @@ -4,8 +4,8 @@ struct info { fz_colorspace *cs; int width, height; - int maxval, depth; - int alpha; + int maxval, bitdepth; + int depth, alpha; char *tupletype; }; @@ -36,6 +36,17 @@ static inline int iseol(int a) return 0; } +static inline int bitdepth_from_maxval(int maxval) +{ + int depth = 0; + while (maxval) + { + maxval >>= 1; + depth++; + } + return depth; +} + static unsigned char * pnm_read_white(fz_context *ctx, unsigned char *p, unsigned char *e, int single_line) { @@ -158,10 +169,20 @@ pnm_ascii_read_image(fz_context *ctx, struct info *pnm, unsigned char *p, unsign p = pnm_read_white(ctx, p, e, 0); p = pnm_read_number(ctx, p, e, &pnm->maxval); p = pnm_read_white(ctx, p, e, 0); - if (pnm->maxval < 0 || pnm->maxval >= 65536) - fz_throw(ctx, FZ_ERROR_GENERIC, "maximum sample value of out range in pnm image: %d", pnm->maxval); } + if (pnm->maxval <= 0 || pnm->maxval >= 65536) + fz_throw(ctx, FZ_ERROR_GENERIC, "maximum sample value of out range in pnm image: %d", pnm->maxval); + + pnm->bitdepth = bitdepth_from_maxval(pnm->maxval); + + if (pnm->height <= 0) + fz_throw(ctx, FZ_ERROR_GENERIC, "image height must be > 0"); + if (pnm->width <= 0) + fz_throw(ctx, FZ_ERROR_GENERIC, "image width must be > 0"); + if (pnm->height > UINT_MAX / pnm->width / fz_colorspace_n(ctx, pnm->cs) / (pnm->bitdepth / 8 + 1)) + fz_throw(ctx, FZ_ERROR_GENERIC, "image too large"); + if (!onlymeta) { unsigned char *dp; @@ -227,10 +248,20 @@ pnm_binary_read_image(fz_context *ctx, struct info *pnm, unsigned char *p, unsig p = pnm_read_white(ctx, p, e, 0); p = pnm_read_number(ctx, p, e, &pnm->maxval); p = pnm_read_white(ctx, p, e, 1); - if (pnm->maxval < 0 || pnm->maxval >= 65536) - fz_throw(ctx, FZ_ERROR_GENERIC, "maximum sample value of out range in pnm image: %d", pnm->maxval); } + if (pnm->maxval <= 0 || pnm->maxval >= 65536) + fz_throw(ctx, FZ_ERROR_GENERIC, "maximum sample value of out range in pnm image: %d", pnm->maxval); + + pnm->bitdepth = bitdepth_from_maxval(pnm->maxval); + + if (pnm->height <= 0) + fz_throw(ctx, FZ_ERROR_GENERIC, "image height must be > 0"); + if (pnm->width <= 0) + fz_throw(ctx, FZ_ERROR_GENERIC, "image width must be > 0"); + if (pnm->height > UINT_MAX / pnm->width / fz_colorspace_n(ctx, pnm->cs) / (pnm->bitdepth / 8 + 1)) + fz_throw(ctx, FZ_ERROR_GENERIC, "image too large"); + if (!onlymeta) { unsigned char *dp; @@ -328,6 +359,8 @@ pam_binary_read_image(fz_context *ctx, struct info *pnm, unsigned char *p, unsig { fz_pixmap *img = NULL; int bitmap = 0; + int minval = 1; + int maxval = 65535; p = pam_binary_read_header(ctx, pnm, p, e); @@ -345,63 +378,37 @@ pam_binary_read_image(fz_context *ctx, struct info *pnm, unsigned char *p, unsig if (!strcmp(pnm->tupletype, "BLACKANDWHITE")) { - if (pnm->depth != 1) - fz_throw(ctx, FZ_ERROR_GENERIC, "depth out of range for b/w pnm image"); + pnm->cs = fz_device_gray(ctx); + maxval = 1; if (pnm->maxval == 1) bitmap = 1; - else if (pnm->maxval < 2 || pnm->maxval > 65535) - fz_throw(ctx, FZ_ERROR_GENERIC, "maxval out of range for grayscale pnm image"); - - pnm->cs = fz_device_gray(ctx); } else if (!strcmp(pnm->tupletype, "GRAYSCALE")) { - if (pnm->maxval < 2 || pnm->maxval > 65535) - fz_throw(ctx, FZ_ERROR_GENERIC, "maxval out of range for grayscale pnm image"); - if (pnm->depth != 1) - fz_throw(ctx, FZ_ERROR_GENERIC, "depth out of range for grayscale pnm image"); pnm->cs = fz_device_gray(ctx); + minval = 2; } else if (!strcmp(pnm->tupletype, "GRAYSCALE_ALPHA")) { - if (pnm->maxval < 2 || pnm->maxval > 65535) - fz_throw(ctx, FZ_ERROR_GENERIC, "maxval out of range for grayscale pnm image with alpha"); - if (pnm->depth != 2) - fz_throw(ctx, FZ_ERROR_GENERIC, "depth out of range for grayscale pnm image with alpha"); pnm->cs = fz_device_gray(ctx); pnm->alpha = 1; + minval = 2; } else if (!strcmp(pnm->tupletype, "RGB")) { - if (pnm->maxval < 1 || pnm->maxval > 65535) - fz_throw(ctx, FZ_ERROR_GENERIC, "maxval out of range for rgb pnm image"); - if (pnm->depth != 3) - fz_throw(ctx, FZ_ERROR_GENERIC, "depth out of range for rgb pnm image"); pnm->cs = fz_device_rgb(ctx); } else if (!strcmp(pnm->tupletype, "RGB_ALPHA")) { - if (pnm->maxval < 1 || pnm->maxval > 65535) - fz_throw(ctx, FZ_ERROR_GENERIC, "maxval out of range for rgb pnm image with alpha"); - if (pnm->depth != 4) - fz_throw(ctx, FZ_ERROR_GENERIC, "depth out of range for rgb pnm image with alpha"); pnm->cs = fz_device_rgb(ctx); pnm->alpha = 1; } else if (!strcmp(pnm->tupletype, "CMYK")) { - if (pnm->maxval < 1 || pnm->maxval > 65535) - fz_throw(ctx, FZ_ERROR_GENERIC, "maxval out of range for cmyk pnm image"); - if (pnm->depth != 4) - fz_throw(ctx, FZ_ERROR_GENERIC, "depth out of range for cmyk pnm image"); pnm->cs = fz_device_cmyk(ctx); } else if (!strcmp(pnm->tupletype, "CMYK_ALPHA")) { - if (pnm->maxval < 1 || pnm->maxval > 65535) - fz_throw(ctx, FZ_ERROR_GENERIC, "maxval out of range for cmyk pnm image with alpha"); - if (pnm->depth != 5) - fz_throw(ctx, FZ_ERROR_GENERIC, "depth out of range for cmyk pnm image with alpha"); pnm->cs = fz_device_cmyk(ctx); pnm->alpha = 1; } @@ -413,6 +420,20 @@ pam_binary_read_image(fz_context *ctx, struct info *pnm, unsigned char *p, unsig fz_free(ctx, pnm->tupletype); + if (pnm->depth != fz_colorspace_n(ctx, pnm->cs) + pnm->alpha) + fz_throw(ctx, FZ_ERROR_GENERIC, "depth out of tuple type range"); + if (pnm->maxval < minval || pnm->maxval > maxval) + fz_throw(ctx, FZ_ERROR_GENERIC, "maxval out of range"); + + pnm->bitdepth = bitdepth_from_maxval(pnm->maxval); + + if (pnm->height <= 0) + fz_throw(ctx, FZ_ERROR_GENERIC, "image height must be > 0"); + if (pnm->width <= 0) + fz_throw(ctx, FZ_ERROR_GENERIC, "image width must be > 0"); + if (pnm->height > UINT_MAX / pnm->width / fz_colorspace_n(ctx, pnm->cs) / (pnm->bitdepth / 8 + 1)) + fz_throw(ctx, FZ_ERROR_GENERIC, "image too large"); + if (!onlymeta) { unsigned char *dp; @@ -471,38 +492,32 @@ pnm_read_image(fz_context *ctx, struct info *pnm, unsigned char *p, size_t total if (!strcmp(signature, "P1")) { - if (!onlymeta) - pnm->cs = fz_device_gray(ctx); + pnm->cs = fz_device_gray(ctx); return pnm_ascii_read_image(ctx, pnm, p, e, onlymeta, 1); } else if (!strcmp(signature, "P2")) { - if (!onlymeta) - pnm->cs = fz_device_gray(ctx); + pnm->cs = fz_device_gray(ctx); return pnm_ascii_read_image(ctx, pnm, p, e, onlymeta, 0); } else if (!strcmp(signature, "P3")) { - if (!onlymeta) - pnm->cs = fz_device_rgb(ctx); + pnm->cs = fz_device_rgb(ctx); return pnm_ascii_read_image(ctx, pnm, p, e, onlymeta, 0); } else if (!strcmp(signature, "P4")) { - if (!onlymeta) - pnm->cs = fz_device_gray(ctx); + pnm->cs = fz_device_gray(ctx); return pnm_binary_read_image(ctx, pnm, p, e, onlymeta, 1); } else if (!strcmp(signature, "P5")) { - if (!onlymeta) - pnm->cs = fz_device_gray(ctx); + pnm->cs = fz_device_gray(ctx); return pnm_binary_read_image(ctx, pnm, p, e, onlymeta, 0); } else if (!strcmp(signature, "P6")) { - if (!onlymeta) - pnm->cs = fz_device_rgb(ctx); + pnm->cs = fz_device_rgb(ctx); return pnm_binary_read_image(ctx, pnm, p, e, onlymeta, 0); } else if (!strcmp(signature, "P7")) @@ -517,7 +532,12 @@ fz_load_pnm(fz_context *ctx, unsigned char *p, size_t total) fz_pixmap *img; struct info pnm = { 0 }; - img = pnm_read_image(ctx, &pnm, p, total, 0); + fz_try(ctx) + img = pnm_read_image(ctx, &pnm, p, total, 0); + fz_always(ctx) + fz_drop_colorspace(ctx, pnm.cs); + fz_catch(ctx) + fz_rethrow(ctx); return img; } @@ -527,11 +547,17 @@ fz_load_pnm_info(fz_context *ctx, unsigned char *p, size_t total, int *wp, int * { struct info pnm = { 0 }; - pnm_read_image(ctx, &pnm, p, total, 1); - - *cspacep = pnm.cs; - *wp = pnm.width; - *hp = pnm.height; - *xresp = 72; - *yresp = 72; + fz_try(ctx) + { + pnm_read_image(ctx, &pnm, p, total, 1); + *cspacep = pnm.cs; + *wp = pnm.width; + *hp = pnm.height; + *xresp = 72; + *yresp = 72; + } + fz_always(ctx) + fz_drop_colorspace(ctx, pnm.cs); + fz_catch(ctx) + fz_rethrow(ctx); } |