From 6c5a066b20234db55c920adf13fca2bc77d3f305 Mon Sep 17 00:00:00 2001 From: Mathieu Malaterre Date: Tue, 29 May 2012 14:52:45 +0000 Subject: [PATCH] [1.5] Apply private patch from Alex Macfarlane Smith This gets rids of a lot memory leaks when used on device with low memory --- libopenjpeg/j2k.c | 21 +++++++++++++++ libopenjpeg/t1.c | 1 + libopenjpeg/t2.c | 43 +++++++++++++++++++++++++----- libopenjpeg/tcd.c | 67 ++++++++++++++++++++++++++++++++++++----------- 4 files changed, 110 insertions(+), 22 deletions(-) diff --git a/libopenjpeg/j2k.c b/libopenjpeg/j2k.c index d34c75fa..5bd52a99 100644 --- a/libopenjpeg/j2k.c +++ b/libopenjpeg/j2k.c @@ -558,7 +558,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 @@ -1737,6 +1747,14 @@ 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]; + opj_free(j2k->tile_data[tileno]); + j2k->tile_data[tileno] = NULL; + } + } + opj_free(j2k->tile_data); } if(j2k->default_tcp != NULL) { @@ -1877,7 +1895,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; diff --git a/libopenjpeg/t1.c b/libopenjpeg/t1.c index 47772041..ed9cdc3f 100644 --- a/libopenjpeg/t1.c +++ b/libopenjpeg/t1.c @@ -1577,6 +1577,7 @@ void t1_decode_cblks( opj_free(cblk->segs); } /* cblkno */ opj_free(precinct->cblks.dec); + precinct->cblks.dec = NULL; } /* precno */ } /* bandno */ } /* resno */ diff --git a/libopenjpeg/t2.c b/libopenjpeg/t2.c index 232a5437..cae29f09 100644 --- a/libopenjpeg/t2.c +++ b/libopenjpeg/t2.c @@ -64,7 +64,7 @@ static int t2_encode_packet(opj_tcd_tile_t *tile, opj_tcp_t *tcp, opj_pi_iterato @param cblksty @param first */ -static void t2_init_seg(opj_tcd_cblk_dec_t* cblk, int index, int cblksty, int first); +static opj_bool t2_init_seg(opj_tcd_cblk_dec_t* cblk, int index, int cblksty, int first); /** Decode a packet of a tile from a source buffer @param t2 T2 handle @@ -296,9 +296,17 @@ static int t2_encode_packet(opj_tcd_tile_t * tile, opj_tcp_t * tcp, opj_pi_itera return (c - dest); } -static void t2_init_seg(opj_tcd_cblk_dec_t* cblk, int index, int cblksty, int first) { +static opj_bool t2_init_seg(opj_tcd_cblk_dec_t* cblk, int index, int cblksty, int first) { opj_tcd_seg_t* seg; - cblk->segs = (opj_tcd_seg_t*) opj_realloc(cblk->segs, (index + 1) * sizeof(opj_tcd_seg_t)); + opj_tcd_seg_t* segs; + segs = (opj_tcd_seg_t*) opj_realloc(cblk->segs, (index + 1) * sizeof(opj_tcd_seg_t)); + + if (segs == NULL) + { + return OPJ_FALSE; + } + cblk->segs = segs; + seg = &cblk->segs[index]; seg->data = NULL; seg->dataindex = 0; @@ -316,6 +324,8 @@ static void t2_init_seg(opj_tcd_cblk_dec_t* cblk, int index, int cblksty, int fi } else { seg->maxpasses = 109; } + + return OPJ_TRUE; } static int t2_decode_packet(opj_t2_t* t2, unsigned char *src, int len, opj_tcd_tile_t *tile, @@ -462,12 +472,22 @@ static int t2_decode_packet(opj_t2_t* t2, unsigned char *src, int len, opj_tcd_t cblk->numlenbits += increment; segno = 0; if (!cblk->numsegs) { - t2_init_seg(cblk, segno, tcp->tccps[compno].cblksty, 1); + if (!t2_init_seg(cblk, segno, tcp->tccps[compno].cblksty, 1)) + { + opj_event_msg(t2->cinfo, EVT_ERROR, "Out of memory\n"); + bio_destroy(bio); + return -999; + } } else { segno = cblk->numsegs - 1; if (cblk->segs[segno].numpasses == cblk->segs[segno].maxpasses) { ++segno; - t2_init_seg(cblk, segno, tcp->tccps[compno].cblksty, 0); + if (!t2_init_seg(cblk, segno, tcp->tccps[compno].cblksty, 0)) + { + opj_event_msg(t2->cinfo, EVT_ERROR, "Out of memory\n"); + bio_destroy(bio); + return -999; + } } } n = cblk->numnewpasses; @@ -478,7 +498,12 @@ static int t2_decode_packet(opj_t2_t* t2, unsigned char *src, int len, opj_tcd_t n -= cblk->segs[segno].numnewpasses; if (n > 0) { ++segno; - t2_init_seg(cblk, segno, tcp->tccps[compno].cblksty, 0); + if (!t2_init_seg(cblk, segno, tcp->tccps[compno].cblksty, 0)) + { + opj_event_msg(t2->cinfo, EVT_ERROR, "Out of memory\n"); + bio_destroy(bio); + return -999; + } } } while (n > 0); } @@ -714,7 +739,11 @@ int t2_decode_packets(opj_t2_t *t2, unsigned char *src, int len, int tileno, opj } else { e = 0; } - if(e == -999) return -999; + if(e == -999) + { + pi_destroy(pi, cp, tileno); + return -999; + } /* progression in resolution */ image->comps[pi[pino].compno].resno_decoded = (e > 0) ? diff --git a/libopenjpeg/tcd.c b/libopenjpeg/tcd.c index 94c5d79f..0f218a16 100644 --- a/libopenjpeg/tcd.c +++ b/libopenjpeg/tcd.c @@ -615,7 +615,7 @@ void tcd_malloc_decode(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp) { tcd->image = image; tcd->tcd_image->tw = cp->tw; tcd->tcd_image->th = cp->th; - tcd->tcd_image->tiles = (opj_tcd_tile_t *) opj_malloc(cp->tw * cp->th * sizeof(opj_tcd_tile_t)); + tcd->tcd_image->tiles = (opj_tcd_tile_t *) opj_calloc(cp->tw * cp->th, sizeof(opj_tcd_tile_t)); /* Allocate place to store the decoded data = final image @@ -1377,10 +1377,23 @@ opj_bool tcd_decode_tile(opj_tcd_t *tcd, unsigned char *src, int len, int tileno t1_time = opj_clock(); /* time needed to decode a tile */ t1 = t1_create(tcd->cinfo); + if (t1 == NULL) + { + opj_event_msg(tcd->cinfo, EVT_ERROR, "Out of memory\n"); + t1_destroy(t1); + return OPJ_FALSE; + } + for (compno = 0; compno < tile->numcomps; ++compno) { opj_tcd_tilecomp_t* tilec = &tile->comps[compno]; /* The +3 is headroom required by the vectorized DWT */ tilec->data = (int*) opj_aligned_malloc((((tilec->x1 - tilec->x0) * (tilec->y1 - tilec->y0))+3) * sizeof(int)); + if (tilec->data == NULL) + { + opj_event_msg(tcd->cinfo, EVT_ERROR, "Out of memory\n"); + return OPJ_FALSE; + } + t1_decode_cblks(t1, tilec, &tcd->tcp->tccps[compno]); } t1_destroy(t1); @@ -1460,6 +1473,11 @@ opj_bool tcd_decode_tile(opj_tcd_t *tcd, unsigned char *src, int len, int tileno if(!imagec->data){ imagec->data = (int*) opj_malloc(imagec->w * imagec->h * sizeof(int)); } + if (!imagec->data) + { + opj_event_msg(tcd->cinfo, EVT_ERROR, "Out of memory\n"); + return OPJ_FALSE; + } if(tcd->tcp->tccps[compno].qmfbid == 1) { for(j = res->y0; j < res->y1; ++j) { for(i = res->x0; i < res->x1; ++i) { @@ -1493,32 +1511,51 @@ opj_bool tcd_decode_tile(opj_tcd_t *tcd, unsigned char *src, int len, int tileno void tcd_free_decode(opj_tcd_t *tcd) { opj_tcd_image_t *tcd_image = tcd->tcd_image; + int i = 0; + for (i = 0; i < tcd_image->tw * tcd_image->th; i++) + { + tcd_free_decode_tile(tcd, i); + } + opj_free(tcd_image->tiles); } void tcd_free_decode_tile(opj_tcd_t *tcd, int tileno) { - int compno,resno,bandno,precno; + int compno,resno,bandno,precno,cblkno; opj_tcd_image_t *tcd_image = tcd->tcd_image; opj_tcd_tile_t *tile = &tcd_image->tiles[tileno]; - 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->imsbtree != NULL) tgt_destroy(prec->imsbtree); - if (prec->incltree != NULL) tgt_destroy(prec->incltree); + 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); } - opj_free(band->precincts); } + opj_free(tilec->resolutions); } - opj_free(tilec->resolutions); + opj_free(tile->comps); + tile->comps = NULL; } - opj_free(tile->comps); }