Backport of the upstream patch: From 03fe49ab96bf65fea784cdc256507ea88267fc7c Mon Sep 17 00:00:00 2001 From: Michael Adams Date: Thu, 2 Mar 2017 08:07:04 -0800 Subject: [PATCH] Fixed some potential double-free problems in the JPC codec. diff -pruN jasper-1.900.1.orig/src/libjasper/jpc/jpc_enc.c jasper-1.900.1/src/libjasper/jpc/jpc_enc.c --- jasper-1.900.1.orig/src/libjasper/jpc/jpc_enc.c 2017-03-30 22:53:59.000000000 +0200 +++ jasper-1.900.1/src/libjasper/jpc/jpc_enc.c 2017-03-31 13:40:12.000000000 +0200 @@ -1140,8 +1140,9 @@ int numgbits; tilex = tileno % cp->numhtiles; tiley = tileno / cp->numhtiles; - if (!(enc->curtile = jpc_enc_tile_create(enc->cp, enc->image, tileno))) { - abort(); + if (!(enc->curtile = jpc_enc_tile_create(enc->cp, enc->image, + tileno))) { + return -1; } tile = enc->curtile; @@ -2016,6 +2017,8 @@ error: return 0; } +/* Note: I don't think that it is necessary to marked destroyed subobjects +as such in this function. */ void jpc_enc_tile_destroy(jpc_enc_tile_t *tile) { jpc_enc_tcmpt_t *tcmpt; @@ -2027,16 +2030,21 @@ void jpc_enc_tile_destroy(jpc_enc_tile_t tcmpt_destroy(tcmpt); } jas_free(tile->tcmpts); + /* tile->tcmpts = NULL; */ } if (tile->lyrsizes) { jas_free(tile->lyrsizes); + /* tile->lyrsizes = NULL; */ } if (tile->pi) { jpc_pi_destroy(tile->pi); + /* tile->pi = NULL; */ } jas_free(tile); + /* tile = NULL; */ } +/* Note: This constructor creates the object in place. */ static jpc_enc_tcmpt_t *tcmpt_create(jpc_enc_tcmpt_t *tcmpt, jpc_enc_cp_t *cp, jas_image_t *image, jpc_enc_tile_t *tile) { @@ -2132,6 +2140,10 @@ error: } +/* Note: Since jpc_enc_tcmpt_t objects are created in-place, they might +potentially be destroyed multiple times at different levels in the call +chain. So, destroyed subobjects must be marked as destroyed to prevent +problems such as double frees. */ static void tcmpt_destroy(jpc_enc_tcmpt_t *tcmpt) { jpc_enc_rlvl_t *rlvl; @@ -2143,16 +2155,20 @@ static void tcmpt_destroy(jpc_enc_tcmpt_ rlvl_destroy(rlvl); } jas_free(tcmpt->rlvls); + tcmpt->rlvls = NULL; } if (tcmpt->data) { jas_seq2d_destroy(tcmpt->data); + tcmpt->data = NULL; } if (tcmpt->tsfb) { jpc_tsfb_destroy(tcmpt->tsfb); + tcmpt->tsfb = NULL; } } +/* Note: This constructor creates the object in place. */ static jpc_enc_rlvl_t *rlvl_create(jpc_enc_rlvl_t *rlvl, jpc_enc_cp_t *cp, jpc_enc_tcmpt_t *tcmpt, jpc_tsfb_band_t *bandinfos) { @@ -2234,6 +2250,10 @@ error: return 0; } +/* Note: Since jpc_enc_rlvl_t objects are created in-place, they might +potentially be destroyed multiple times at different levels in the call +chain. So, destroyed subobjects must be marked as destroyed to prevent +problems such as double frees. */ static void rlvl_destroy(jpc_enc_rlvl_t *rlvl) { jpc_enc_band_t *band; @@ -2245,9 +2265,11 @@ static void rlvl_destroy(jpc_enc_rlvl_t band_destroy(band); } jas_free(rlvl->bands); + rlvl->bands = NULL; } } +/* Note: This constructor creates the object in place. */ static jpc_enc_band_t *band_create(jpc_enc_band_t *band, jpc_enc_cp_t *cp, jpc_enc_rlvl_t *rlvl, jpc_tsfb_band_t *bandinfos) { @@ -2315,6 +2337,10 @@ error: return 0; } +/* Note: Since jpc_enc_band_t objects are created in-place, they might +potentially be destroyed multiple times at different levels in the call +chain. So, destroyed subobjects must be marked as destroyed to prevent +problems such as double frees. */ static void band_destroy(jpc_enc_band_t *band) { jpc_enc_prc_t *prc; @@ -2328,12 +2354,15 @@ static void band_destroy(jpc_enc_band_t prc_destroy(prc); } jas_free(band->prcs); + band->prcs = NULL; } if (band->data) { jas_seq2d_destroy(band->data); + band->data = NULL; } } +/* Note: This constructor creates the object in place. */ static jpc_enc_prc_t *prc_create(jpc_enc_prc_t *prc, jpc_enc_cp_t *cp, jpc_enc_band_t *band) { uint_fast32_t prcno; @@ -2459,6 +2488,10 @@ error: return 0; } +/* Note: Since jpc_enc_prc_t objects are created in-place, they might +potentially be destroyed multiple times at different levels in the call +chain. So, destroyed subobjects must be marked as destroyed to prevent +problems such as double frees. */ static void prc_destroy(jpc_enc_prc_t *prc) { jpc_enc_cblk_t *cblk; @@ -2470,22 +2503,29 @@ static void prc_destroy(jpc_enc_prc_t *p cblk_destroy(cblk); } jas_free(prc->cblks); + prc->cblks = NULL; } if (prc->incltree) { jpc_tagtree_destroy(prc->incltree); + prc->incltree = NULL; } if (prc->nlibtree) { jpc_tagtree_destroy(prc->nlibtree); + prc->nlibtree = NULL; } if (prc->savincltree) { jpc_tagtree_destroy(prc->savincltree); + prc->savincltree = NULL; } if (prc->savnlibtree) { jpc_tagtree_destroy(prc->savnlibtree); + prc->savnlibtree = NULL; } } -static jpc_enc_cblk_t *cblk_create(jpc_enc_cblk_t *cblk, jpc_enc_cp_t *cp, jpc_enc_prc_t *prc) +/* Note: This constructor creates the object in place. */ +static jpc_enc_cblk_t *cblk_create(jpc_enc_cblk_t *cblk, jpc_enc_cp_t *cp, + jpc_enc_prc_t *prc) { jpc_enc_band_t *band; uint_fast32_t cblktlx; @@ -2543,6 +2583,10 @@ error: return 0; } +/* Note: Since jpc_enc_cblk_t objects are created in-place, they might +potentially be destroyed multiple times at different levels in the call +chain. So, destroyed subobjects must be marked as destroyed to prevent +problems such as double frees. */ static void cblk_destroy(jpc_enc_cblk_t *cblk) { uint_fast16_t passno; @@ -2553,18 +2597,23 @@ static void cblk_destroy(jpc_enc_cblk_t pass_destroy(pass); } jas_free(cblk->passes); + cblk->passes = NULL; } if (cblk->stream) { jas_stream_close(cblk->stream); + cblk->stream = NULL; } if (cblk->mqenc) { jpc_mqenc_destroy(cblk->mqenc); + cblk->mqenc = NULL; } if (cblk->data) { jas_seq2d_destroy(cblk->data); + cblk->data = NULL; } if (cblk->flags) { jas_seq2d_destroy(cblk->flags); + cblk->flags = NULL; } }