From 5710485cd8db4037e9670c2c03a8ad2481d2e198 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nikola=20Forr=C3=B3?= Date: Mon, 20 Feb 2017 14:16:25 +0100 Subject: [PATCH 1/4] Fix CVE-2016-5139 --- libopenjpeg/j2k.c | 11 +++++-- libopenjpeg/opj_includes.h | 18 +++++++++++ libopenjpeg/tcd.c | 74 ++++++++++++++++++++++++++++++++-------------- 3 files changed, 78 insertions(+), 25 deletions(-) diff --git a/libopenjpeg/j2k.c b/libopenjpeg/j2k.c index 4924b23..0a68476 100644 --- a/libopenjpeg/j2k.c +++ b/libopenjpeg/j2k.c @@ -1670,6 +1670,7 @@ static void j2k_read_eoc(opj_j2k_t *j2k) { opj_tcd_t *tcd = tcd_create(j2k->cinfo); tcd_malloc_decode(tcd, j2k->image, j2k->cp); for (i = 0; i < j2k->cp->tileno_size; i++) { + tileno = j2k->cp->tileno[i]; tcd_malloc_decode_tile(tcd, j2k->image, j2k->cp, i, j2k->cstr_info); if (j2k->cp->tileno[i] != -1) { @@ -1680,7 +1681,11 @@ static void j2k_read_eoc(opj_j2k_t *j2k) { tcd_free_decode_tile(tcd, i); } else + { success = OPJ_FALSE; + opj_free(j2k->tile_data[tileno]); + j2k->tile_data[tileno] = NULL; + } if (success == OPJ_FALSE) { j2k->state |= J2K_STATE_ERR; break; @@ -1854,8 +1859,10 @@ void j2k_destroy_decompress(opj_j2k_t *j2k) { if(j2k->cp != NULL) { for (i = 0; i < j2k->cp->tileno_size; i++) { int tileno = j2k->cp->tileno[i]; - opj_free(j2k->tile_data[tileno]); - j2k->tile_data[tileno] = NULL; + if (tileno != -1) { + opj_free(j2k->tile_data[tileno]); + j2k->tile_data[tileno] = NULL; + } } } diff --git a/libopenjpeg/opj_includes.h b/libopenjpeg/opj_includes.h index 2b5866a..3729c4d 100644 --- a/libopenjpeg/opj_includes.h +++ b/libopenjpeg/opj_includes.h @@ -137,4 +137,22 @@ static INLINE long lrintf(float f){ #endif /* USE_JPWL */ /* < +#else +#if defined(_WIN32) +typedef signed __int8 int8_t; +typedef unsigned __int8 uint8_t; +typedef signed __int16 int16_t; +typedef unsigned __int16 uint16_t; +typedef signed __int32 int32_t; +typedef unsigned __int32 uint32_t; +typedef signed __int64 int64_t; +typedef unsigned __int64 uint64_t; +#else +#error unsupported platform +#endif +#endif + #endif /* OPJ_INCLUDES_H */ diff --git a/libopenjpeg/tcd.c b/libopenjpeg/tcd.c index 3493bb3..72d6838 100644 --- a/libopenjpeg/tcd.c +++ b/libopenjpeg/tcd.c @@ -709,6 +709,12 @@ void tcd_malloc_decode_tile(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp, tilec->numresolutions = tccp->numresolutions; tilec->resolutions = (opj_tcd_resolution_t *) opj_malloc(tilec->numresolutions * sizeof(opj_tcd_resolution_t)); + + if (tilec->resolutions == NULL) { + opj_event_msg(tcd->cinfo, EVT_ERROR, "Not enough memory to handle tile component resolutions\n"); + cp->tileno[tileno] = -1; + return; + } for (resno = 0; resno < tilec->numresolutions; resno++) { int pdx, pdy; @@ -742,8 +748,20 @@ void tcd_malloc_decode_tile(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp, brprcxend = int_ceildivpow2(res->x1, pdx) << pdx; brprcyend = int_ceildivpow2(res->y1, pdy) << pdy; - res->pw = (res->x0 == res->x1) ? 0 : ((brprcxend - tlprcxstart) >> pdx); - res->ph = (res->y0 == res->y1) ? 0 : ((brprcyend - tlprcystart) >> pdy); + res->pw = (res->x0 == res->x1) ? 0U : ((brprcxend - tlprcxstart) >> pdx); + res->ph = (res->y0 == res->y1) ? 0U : ((brprcyend - tlprcystart) >> pdy); + + if ((res->pw != 0U) && ((((uint32_t)-1) / res->pw) < res->ph)) { + opj_event_msg(tcd->cinfo, EVT_ERROR, "Not enough memory for tile data\n"); + cp->tileno[tileno] = -1; + return; + } + + if ((((uint32_t)-1) / (uint32_t)sizeof(opj_tcd_precinct_t)) < res->pw * res->ph) { + opj_event_msg(tcd->cinfo, EVT_ERROR, "Not enough memory for tile data\n"); + cp->tileno[tileno] = -1; + return; + } if (resno == 0) { tlcbgxstart = tlprcxstart; @@ -795,6 +813,12 @@ void tcd_malloc_decode_tile(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp, band->numbps = ss->expn + tccp->numgbits - 1; /* WHY -1 ? */ band->precincts = (opj_tcd_precinct_t *) opj_malloc(res->pw * res->ph * sizeof(opj_tcd_precinct_t)); + + if (band->precincts == NULL) { + opj_event_msg(tcd->cinfo, EVT_ERROR, "Not enough memory to handle band precints\n"); + cp->tileno[tileno] = -1; + return; + } for (precno = 0; precno < res->pw * res->ph; precno++) { int tlcblkxstart, tlcblkystart, brcblkxend, brcblkyend; @@ -1558,29 +1582,33 @@ void tcd_free_decode_tile(opj_tcd_t *tcd, int tileno) { if (tile->comps != NULL) { for (compno = 0; compno < tile->numcomps; compno++) { opj_tcd_tilecomp_t *tilec = &tile->comps[compno]; - for (resno = 0; resno < tilec->numresolutions; resno++) { - opj_tcd_resolution_t *res = &tilec->resolutions[resno]; - for (bandno = 0; bandno < res->numbands; bandno++) { - opj_tcd_band_t *band = &res->bands[bandno]; - for (precno = 0; precno < res->ph * res->pw; precno++) { - opj_tcd_precinct_t *prec = &band->precincts[precno]; - if (prec->cblks.dec != NULL) { - for (cblkno = 0; cblkno < prec->cw * prec->ch; ++cblkno) { - opj_tcd_cblk_dec_t* cblk = &prec->cblks.dec[cblkno]; - opj_free(cblk->data); - opj_free(cblk->segs); - } - opj_free(prec->cblks.dec); - } - if (prec->imsbtree != NULL) tgt_destroy(prec->imsbtree); - if (prec->incltree != NULL) tgt_destroy(prec->incltree); - - - } - opj_free(band->precincts); + if (tilec->resolutions != NULL) { + for (resno = 0; resno < tilec->numresolutions; resno++) { + opj_tcd_resolution_t *res = &tilec->resolutions[resno]; + for (bandno = 0; bandno < res->numbands; bandno++) { + opj_tcd_band_t *band = &res->bands[bandno]; + if (band->precincts != NULL) { + for (precno = 0; precno < res->ph * res->pw; precno++) { + opj_tcd_precinct_t *prec = &band->precincts[precno]; + if (prec->cblks.dec != NULL) { + for (cblkno = 0; cblkno < prec->cw * prec->ch; ++cblkno) { + opj_tcd_cblk_dec_t* cblk = &prec->cblks.dec[cblkno]; + opj_free(cblk->data); + opj_free(cblk->segs); + } + opj_free(prec->cblks.dec); + } + if (prec->imsbtree != NULL) tgt_destroy(prec->imsbtree); + if (prec->incltree != NULL) tgt_destroy(prec->incltree); + + + } + opj_free(band->precincts); + } + } } + opj_free(tilec->resolutions); } - opj_free(tilec->resolutions); } opj_free(tile->comps); tile->comps = NULL; -- 2.7.4