CVE-2016-9389: Other (NVD-CWE-Other)
value: The jpc_irct and jpc_iict functions in jpc_mct.c in JasPer before 1.900.14 allow remote attackers to cause a denial of service (assertion failure).
CWE description: NVD is only using a subset of CWE for mapping instead of the entire CWE, and the weakness type is not covered by that subset.
CVSS v3 base score: 7.5
Published: 2017-03-23T18:59Z
Repository: https://github.com/mdadams/jasper
Language: C
Files changed: src/libjasper/base/jas_image.c, src/libjasper/include/jasper/jas_image.h, src/libjasper/jpc/jpc_dec.c
Commit date: 2016-10-24 07:26:40 -0700
Commit message: The component domains must be the same for the ICT/RCT in the JPC codec.
This was previously enforced with an assertion.
Now, it is handled in a more graceful manner.

Diff: diff --git a/src/libjasper/base/jas_image.c b/src/libjasper/base/jas_image.c
index 16e7b19..b40ba0c 100644
--- a/src/libjasper/base/jas_image.c
+++ b/src/libjasper/base/jas_image.c
@@ -75,10 +75,11 @@
 #include <stdio.h>
 #include <string.h>
 #include <assert.h>
 #include <ctype.h>
 #include <inttypes.h>
+#include <stdbool.h>
 
 #include "jasper/jas_math.h"
 #include "jasper/jas_image.h"
 #include "jasper/jas_malloc.h"
 #include "jasper/jas_string.h"
@@ -653,10 +654,28 @@ int jas_image_fmtfromname(char *name)
 
 /******************************************************************************\
 * Miscellaneous operations.
 \******************************************************************************/
 
+bool jas_image_cmpt_domains_same(jas_image_t *image)
+{
+	int cmptno;
+	jas_image_cmpt_t *cmpt;
+	jas_image_cmpt_t *cmpt0;
+
+	cmpt0 = image->cmpts_[0];
+	for (cmptno = 1; cmptno < image->numcmpts_; ++cmptno) {
+		cmpt = image->cmpts_[cmptno];
+		if (cmpt->tlx_ != cmpt0->tlx_ || cmpt->tly_ != cmpt0->tly_ ||
+		  cmpt->hstep_ != cmpt0->hstep_ || cmpt->vstep_ != cmpt0->vstep_ ||
+		  cmpt->width_ != cmpt0->width_ || cmpt->height_ != cmpt0->height_) {
+			return 0;
+		}
+	}
+	return 1;
+}
+
 uint_fast32_t jas_image_rawsize(jas_image_t *image)
 {
 	uint_fast32_t rawsize;
 	int cmptno;
 	jas_image_cmpt_t *cmpt;
diff --git a/src/libjasper/include/jasper/jas_image.h b/src/libjasper/include/jasper/jas_image.h
index 3ccb749..163477e 100644
--- a/src/libjasper/include/jasper/jas_image.h
+++ b/src/libjasper/include/jasper/jas_image.h
@@ -77,10 +77,11 @@
 #include <jasper/jas_config.h>
 #include <jasper/jas_stream.h>
 #include <jasper/jas_seq.h>
 #include <jasper/jas_cm.h>
 #include <stdio.h>
+#include <stdbool.h>
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
@@ -397,10 +398,13 @@ void jas_image_destroy(jas_image_t *image);
   (plus "one"). */
 #define	jas_image_cmptbry(image, cmptno) \
 	((image)->cmpts_[cmptno]->tly_ + (image)->cmpts_[cmptno]->height_ * \
 	  (image)->cmpts_[cmptno]->vstep_)
 
+// Test if all components are specified at the same positions in space. */
+bool jas_image_cmpt_domains_same(jas_image_t *image);
+
 /* Get the raw size of an image (i.e., the nominal size of the image without
   any compression. */
 uint_fast32_t jas_image_rawsize(jas_image_t *image);
 
 /* Create an image from a stream in some specified format. */
diff --git a/src/libjasper/jpc/jpc_dec.c b/src/libjasper/jpc/jpc_dec.c
index 4f24660..95ac7c6 100644
--- a/src/libjasper/jpc/jpc_dec.c
+++ b/src/libjasper/jpc/jpc_dec.c
@@ -1089,18 +1089,26 @@ static int jpc_dec_tiledecode(jpc_dec_t *dec, jpc_dec_tile_t *tile)
 	case JPC_MCT_RCT:
 		if (dec->numcomps < 3) {
 			jas_eprintf("RCT requires at least three components\n");
 			return -1;
 		}
+		if (!jas_image_cmpt_domains_same(dec->image)) {
+			jas_eprintf("RCT requires all components have the same domain\n");
+			return -1;
+		}
 		jpc_irct(tile->tcomps[0].data, tile->tcomps[1].data,
 		  tile->tcomps[2].data);
 		break;
 	case JPC_MCT_ICT:
 		if (dec->numcomps < 3) {
 			jas_eprintf("ICT requires at least three components\n");
 			return -1;
 		}
+		if (!jas_image_cmpt_domains_same(dec->image)) {
+			jas_eprintf("RCT requires all components have the same domain\n");
+			return -1;
+		}
 		jpc_iict(tile->tcomps[0].data, tile->tcomps[1].data,
 		  tile->tcomps[2].data);
 		break;
 	}
 

Fixed code: #include <stdbool.h>
bool jas_image_cmpt_domains_same(jas_image_t *image)
{
	int cmptno;
	jas_image_cmpt_t *cmpt;
	jas_image_cmpt_t *cmpt0;

	cmpt0 = image->cmpts_[0];
	for (cmptno = 1; cmptno < image->numcmpts_; ++cmptno) {
		cmpt = image->cmpts_[cmptno];
		if (cmpt->tlx_ != cmpt0->tlx_ || cmpt->tly_ != cmpt0->tly_ ||
		  cmpt->hstep_ != cmpt0->hstep_ || cmpt->vstep_ != cmpt0->vstep_ ||
		  cmpt->width_ != cmpt0->width_ || cmpt->height_ != cmpt0->height_) {
			return 0;
		}
	}
	return 1;
}

#include <stdbool.h>
// Test if all components are specified at the same positions in space. */
bool jas_image_cmpt_domains_same(jas_image_t *image);

		if (!jas_image_cmpt_domains_same(dec->image)) {
			jas_eprintf("RCT requires all components have the same domain\n");
			return -1;
		}
		if (!jas_image_cmpt_domains_same(dec->image)) {
			jas_eprintf("RCT requires all components have the same domain\n");
			return -1;
		}