Blob Blame History Raw
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;
 	}
 }