From f11b365a5147cd6d1a2b0f23614b6ff6762d9dce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nikola=20Forr=C3=B3?= Date: Mon, 20 Feb 2017 14:17:46 +0100 Subject: [PATCH 2/4] Fix CVE-2016-5158 --- libopenjpeg/dwt.c | 45 ++++++++++++++++++++++++++++++++++++++------- libopenjpeg/dwt.h | 4 ++-- libopenjpeg/jp2.c | 41 +++++++++++++++++++++++------------------ libopenjpeg/t1.c | 22 ++++++++++++++++++---- libopenjpeg/tcd.c | 10 ++++++++-- 5 files changed, 89 insertions(+), 33 deletions(-) diff --git a/libopenjpeg/dwt.c b/libopenjpeg/dwt.c index 0fbfc20..663cfe2 100644 --- a/libopenjpeg/dwt.c +++ b/libopenjpeg/dwt.c @@ -118,7 +118,7 @@ static void dwt_encode_stepsize(int stepsize, int numbps, opj_stepsize_t *bandno /** Inverse wavelet transform in 2-D. */ -static void dwt_decode_tile(opj_tcd_tilecomp_t* tilec, int i, DWT1DFN fn); +static opj_bool dwt_decode_tile(opj_tcd_tilecomp_t* tilec, int i, DWT1DFN fn); /*@}*/ @@ -379,8 +379,8 @@ void dwt_encode(opj_tcd_tilecomp_t * tilec) { /* */ /* Inverse 5-3 wavelet transform in 2-D. */ /* */ -void dwt_decode(opj_tcd_tilecomp_t* tilec, int numres) { - dwt_decode_tile(tilec, numres, &dwt_decode_1); +opj_bool dwt_decode(opj_tcd_tilecomp_t* tilec, int numres) { + return dwt_decode_tile(tilec, numres, &dwt_decode_1); } @@ -516,7 +516,7 @@ static int dwt_decode_max_resolution(opj_tcd_resolution_t* restrict r, int i) { /* */ /* Inverse wavelet transform in 2-D. */ /* */ -static void dwt_decode_tile(opj_tcd_tilecomp_t* tilec, int numres, DWT1DFN dwt_1D) { +static opj_bool dwt_decode_tile(opj_tcd_tilecomp_t* tilec, int numres, DWT1DFN dwt_1D) { dwt_t h; dwt_t v; @@ -527,7 +527,18 @@ static void dwt_decode_tile(opj_tcd_tilecomp_t* tilec, int numres, DWT1DFN dwt_1 int w = tilec->x1 - tilec->x0; - h.mem = (int*)opj_aligned_malloc(dwt_decode_max_resolution(tr, numres) * sizeof(int)); + uint32_t h_mem_count = dwt_decode_max_resolution(tr, numres); + + if (((uint32_t)-1) / (uint32_t)sizeof(int) < h_mem_count) { + return OPJ_FALSE; + } + + h.mem = (int*)opj_aligned_malloc(h_mem_count * sizeof(int)); + + if (h.mem == NULL) { + return OPJ_FALSE; + } + v.mem = h.mem; while( --numres) { @@ -563,6 +574,8 @@ static void dwt_decode_tile(opj_tcd_tilecomp_t* tilec, int numres, DWT1DFN dwt_1 } } opj_aligned_free(h.mem); + + return OPJ_TRUE; } static void v4dwt_interleave_h(v4dwt_t* restrict w, float* restrict a, int x, int size){ @@ -772,7 +785,7 @@ static void v4dwt_decode(v4dwt_t* restrict dwt){ /* */ /* Inverse 9-7 wavelet transform in 2-D. */ /* */ -void dwt_decode_real(opj_tcd_tilecomp_t* restrict tilec, int numres){ +opj_bool dwt_decode_real(opj_tcd_tilecomp_t* restrict tilec, int numres){ v4dwt_t h; v4dwt_t v; @@ -783,7 +796,23 @@ void dwt_decode_real(opj_tcd_tilecomp_t* restrict tilec, int numres){ int w = tilec->x1 - tilec->x0; - h.wavelet = (v4*) opj_aligned_malloc((dwt_decode_max_resolution(res, numres)+5) * sizeof(v4)); + uint32_t mr = dwt_decode_max_resolution(res, numres); + + if (mr >= ((uint32_t)-5)) { + return OPJ_FALSE; + } + mr += 5; + + if (((uint32_t)-1) / (uint32_t)sizeof(v4) < mr) { + return OPJ_FALSE; + } + + h.wavelet = (v4*) opj_aligned_malloc(mr * sizeof(v4)); + + if (h.wavelet == NULL) { + return OPJ_FALSE; + } + v.wavelet = h.wavelet; while( --numres) { @@ -854,5 +883,7 @@ void dwt_decode_real(opj_tcd_tilecomp_t* restrict tilec, int numres){ } opj_aligned_free(h.wavelet); + + return OPJ_TRUE; } diff --git a/libopenjpeg/dwt.h b/libopenjpeg/dwt.h index adf73e5..138ab76 100644 --- a/libopenjpeg/dwt.h +++ b/libopenjpeg/dwt.h @@ -59,7 +59,7 @@ Apply a reversible inverse DWT transform to a component of an image. @param tilec Tile component information (current tile) @param numres Number of resolution levels to decode */ -void dwt_decode(opj_tcd_tilecomp_t* tilec, int numres); +opj_bool dwt_decode(opj_tcd_tilecomp_t* tilec, int numres); /** Get the gain of a subband for the reversible 5-3 DWT. @param orient Number that identifies the subband (0->LL, 1->HL, 2->LH, 3->HH) @@ -85,7 +85,7 @@ Apply an irreversible inverse DWT transform to a component of an image. @param tilec Tile component information (current tile) @param numres Number of resolution levels to decode */ -void dwt_decode_real(opj_tcd_tilecomp_t* tilec, int numres); +opj_bool dwt_decode_real(opj_tcd_tilecomp_t* tilec, int numres); /** Get the gain of a subband for the irreversible 9-7 DWT. @param orient Number that identifies the subband (0->LL, 1->HL, 2->LH, 3->HH) diff --git a/libopenjpeg/jp2.c b/libopenjpeg/jp2.c index c3740eb..85b3999 100644 --- a/libopenjpeg/jp2.c +++ b/libopenjpeg/jp2.c @@ -382,9 +382,7 @@ static void jp2_apply_pclr(opj_jp2_color_t *color, opj_image_t *image, opj_commo { pcol = cmap[i].pcol; cmp = cmap[i].cmp; - if( pcol < nr_channels ) - new_comps[pcol] = old_comps[cmp]; - else + if( pcol >= nr_channels ) { opj_event_msg(cinfo, EVT_ERROR, "Error with pcol value %d (max: %d). skipping\n", pcol, nr_channels); continue; @@ -392,34 +390,41 @@ static void jp2_apply_pclr(opj_jp2_color_t *color, opj_image_t *image, opj_commo if(cmap[i].mtyp == 0) /* Direct use */ { - old_comps[cmp].data = NULL; continue; + new_comps[i] = old_comps[cmp]; + } else { + new_comps[pcol] = old_comps[cmp]; } /* Palette mapping: */ - new_comps[pcol].data = (int*) + new_comps[i].data = (int*) opj_malloc(old_comps[cmp].w * old_comps[cmp].h * sizeof(int)); - new_comps[pcol].prec = channel_size[i]; - new_comps[pcol].sgnd = channel_sign[i]; + new_comps[i].prec = channel_size[i]; + new_comps[i].sgnd = channel_sign[i]; } top_k = color->jp2_pclr->nr_entries - 1; for(i = 0; i < nr_channels; ++i) { -/* Direct use: */ - if(cmap[i].mtyp == 0) continue; - /* Palette mapping: */ cmp = cmap[i].cmp; pcol = cmap[i].pcol; src = old_comps[cmp].data; - dst = new_comps[pcol].data; max = new_comps[pcol].w * new_comps[pcol].h; - for(j = 0; j < max; ++j) - { -/* The index */ - if((k = src[j]) < 0) k = 0; else if(k > top_k) k = top_k; -/* The colour */ - dst[j] = entries[k * nr_channels + pcol]; - } +/* Direct use: */ + if(cmap[i].mtyp == 0) { + dst = new_comps[i].data; + for(j = 0; j < max; ++j) { + dst[j] = src[j]; + } + } else { + dst = new_comps[pcol].data; + for(j = 0; j < max; ++j) { + /* The index */ + if((k = src[j]) < 0) k = 0; else if(k > top_k) k = top_k; + + /* The colour */ + dst[j] = entries[k * nr_channels + pcol]; + } + } } max = image->numcomps; for(i = 0; i < max; ++i) diff --git a/libopenjpeg/t1.c b/libopenjpeg/t1.c index ed9cdc3..30815e4 100644 --- a/libopenjpeg/t1.c +++ b/libopenjpeg/t1.c @@ -1114,7 +1114,13 @@ static opj_bool allocate_buffers( int flagssize; if(datasize > t1->datasize){ - opj_aligned_free(t1->data); + if (t1->data != NULL) { + opj_aligned_free(t1->data); + t1->data = NULL; + } + if (((uint32_t)-1) / (uint32_t)sizeof(int) < datasize) { + return OPJ_FALSE; + } t1->data = (int*) opj_aligned_malloc(datasize * sizeof(int)); if(!t1->data){ return OPJ_FALSE; @@ -1127,7 +1133,13 @@ static opj_bool allocate_buffers( flagssize=t1->flags_stride * (h+2); if(flagssize > t1->flagssize){ - opj_aligned_free(t1->flags); + if (t1->flags != NULL) { + opj_aligned_free(t1->flags); + t1->flags = NULL; + } + if (((uint32_t)-1) / (uint32_t)sizeof(flag_t) < flagssize) { + return OPJ_FALSE; + } t1->flags = (flag_t*) opj_aligned_malloc(flagssize * sizeof(flag_t)); if(!t1->flags){ return OPJ_FALSE; @@ -1390,8 +1402,10 @@ void t1_destroy(opj_t1_t *t1) { /* destroy MQC and RAW handles */ mqc_destroy(t1->mqc); raw_destroy(t1->raw); - opj_aligned_free(t1->data); - opj_aligned_free(t1->flags); + if (t1->data != NULL) + opj_aligned_free(t1->data); + if (t1->flags != NULL) + opj_aligned_free(t1->flags); opj_free(t1); } } diff --git a/libopenjpeg/tcd.c b/libopenjpeg/tcd.c index 72d6838..902243b 100644 --- a/libopenjpeg/tcd.c +++ b/libopenjpeg/tcd.c @@ -1465,9 +1465,15 @@ opj_bool tcd_decode_tile(opj_tcd_t *tcd, unsigned char *src, int len, int tileno numres2decode = tcd->image->comps[compno].resno_decoded + 1; if(numres2decode > 0){ if (tcd->tcp->tccps[compno].qmfbid == 1) { - dwt_decode(tilec, numres2decode); + if (! dwt_decode(tilec, numres2decode)) { + opj_event_msg(tcd->cinfo, EVT_ERROR, "Error during DWT decoding\n"); + return OPJ_FALSE; + } } else { - dwt_decode_real(tilec, numres2decode); + if (! dwt_decode_real(tilec, numres2decode)) { + opj_event_msg(tcd->cinfo, EVT_ERROR, "Error during DWT decoding\n"); + return OPJ_FALSE; + } } } } -- 2.7.4