Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'extern/libopenjpeg/j2k.c')
-rw-r--r--extern/libopenjpeg/j2k.c207
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)) {