Backport of the upstream patch:
From 03fe49ab96bf65fea784cdc256507ea88267fc7c Mon Sep 17 00:00:00 2001
From: Michael Adams <mdadams@ece.uvic.ca>
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;
}
}