[1.5] Apply private patch from Alex Macfarlane Smith
authorMathieu Malaterre <mathieu.malaterre@gmail.com>
Tue, 29 May 2012 14:52:45 +0000 (14:52 +0000)
committerMathieu Malaterre <mathieu.malaterre@gmail.com>
Tue, 29 May 2012 14:52:45 +0000 (14:52 +0000)
This gets rids of a lot memory leaks when used on device with low memory

libopenjpeg/j2k.c
libopenjpeg/t1.c
libopenjpeg/t2.c
libopenjpeg/tcd.c

index d34c75faa7ba20cecbccf02986d524ba8d5484c2..5bd52a998e2182d0aabb8c06f7b4ac0673b021c8 100644 (file)
@@ -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;
index 477720412aa13aafdfa4f98c7259823c929f8a35..ed9cdc3fea6b2df04d20fc1f9159175d62fa983c 100644 (file)
@@ -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 */
index 232a54373290efde0216abc1dea918d96f7f793f..cae29f09b1dd3feeb18324d074799124e67a2b35 100644 (file)
@@ -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) ? 
index 94c5d79f668f22f651838eb29784774999f6a9a0..0f218a16edf760952094e03f2e2543de2483a940 100644 (file)
@@ -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);
 }