diff --git a/libopenjpeg/cio.c b/libopenjpeg/cio.c index 6fefde7..f15970b 100644 --- a/libopenjpeg/cio.c +++ b/libopenjpeg/cio.c @@ -107,6 +107,11 @@ int OPJ_CALLCONV cio_tell(opj_cio_t *cio) { * pos : position, in number of bytes, from the beginning of the stream */ void OPJ_CALLCONV cio_seek(opj_cio_t *cio, int pos) { + if ((cio->start + pos) > cio->end) { + opj_event_msg(cio->cinfo, EVT_ERROR, "error: trying to seek past the end of the codestream (start = %d, change = %d, end = %d\n", cio->start, pos, cio->end); + cio->bp = cio->end; + return; + } cio->bp = cio->start + pos; } @@ -114,6 +119,7 @@ void OPJ_CALLCONV cio_seek(opj_cio_t *cio, int pos) { * Number of bytes left before the end of the stream. */ int cio_numbytesleft(opj_cio_t *cio) { + assert((cio->end - cio->bp) >= 0); return cio->end - cio->bp; } @@ -191,6 +197,11 @@ unsigned int cio_read(opj_cio_t *cio, int n) { */ void cio_skip(opj_cio_t *cio, int n) { assert((cio->bp + n) >= cio->bp); + if (((cio->bp + n) < cio->start) || ((cio->bp + n) > cio->end)) { + opj_event_msg(cio->cinfo, EVT_ERROR, "error: trying to skip bytes past the end of the codestream (current = %d, change = %d, end = %d\n", cio->bp, n, cio->end); + cio->bp = cio->end; + return; + } cio->bp += n; } diff --git a/libopenjpeg/j2k.c b/libopenjpeg/j2k.c index 555fe54..d640139 100644 --- a/libopenjpeg/j2k.c +++ b/libopenjpeg/j2k.c @@ -476,7 +476,7 @@ static void j2k_read_siz(opj_j2k_t *j2k) { image->comps = (opj_image_comp_t*) opj_calloc(image->numcomps, sizeof(opj_image_comp_t)); for (i = 0; i < image->numcomps; i++) { - int tmp, w, h; + int tmp/*, w, h*/; tmp = cio_read(cio, 1); /* Ssiz_i */ image->comps[i].prec = (tmp & 0x7f) + 1; image->comps[i].sgnd = tmp >> 7; @@ -519,8 +519,8 @@ static void j2k_read_siz(opj_j2k_t *j2k) { } /* TODO: unused ? */ - w = int_ceildiv(image->x1 - image->x0, image->comps[i].dx); - h = int_ceildiv(image->y1 - image->y0, image->comps[i].dy); +/* w = int_ceildiv(image->x1 - image->x0, image->comps[i].dx); + h = int_ceildiv(image->y1 - image->y0, image->comps[i].dy);*/ image->comps[i].resno_decoded = 0; /* number of resolution decoded */ image->comps[i].factor = cp->reduce; /* reducing factor per component */ @@ -2014,6 +2014,12 @@ opj_image_t* j2k_decode(opj_j2k_t *j2k, opj_cio_t *cio, opj_codestream_info_t *c j2k_read_eoc(j2k); } + if (j2k->state & J2K_STATE_ERR) { + opj_event_msg(cinfo, EVT_ERROR, "Error in decoding tile\n"); + opj_image_destroy(image); + return NULL; + } + if (j2k->state != J2K_STATE_MT) { opj_event_msg(cinfo, EVT_WARNING, "Incomplete bitstream\n"); } diff --git a/libopenjpeg/jp2.c b/libopenjpeg/jp2.c index 0ecd5cb..562b303 100644 --- a/libopenjpeg/jp2.c +++ b/libopenjpeg/jp2.c @@ -674,6 +674,17 @@ opj_bool jp2_read_jp2h(opj_jp2_t *jp2, opj_cio_t *cio, opj_jp2_color_t *color) return OPJ_FALSE; jp2h_end = box.init_pos + box.length; + { + int curpos = cio_tell(cio); + cio_seek(cio, box.init_pos); + cio_skip(cio, box.length); + if ((cio_tell(cio) - box.init_pos) != box.length) { + opj_event_msg(cinfo, EVT_ERROR, "Box size exceeds size of codestream (expected: %d, real: %d)\n", box.length, (cio_tell(cio) - box.init_pos)); + return OPJ_FALSE; + } + cio_seek(cio, curpos); + } + if (jp2->bpc == 255) { if (!jp2_read_bpcc(jp2, cio)) @@ -871,6 +882,13 @@ static opj_bool jp2_read_ftyp(opj_jp2_t *jp2, opj_cio_t *cio) { jp2->numcl = (box.length - 16) / 4; jp2->cl = (unsigned int *) opj_malloc(jp2->numcl * sizeof(unsigned int)); + if (cio_numbytesleft(cio) < ((int)jp2->numcl * 4)) { + opj_event_msg(cinfo, EVT_ERROR, "Not enough bytes in FTYP Box " + "(expected %d, but only %d left)\n", + ((int)jp2->numcl * 4), cio_numbytesleft(cio)); + return OPJ_FALSE; + } + for (i = 0; i < (int)jp2->numcl; i++) { jp2->cl[i] = cio_read(cio, 4); /* CLi */ } diff --git a/libopenjpeg/opj_malloc.h b/libopenjpeg/opj_malloc.h index 9e4af23..87d7b5c 100644 --- a/libopenjpeg/opj_malloc.h +++ b/libopenjpeg/opj_malloc.h @@ -48,7 +48,7 @@ Allocate an uninitialized memory block #ifdef ALLOC_PERF_OPT void * OPJ_CALLCONV opj_malloc(size_t size); #else -#define opj_malloc(size) malloc(size) +#define opj_malloc(size) calloc(1, size) #endif /** diff --git a/libopenjpeg/t2.c b/libopenjpeg/t2.c index cae29f0..65d5d9e 100644 --- a/libopenjpeg/t2.c +++ b/libopenjpeg/t2.c @@ -340,6 +340,11 @@ static int t2_decode_packet(opj_t2_t* t2, unsigned char *src, int len, opj_tcd_t int precno = pi->precno; /* precinct value */ int layno = pi->layno; /* quality layer value */ + if (!&(tile->comps[compno])) { + opj_event_msg(t2->cinfo, EVT_ERROR, "Trying to decode tile with no components!\n"); + return -999; + } + opj_tcd_resolution_t* res = &tile->comps[compno].resolutions[resno]; unsigned char *hd = NULL; diff --git a/libopenjpeg/tcd.c b/libopenjpeg/tcd.c index c38aa56..a19a457 100644 --- a/libopenjpeg/tcd.c +++ b/libopenjpeg/tcd.c @@ -667,8 +667,8 @@ void tcd_malloc_decode(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp) { y1 = j == 0 ? tilec->y1 : int_max(y1, (unsigned int) tilec->y1); } - w = int_ceildivpow2(x1 - x0, image->comps[i].factor); - h = int_ceildivpow2(y1 - y0, image->comps[i].factor); + w = int_ceildivpow2((long)(x1) - (long)(x0), image->comps[i].factor); + h = int_ceildivpow2((long)(y1) - (long)(y0), image->comps[i].factor); image->comps[i].w = w; image->comps[i].h = h; @@ -1381,7 +1381,16 @@ opj_bool tcd_decode_tile(opj_tcd_t *tcd, unsigned char *src, int len, int tileno if (l == -999) { eof = 1; opj_event_msg(tcd->cinfo, EVT_ERROR, "tcd_decode: incomplete bistream\n"); + return OPJ_FALSE; } + + /* The code below assumes that numcomps > 0 */ + if (tile->numcomps <= 0) { + opj_event_msg(tcd->cinfo, EVT_ERROR, "tcd_decode: tile has a zero or negative numcomps\n"); + return OPJ_TRUE; + } + + /*------------------TIER1-----------------*/