diff --git a/libopenjpeg/jp2.c b/libopenjpeg/jp2.c index 6d1b439c..d3322603 100644 --- a/libopenjpeg/jp2.c +++ b/libopenjpeg/jp2.c @@ -737,6 +737,84 @@ opj_bool jp2_read_jp2h(opj_jp2_t *jp2, opj_cio_t *cio, opj_jp2_color_t *color) }/* jp2_read_jp2h() */ +static opj_bool opj_jp2_check_color(opj_image_t *image, opj_jp2_color_t *color, opj_common_ptr cinfo) +{ + int i; + + /* testcase 4149.pdf.SIGSEGV.cf7.3501 */ + if (color->jp2_cdef) { + opj_jp2_cdef_info_t *info = color->jp2_cdef->info; + int n = color->jp2_cdef->n; + + for (i = 0; i < n; i++) { + if (info[i].cn >= image->numcomps) { + opj_event_msg(cinfo, EVT_ERROR, "Invalid component index %d (>= %d).\n", info[i].cn, image->numcomps); + return OPJ_FALSE; + } + if (info[i].asoc > 0 && (info[i].asoc - 1) >= image->numcomps) { + opj_event_msg(cinfo, EVT_ERROR, "Invalid component index %d (>= %d).\n", info[i].asoc - 1, image->numcomps); + return OPJ_FALSE; + } + } + } + + /* testcases 451.pdf.SIGSEGV.f4c.3723, 451.pdf.SIGSEGV.5b5.3723 and + 66ea31acbb0f23a2bbc91f64d69a03f5_signal_sigsegv_13937c0_7030_5725.pdf */ + if (color->jp2_pclr && color->jp2_pclr->cmap) { + int nr_channels = color->jp2_pclr->nr_channels; + opj_jp2_cmap_comp_t *cmap = color->jp2_pclr->cmap; + opj_bool *pcol_usage, is_sane = OPJ_TRUE; + + /* verify that all original components match an existing one */ + for (i = 0; i < nr_channels; i++) { + if (cmap[i].cmp >= image->numcomps) { + opj_event_msg(cinfo, EVT_ERROR, "Invalid component index %d (>= %d).\n", cmap[i].cmp, image->numcomps); + is_sane = OPJ_FALSE; + } + } + + pcol_usage = opj_calloc(nr_channels, sizeof(opj_bool)); + if (!pcol_usage) { + opj_event_msg(cinfo, EVT_ERROR, "Unexpected OOM.\n"); + return OPJ_FALSE; + } + /* verify that no component is targeted more than once */ + for (i = 0; i < nr_channels; i++) { + int pcol = cmap[i].pcol; + assert(cmap[i].mtyp == 0 || cmap[i].mtyp == 1); + if (pcol >= nr_channels) { + opj_event_msg(cinfo, EVT_ERROR, "Invalid component/palette index for direct mapping %d.\n", pcol); + is_sane = OPJ_FALSE; + } + else if (pcol_usage[pcol] && cmap[i].mtyp == 1) { + opj_event_msg(cinfo, EVT_ERROR, "Component %d is mapped twice.\n", pcol); + is_sane = OPJ_FALSE; + } + else if (cmap[i].mtyp == 0 && cmap[i].pcol != 0) { + /* I.5.3.5 PCOL: If the value of the MTYP field for this channel is 0, then + * the value of this field shall be 0. */ + opj_event_msg(cinfo, EVT_ERROR, "Direct use at #%d however pcol=%d.\n", i, pcol); + is_sane = OPJ_FALSE; + } + else + pcol_usage[pcol] = OPJ_TRUE; + } + /* verify that all components are targeted at least once */ + for (i = 0; i < nr_channels; i++) { + if (!pcol_usage[i] && cmap[i].mtyp != 0) { + opj_event_msg(cinfo, EVT_ERROR, "Component %d doesn't have a mapping.\n", i); + is_sane = OPJ_FALSE; + } + } + opj_free(pcol_usage); + if (!is_sane) { + return OPJ_FALSE; + } + } + + return OPJ_TRUE; +} + opj_image_t* opj_jp2_decode(opj_jp2_t *jp2, opj_cio_t *cio, opj_codestream_info_t *cstr_info) { @@ -770,6 +848,10 @@ opj_image_t* opj_jp2_decode(opj_jp2_t *jp2, opj_cio_t *cio, } if (!jp2->ignore_pclr_cmap_cdef){ + if (!opj_jp2_check_color(image, &color, cinfo)) { + opj_event_msg(cinfo, EVT_ERROR, "Failed to decode PCRL box\n"); + return NULL; + } /* Set Image Color Space */ if (jp2->enumcs == 16) diff --git a/libopenjpeg/tcd.c b/libopenjpeg/tcd.c index c05b13df..77df6715 100644 --- a/libopenjpeg/tcd.c +++ b/libopenjpeg/tcd.c @@ -32,6 +32,7 @@ #define _ISOC99_SOURCE /* lrintf is C99 */ #include "opj_includes.h" +#include void tcd_dump(FILE *fd, opj_tcd_t *tcd, opj_tcd_image_t * img) { int tileno, compno, resno, bandno, precno;/*, cblkno;*/ @@ -1493,10 +1494,18 @@ opj_bool tcd_decode_tile(opj_tcd_t *tcd, unsigned char *src, int len, int tileno int tw = tilec->x1 - tilec->x0; int w = imagec->w; + int i, j; int offset_x = int_ceildivpow2(imagec->x0, imagec->factor); int offset_y = int_ceildivpow2(imagec->y0, imagec->factor); + if( res->x0 > offset_x || offset_x > res->x1 + || res->y0 > offset_y || offset_y > res->y1 ) + { + opj_event_msg(tcd->cinfo, EVT_ERROR, "Impossible offsets\n"); + return OPJ_FALSE; + } + assert( res->x0 <= offset_x && offset_x <= res->x1 ); + assert( res->y0 <= offset_y && offset_y <= res->y1 ); - int i, j; if(!imagec->data){ imagec->data = (int*) opj_malloc(imagec->w * imagec->h * sizeof(int)); } @@ -1510,6 +1519,7 @@ opj_bool tcd_decode_tile(opj_tcd_t *tcd, unsigned char *src, int len, int tileno for(i = res->x0; i < res->x1; ++i) { int v = tilec->data[i - res->x0 + (j - res->y0) * tw]; v += adjust; + /*assert( (i - offset_x) + (j - offset_y) * w >= 0 );*/ imagec->data[(i - offset_x) + (j - offset_y) * w] = int_clamp(v, min, max); } } @@ -1519,6 +1529,7 @@ opj_bool tcd_decode_tile(opj_tcd_t *tcd, unsigned char *src, int len, int tileno float tmp = ((float*)tilec->data)[i - res->x0 + (j - res->y0) * tw]; int v = lrintf(tmp); v += adjust; + /*assert( (i - offset_x) + (j - offset_y) * w >= 0 );*/ imagec->data[(i - offset_x) + (j - offset_y) * w] = int_clamp(v, min, max); } }