diff options
Diffstat (limited to 'extern/libopenjpeg/j2k.c')
-rw-r--r-- | extern/libopenjpeg/j2k.c | 207 |
1 files changed, 186 insertions, 21 deletions
diff --git a/extern/libopenjpeg/j2k.c b/extern/libopenjpeg/j2k.c index d34c75faa7b..93e5c9eb80a 100644 --- a/extern/libopenjpeg/j2k.c +++ b/extern/libopenjpeg/j2k.c @@ -32,6 +32,7 @@ */ #include "opj_includes.h" +#include <assert.h> /** @defgroup J2K J2K - JPEG-2000 codestream reader/writer */ /*@{*/ @@ -404,6 +405,7 @@ static void j2k_write_siz(opj_j2k_t *j2k) { static void j2k_read_siz(opj_j2k_t *j2k) { int len, i; + int n_comps; opj_cio_t *cio = j2k->cio; opj_image_t *image = j2k->image; @@ -422,12 +424,33 @@ static void j2k_read_siz(opj_j2k_t *j2k) { if ((image->x0<0)||(image->x1<0)||(image->y0<0)||(image->y1<0)) { opj_event_msg(j2k->cinfo, EVT_ERROR, - "%s: invalid image size (x0:%d, x1:%d, y0:%d, y1:%d)\n", + "invalid image size (x0:%d, x1:%d, y0:%d, y1:%d)\n", image->x0,image->x1,image->y0,image->y1); return; } + n_comps = (len - 36 - 2 ) / 3; + assert( (len - 36 - 2 ) % 3 == 0 ); image->numcomps = cio_read(cio, 2); /* Csiz */ + assert( n_comps == image->numcomps ); + (void)n_comps; + + /* testcase 4035.pdf.SIGSEGV.d8b.3375 */ + if (image->x0 > image->x1 || image->y0 > image->y1) { + opj_event_msg(j2k->cinfo, EVT_ERROR, "Error with SIZ marker: negative image size (%d x %d)\n", image->x1 - image->x0, image->y1 - image->y0); + return; + } + /* testcase 2539.pdf.SIGFPE.706.1712 (also 3622.pdf.SIGFPE.706.2916 and 4008.pdf.SIGFPE.706.3345 and maybe more) */ + if (!(cp->tdx * cp->tdy)) { + opj_event_msg(j2k->cinfo, EVT_ERROR, "Error with SIZ marker: invalid tile size (tdx: %d, tdy: %d)\n", cp->tdx, cp->tdy); + return; + } + + /* testcase 1610.pdf.SIGSEGV.59c.681 */ + if (((int64)image->x1) * ((int64)image->y1) != (image->x1 * image->y1)) { + opj_event_msg(j2k->cinfo, EVT_ERROR, "Prevent buffer overflow (x1: %d, y1: %d)\n", image->x1, image->y1); + return; + } #ifdef USE_JPWL if (j2k->cp->correct) { @@ -466,11 +489,19 @@ static void j2k_read_siz(opj_j2k_t *j2k) { /* update components number in the jpwl_exp_comps filed */ cp->exp_comps = image->numcomps; } +#else + (void)len; #endif /* USE_JPWL */ + /* prevent division by zero */ + if (!(cp->tdx * cp->tdy)) { + opj_event_msg(j2k->cinfo, EVT_ERROR, "invalid tile size (tdx: %d, tdy: %d)\n", cp->tdx, cp->tdy); + return; + } + 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; tmp = cio_read(cio, 1); /* Ssiz_i */ image->comps[i].prec = (tmp & 0x7f) + 1; image->comps[i].sgnd = tmp >> 7; @@ -506,9 +537,11 @@ static void j2k_read_siz(opj_j2k_t *j2k) { } #endif /* USE_JPWL */ - /* TODO: unused ? */ - w = int_ceildiv(image->x1 - image->x0, image->comps[i].dx); - h = int_ceildiv(image->y1 - image->y0, image->comps[i].dy); + /* prevent division by zero */ + if (!(image->comps[i].dx * image->comps[i].dy)) { + opj_event_msg(j2k->cinfo, EVT_ERROR, "JPWL: invalid component size (dx: %d, dy: %d)\n", image->comps[i].dx, image->comps[i].dy); + return; + } image->comps[i].resno_decoded = 0; /* number of resolution decoded */ image->comps[i].factor = cp->reduce; /* reducing factor per component */ @@ -517,6 +550,15 @@ static void j2k_read_siz(opj_j2k_t *j2k) { cp->tw = int_ceildiv(image->x1 - cp->tx0, cp->tdx); cp->th = int_ceildiv(image->y1 - cp->ty0, cp->tdy); + /* gdal_fuzzer_check_number_of_tiles.jp2 */ + if (cp->tw == 0 || cp->th == 0 || cp->tw > 65535 / cp->th) { + opj_event_msg(j2k->cinfo, EVT_ERROR, + "Invalid number of tiles : %u x %u (maximum fixed by jpeg2000 norm is 65535 tiles)\n", + cp->tw, cp->th); + return; + } + + #ifdef USE_JPWL if (j2k->cp->correct) { /* if JPWL is on, we check whether TX errors have damaged @@ -558,7 +600,17 @@ static void j2k_read_siz(opj_j2k_t *j2k) { #endif /* USE_JPWL */ cp->tcps = (opj_tcp_t*) opj_calloc(cp->tw * cp->th, sizeof(opj_tcp_t)); + if (cp->tcps == NULL) + { + opj_event_msg(j2k->cinfo, EVT_ERROR, "Out of memory\n"); + return; + } cp->tileno = (int*) opj_malloc(cp->tw * cp->th * sizeof(int)); + if (cp->tileno == NULL) + { + opj_event_msg(j2k->cinfo, EVT_ERROR, "Out of memory\n"); + return; + } cp->tileno_size = 0; #ifdef USE_JPWL @@ -684,6 +736,12 @@ static void j2k_read_cox(opj_j2k_t *j2k, int compno) { "of resolutions of this component\nModify the cp_reduce parameter.\n\n", compno); j2k->state |= J2K_STATE_ERR; } + if( tccp->numresolutions > J2K_MAXRLVLS ) { + opj_event_msg(j2k->cinfo, EVT_ERROR, "Error decoding component %d.\nThe number of resolutions is too big: %d vs max= %d. Truncating.\n\n", + compno, tccp->numresolutions, J2K_MAXRLVLS); + j2k->state |= J2K_STATE_ERR; + tccp->numresolutions = J2K_MAXRLVLS; + } tccp->cblkw = cio_read(cio, 1) + 2; /* SPcox (E) */ tccp->cblkh = cio_read(cio, 1) + 2; /* SPcox (F) */ @@ -753,6 +811,7 @@ static void j2k_read_cod(opj_j2k_t *j2k) { opj_image_t *image = j2k->image; len = cio_read(cio, 2); /* Lcod */ + (void)len; tcp->csty = cio_read(cio, 1); /* Scod */ tcp->prg = (OPJ_PROG_ORDER)cio_read(cio, 1); /* SGcod (A) */ tcp->numlayers = cio_read(cio, 2); /* SGcod (B) */ @@ -806,7 +865,14 @@ static void j2k_read_coc(opj_j2k_t *j2k) { opj_cio_t *cio = j2k->cio; len = cio_read(cio, 2); /* Lcoc */ + (void)len; compno = cio_read(cio, image->numcomps <= 256 ? 1 : 2); /* Ccoc */ + if (compno >= image->numcomps) { + opj_event_msg(j2k->cinfo, EVT_ERROR, + "bad component number in COC (%d out of a maximum of %d)\n", + compno, image->numcomps); + return; + } tcp->tccps[compno].csty = cio_read(cio, 1); /* Scoc */ j2k_read_cox(j2k, compno); } @@ -877,6 +943,8 @@ static void j2k_read_qcx(opj_j2k_t *j2k, int compno, int len) { opj_event_msg(j2k->cinfo, EVT_WARNING , "bad number of subbands in Sqcx (%d) regarding to J2K_MAXBANDS (%d) \n" "- limiting number of bands to J2K_MAXBANDS and try to move to the next markers\n", numbands, J2K_MAXBANDS); + /* edf_c2_1013627.jp2 */ + numbands = 1; } #endif /* USE_JPWL */ @@ -988,9 +1056,16 @@ static void j2k_read_qcc(opj_j2k_t *j2k) { /* keep your private count of tiles */ backup_compno++; - }; + } #endif /* USE_JPWL */ + if ((compno < 0) || (compno >= numcomp)) { + opj_event_msg(j2k->cinfo, EVT_ERROR, + "bad component number in QCC (%d out of a maximum of %d)\n", + compno, j2k->image->numcomps); + return; + } + j2k_read_qcx(j2k, compno, len - 2 - (numcomp <= 256 ? 1 : 2)); } @@ -1036,6 +1111,15 @@ static void j2k_read_poc(opj_j2k_t *j2k) { len = cio_read(cio, 2); /* Lpoc */ numpchgs = (len - 2) / (5 + 2 * (numcomps <= 256 ? 1 : 2)); + if( numpchgs >= 32 ) + { + /* edf_c2_1103421.jp2 */ + opj_event_msg(j2k->cinfo, EVT_ERROR, + "bad number of POCS (%d out of a maximum of %d)\n", + numpchgs, 32); + numpchgs = 0; + } + for (i = old_poc; i < numpchgs + old_poc; i++) { opj_poc_t *poc; poc = &tcp->pocs[i]; @@ -1058,9 +1142,12 @@ static void j2k_read_crg(opj_j2k_t *j2k) { int numcomps = j2k->image->numcomps; len = cio_read(cio, 2); /* Lcrg */ + (void)len; for (i = 0; i < numcomps; i++) { Xcrg_i = cio_read(cio, 2); /* Xcrg_i */ + (void)Xcrg_i; Ycrg_i = cio_read(cio, 2); /* Ycrg_i */ + (void)Ycrg_i; } } @@ -1072,13 +1159,16 @@ static void j2k_read_tlm(opj_j2k_t *j2k) { len = cio_read(cio, 2); /* Ltlm */ Ztlm = cio_read(cio, 1); /* Ztlm */ + (void)Ztlm; Stlm = cio_read(cio, 1); /* Stlm */ ST = ((Stlm >> 4) & 0x01) + ((Stlm >> 4) & 0x02); SP = (Stlm >> 6) & 0x01; tile_tlm = (len - 4) / ((SP + 1) * 2 + ST); for (i = 0; i < tile_tlm; i++) { Ttlm_i = cio_read(cio, ST); /* Ttlm_i */ + (void)Ttlm_i; Ptlm_i = cio_read(cio, SP ? 4 : 2); /* Ptlm_i */ + (void)Ptlm_i; } } @@ -1089,6 +1179,7 @@ static void j2k_read_plm(opj_j2k_t *j2k) { len = cio_read(cio, 2); /* Lplm */ Zplm = cio_read(cio, 1); /* Zplm */ + (void)Zplm; len -= 3; while (len > 0) { Nplm = cio_read(cio, 4); /* Nplm */ @@ -1114,6 +1205,7 @@ static void j2k_read_plt(opj_j2k_t *j2k) { len = cio_read(cio, 2); /* Lplt */ Zplt = cio_read(cio, 1); /* Zplt */ + (void)Zplt; for (i = len - 3; i > 0; i--) { add = cio_read(cio, 1); packet_len = (packet_len << 7) + add; /* Iplt_i */ @@ -1261,6 +1353,7 @@ static void j2k_read_sot(opj_j2k_t *j2k) { opj_cio_t *cio = j2k->cio; len = cio_read(cio, 2); + (void)len; tileno = cio_read(cio, 2); #ifdef USE_JPWL @@ -1269,7 +1362,7 @@ static void j2k_read_sot(opj_j2k_t *j2k) { static int backup_tileno = 0; /* tileno is negative or larger than the number of tiles!!! */ - if ((tileno < 0) || (tileno > (cp->tw * cp->th))) { + if ((tileno < 0) || (tileno >= (cp->tw * cp->th))) { opj_event_msg(j2k->cinfo, EVT_ERROR, "JPWL: bad tile number (%d out of a maximum of %d)\n", tileno, (cp->tw * cp->th)); @@ -1286,8 +1379,18 @@ static void j2k_read_sot(opj_j2k_t *j2k) { /* keep your private count of tiles */ backup_tileno++; - }; + } + else #endif /* USE_JPWL */ + { + /* tileno is negative or larger than the number of tiles!!! */ + if ((tileno < 0) || (tileno >= (cp->tw * cp->th))) { + opj_event_msg(j2k->cinfo, EVT_ERROR, + "JPWL: bad tile number (%d out of a maximum of %d)\n", + tileno, (cp->tw * cp->th)); + return; + } + } if (cp->tileno_size == 0) { cp->tileno[cp->tileno_size] = tileno; @@ -1325,8 +1428,18 @@ static void j2k_read_sot(opj_j2k_t *j2k) { totlen); } - }; + } + else #endif /* USE_JPWL */ + { + /* totlen is negative or larger than the bytes left!!! */ + if ((totlen < 0) || (totlen > (cio_numbytesleft(cio) + 8))) { + opj_event_msg(j2k->cinfo, EVT_ERROR, + "JPWL: bad tile byte size (%d bytes against %d bytes left)\n", + totlen, cio_numbytesleft(cio) + 8); + return; + } + } if (!totlen) totlen = cio_numbytesleft(cio) + 8; @@ -1478,7 +1591,13 @@ static void j2k_read_sod(opj_j2k_t *j2k) { } data = j2k->tile_data[curtileno]; + data_ptr = data; /* store in case of failure */ data = (unsigned char*) opj_realloc(data, (j2k->tile_len[curtileno] + len) * sizeof(unsigned char)); + if( data == NULL ) { + opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not reallocated\n" ); + opj_free( data_ptr ); + return; + } data_ptr = data + j2k->tile_len[curtileno]; for (i = 0; i < len; i++) { @@ -1518,8 +1637,10 @@ static void j2k_read_rgn(opj_j2k_t *j2k) { int numcomps = j2k->image->numcomps; len = cio_read(cio, 2); /* Lrgn */ + (void)len; compno = cio_read(cio, numcomps <= 256 ? 1 : 2); /* Crgn */ roisty = cio_read(cio, 1); /* Srgn */ + (void)roisty; #ifdef USE_JPWL if (j2k->cp->correct) { @@ -1536,6 +1657,13 @@ static void j2k_read_rgn(opj_j2k_t *j2k) { }; #endif /* USE_JPWL */ + if (compno >= numcomps) { + opj_event_msg(j2k->cinfo, EVT_ERROR, + "bad component number in RGN (%d out of a maximum of %d)\n", + compno, j2k->image->numcomps); + return; + } + tcp->tccps[compno].roishift = cio_read(cio, 1); /* SPrgn */ } @@ -1554,7 +1682,7 @@ static void j2k_write_eoc(opj_j2k_t *j2k) { static void j2k_read_eoc(opj_j2k_t *j2k) { int i, tileno; - opj_bool success; + opj_bool success = OPJ_FALSE; /* if packets should be decoded */ if (j2k->cp->limit_decoding != DECODE_ALL_BUT_PACKETS) { @@ -1562,11 +1690,17 @@ static void j2k_read_eoc(opj_j2k_t *j2k) { tcd_malloc_decode(tcd, j2k->image, j2k->cp); for (i = 0; i < j2k->cp->tileno_size; i++) { tcd_malloc_decode_tile(tcd, j2k->image, j2k->cp, i, j2k->cstr_info); - tileno = j2k->cp->tileno[i]; - success = tcd_decode_tile(tcd, j2k->tile_data[tileno], j2k->tile_len[tileno], tileno, j2k->cstr_info); - opj_free(j2k->tile_data[tileno]); - j2k->tile_data[tileno] = NULL; - tcd_free_decode_tile(tcd, i); + if (j2k->cp->tileno[i] != -1) + { + tileno = j2k->cp->tileno[i]; + success = tcd_decode_tile(tcd, j2k->tile_data[tileno], j2k->tile_len[tileno], tileno, j2k->cstr_info); + assert( tileno != -1 ); + opj_free(j2k->tile_data[tileno]); + j2k->tile_data[tileno] = NULL; + tcd_free_decode_tile(tcd, i); + } + else + success = OPJ_FALSE; if (success == OPJ_FALSE) { j2k->state |= J2K_STATE_ERR; break; @@ -1737,6 +1871,17 @@ void j2k_destroy_decompress(opj_j2k_t *j2k) { opj_free(j2k->tile_len); } if(j2k->tile_data != NULL) { + if(j2k->cp != NULL) { + for (i = 0; i < j2k->cp->tileno_size; i++) { + int tileno = j2k->cp->tileno[i]; + if( tileno != -1 ) + { + opj_free(j2k->tile_data[tileno]); + j2k->tile_data[tileno] = NULL; + } + } + } + opj_free(j2k->tile_data); } if(j2k->default_tcp != NULL) { @@ -1856,9 +2001,15 @@ opj_image_t* j2k_decode(opj_j2k_t *j2k, opj_cio_t *cio, opj_codestream_info_t *c #endif /* USE_JPWL */ if (id >> 8 != 0xff) { - opj_image_destroy(image); - opj_event_msg(cinfo, EVT_ERROR, "%.8x: expected a marker instead of %x\n", cio_tell(cio) - 2, id); - return 0; + if(cio_numbytesleft(cio) != 0) /* not end of file reached and no EOC */ + { + opj_event_msg(cinfo, EVT_ERROR, "%.8x: expected a marker instead of %x\n", cio_tell(cio) - 2, id); + opj_image_destroy(image); + return 0; + } + opj_event_msg(cinfo, EVT_WARNING, "%.8x: expected a marker instead of %x\n", cio_tell(cio) - 2, id); + j2k->state = J2K_STATE_NEOC; + break; } e = j2k_dec_mstab_lookup(id); /* Check if the marker is known*/ @@ -1877,7 +2028,10 @@ opj_image_t* j2k_decode(opj_j2k_t *j2k, opj_cio_t *cio, opj_codestream_info_t *c (*e->handler)(j2k); } if (j2k->state & J2K_STATE_ERR) + { + opj_image_destroy(image); return NULL; + } if (j2k->state == J2K_STATE_MT) { break; @@ -1888,6 +2042,11 @@ opj_image_t* j2k_decode(opj_j2k_t *j2k, opj_cio_t *cio, opj_codestream_info_t *c } if (j2k->state == J2K_STATE_NEOC) { j2k_read_eoc(j2k); + /* Check one last time for errors during decoding before returning */ + if (j2k->state & J2K_STATE_ERR) { + opj_image_destroy(image); + return NULL; + } } if (j2k->state != J2K_STATE_MT) { @@ -1949,9 +2108,15 @@ opj_image_t* j2k_decode_jpt_stream(opj_j2k_t *j2k, opj_cio_t *cio, opj_codestre id = cio_read(cio, 2); if (id >> 8 != 0xff) { - opj_image_destroy(image); - opj_event_msg(cinfo, EVT_ERROR, "%.8x: expected a marker instead of %x\n", cio_tell(cio) - 2, id); - return 0; + if(cio_numbytesleft(cio) != 0) /* no end of file reached and no EOC */ + { + opj_event_msg(cinfo, EVT_ERROR, "%.8x: expected a marker instead of %x\n", cio_tell(cio) - 2, id); + opj_image_destroy(image); + return 0; + } + opj_event_msg(cinfo, EVT_WARNING, "%.8x: expected a marker instead of %x\n", cio_tell(cio) - 2, id); + j2k->state = J2K_STATE_NEOC; + break; } e = j2k_dec_mstab_lookup(id); if (!(j2k->state & e->states)) { |