CVE-2017-6850: NULL Pointer Dereference (CWE-476)
value: The jp2_cdef_destroy function in jp2_cod.c in JasPer before 2.0.13 allows remote attackers to cause a denial of service (NULL pointer dereference) via a crafted image.
CWE description: The product dereferences a pointer that it expects to be valid but is NULL.
CVSS v3 base score: 5.5
Published: 2017-03-15T14:59Z
Repository: https://github.com/mdadams/jasper
Language: C
Files changed: src/libjasper/base/jas_stream.c, src/libjasper/jp2/jp2_cod.c
Commit date: 2017-03-04 14:43:24 -0800
Commit message: Fixed bugs due to uninitialized data in the JP2 decoder.
Also, added some comments marking I/O stream interfaces that probably
need to be changed (in the long term) to fix integer overflow problems.

Diff: diff --git a/src/libjasper/base/jas_stream.c b/src/libjasper/base/jas_stream.c
index 327ee57..d70408f 100644
--- a/src/libjasper/base/jas_stream.c
+++ b/src/libjasper/base/jas_stream.c
@@ -662,10 +662,11 @@ int jas_stream_ungetc(jas_stream_t *stream, int c)
 	++stream->cnt_;
 	*stream->ptr_ = c;
 	return 0;
 }
 
+/* FIXME integral type */
 int jas_stream_read(jas_stream_t *stream, void *buf, int cnt)
 {
 	int n;
 	int c;
 	char *bufptr;
@@ -688,10 +689,11 @@ int jas_stream_read(jas_stream_t *stream, void *buf, int cnt)
 	}
 
 	return n;
 }
 
+/* FIXME integral type */
 int jas_stream_write(jas_stream_t *stream, const void *buf, int cnt)
 {
 	int n;
 	const char *bufptr;
 
@@ -740,10 +742,11 @@ int jas_stream_puts(jas_stream_t *stream, const char *s)
 		++s;
 	}
 	return 0;
 }
 
+/* FIXME integral type */
 char *jas_stream_gets(jas_stream_t *stream, char *buf, int bufsize)
 {
 	int c;
 	char *bufptr;
 	assert(bufsize > 0);
@@ -763,10 +766,11 @@ char *jas_stream_gets(jas_stream_t *stream, char *buf, int bufsize)
 	}
 	*bufptr = '\0';
 	return buf;
 }
 
+/* FIXME integral type */
 int jas_stream_gobble(jas_stream_t *stream, int n)
 {
 	int m;
 
 	JAS_DBGLOG(100, ("jas_stream_gobble(%p, %d)\n", stream, n));
@@ -781,10 +785,11 @@ int jas_stream_gobble(jas_stream_t *stream, int n)
 		}
 	}
 	return n;
 }
 
+/* FIXME integral type */
 int jas_stream_pad(jas_stream_t *stream, int n, int c)
 {
 	int m;
 
 	JAS_DBGLOG(100, ("jas_stream_pad(%p, %d, %d)\n", stream, n, c));
@@ -883,10 +888,11 @@ long jas_stream_tell(jas_stream_t *stream)
 
 /******************************************************************************\
 * Buffer initialization code.
 \******************************************************************************/
 
+/* FIXME integral type */
 static void jas_stream_initbuf(jas_stream_t *stream, int bufmode, char *buf,
   int bufsize)
 {
 	/* If this function is being called, the buffer should not have been
 	  initialized yet. */
@@ -1058,10 +1064,11 @@ static int jas_strtoopenmode(const char *s)
 		++s;
 	}
 	return openmode;
 }
 
+/* FIXME integral type */
 int jas_stream_copy(jas_stream_t *out, jas_stream_t *in, int n)
 {
 	int all;
 	int c;
 	int m;
@@ -1083,19 +1090,21 @@ int jas_stream_copy(jas_stream_t *out, jas_stream_t *in, int n)
 		--m;
 	}
 	return 0;
 }
 
+/* FIXME integral type */
 long jas_stream_setrwcount(jas_stream_t *stream, long rwcnt)
 {
 	int old;
 
 	old = stream->rwcnt_;
 	stream->rwcnt_ = rwcnt;
 	return old;
 }
 
+/* FIXME integral type */
 int jas_stream_display(jas_stream_t *stream, FILE *fp, int n)
 {
 	unsigned char buf[16];
 	int i;
 	int j;
@@ -1166,10 +1175,11 @@ long jas_stream_length(jas_stream_t *stream)
 
 /******************************************************************************\
 * Memory stream object.
 \******************************************************************************/
 
+/* FIXME integral type */
 static int mem_read(jas_stream_obj_t *obj, char *buf, int cnt)
 {
 	ssize_t n;
 	assert(cnt >= 0);
 	assert(buf);
@@ -1207,10 +1217,11 @@ static int mem_resize(jas_stream_memobj_t *m, size_t bufsize)
 	m->buf_ = buf;
 	m->bufsize_ = bufsize;
 	return 0;
 }
 
+/* FIXME integral type */
 static int mem_write(jas_stream_obj_t *obj, char *buf, int cnt)
 {
 	size_t n;
 	int ret;
 	jas_stream_memobj_t *m = (jas_stream_memobj_t *)obj;
@@ -1262,10 +1273,11 @@ static int mem_write(jas_stream_obj_t *obj, char *buf, int cnt)
 	}
 	assert(ret == cnt);
 	return ret;
 }
 
+/* FIXME integral type */
 static long mem_seek(jas_stream_obj_t *obj, long offset, int origin)
 {
 	jas_stream_memobj_t *m = (jas_stream_memobj_t *)obj;
 	size_t newpos;
 
@@ -1308,26 +1320,29 @@ static int mem_close(jas_stream_obj_t *obj)
 
 /******************************************************************************\
 * File stream object.
 \******************************************************************************/
 
+/* FIXME integral type */
 static int file_read(jas_stream_obj_t *obj, char *buf, int cnt)
 {
 	jas_stream_fileobj_t *fileobj;
 	JAS_DBGLOG(100, ("file_read(%p, %p, %d)\n", obj, buf, cnt));
 	fileobj = JAS_CAST(jas_stream_fileobj_t *, obj);
 	return read(fileobj->fd, buf, cnt);
 }
 
+/* FIXME integral type */
 static int file_write(jas_stream_obj_t *obj, char *buf, int cnt)
 {
 	jas_stream_fileobj_t *fileobj;
 	JAS_DBGLOG(100, ("file_write(%p, %p, %d)\n", obj, buf, cnt));
 	fileobj = JAS_CAST(jas_stream_fileobj_t *, obj);
 	return write(fileobj->fd, buf, cnt);
 }
 
+/* FIXME integral type */
 static long file_seek(jas_stream_obj_t *obj, long offset, int origin)
 {
 	jas_stream_fileobj_t *fileobj;
 	JAS_DBGLOG(100, ("file_seek(%p, %ld, %d)\n", obj, offset, origin));
 	fileobj = JAS_CAST(jas_stream_fileobj_t *, obj);
@@ -1350,10 +1365,11 @@ static int file_close(jas_stream_obj_t *obj)
 
 /******************************************************************************\
 * Stdio file stream object.
 \******************************************************************************/
 
+/* FIXME integral type */
 static int sfile_read(jas_stream_obj_t *obj, char *buf, int cnt)
 {
 	FILE *fp;
 	size_t n;
 	int result;
@@ -1365,20 +1381,22 @@ static int sfile_read(jas_stream_obj_t *obj, char *buf, int cnt)
 	}
 	result = JAS_CAST(int, n);
 	return result;
 }
 
+/* FIXME integral type */
 static int sfile_write(jas_stream_obj_t *obj, char *buf, int cnt)
 {
 	FILE *fp;
 	size_t n;
 	JAS_DBGLOG(100, ("sfile_write(%p, %p, %d)\n", obj, buf, cnt));
 	fp = JAS_CAST(FILE *, obj);
 	n = fwrite(buf, 1, cnt, fp);
 	return (n != JAS_CAST(size_t, cnt)) ? (-1) : cnt;
 }
 
+/* FIXME integral type */
 static long sfile_seek(jas_stream_obj_t *obj, long offset, int origin)
 {
 	FILE *fp;
 	JAS_DBGLOG(100, ("sfile_seek(%p, %ld, %d)\n", obj, offset, origin));
 	fp = JAS_CAST(FILE *, obj);
diff --git a/src/libjasper/jp2/jp2_cod.c b/src/libjasper/jp2/jp2_cod.c
index 7f3608a..8d98a2c 100644
--- a/src/libjasper/jp2/jp2_cod.c
+++ b/src/libjasper/jp2/jp2_cod.c
@@ -181,19 +181,32 @@ jp2_boxinfo_t jp2_boxinfo_unk = {
 
 /******************************************************************************\
 * Box constructor.
 \******************************************************************************/
 
-jp2_box_t *jp2_box_create(int type)
+jp2_box_t *jp2_box_create0()
 {
 	jp2_box_t *box;
-	jp2_boxinfo_t *boxinfo;
-
 	if (!(box = jas_malloc(sizeof(jp2_box_t)))) {
 		return 0;
 	}
 	memset(box, 0, sizeof(jp2_box_t));
+	box->type = 0;
+	box->len = 0;
+	// Mark the box data as never having been constructed
+	// so that we will not errantly attempt to destroy it later.
+	box->ops = &jp2_boxinfo_unk.ops;
+	return box;
+}
+
+jp2_box_t *jp2_box_create(int type)
+{
+	jp2_box_t *box;
+	jp2_boxinfo_t *boxinfo;
+	if (!(box = jp2_box_create0())) {
+		return 0;
+	}
 	box->type = type;
 	box->len = 0;
 	if (!(boxinfo = jp2_boxinfolookup(type))) {
 		return 0;
 	}
@@ -246,29 +259,26 @@ jp2_box_t *jp2_box_get(jas_stream_t *in)
 	bool dataflag;
 
 	box = 0;
 	tmpstream = 0;
 
-	if (!(box = jas_malloc(sizeof(jp2_box_t)))) {
+	if (!(box = jp2_box_create0())) {
 		goto error;
 	}
-
-	// Mark the box data as never having been constructed
-	// so that we will not errantly attempt to destroy it later.
-	box->ops = &jp2_boxinfo_unk.ops;
-
 	if (jp2_getuint32(in, &len) || jp2_getuint32(in, &box->type)) {
 		goto error;
 	}
 	boxinfo = jp2_boxinfolookup(box->type);
 	box->info = boxinfo;
 	box->len = len;
 	JAS_DBGLOG(10, (
-	  "preliminary processing of JP2 box: type=%c%s%c (0x%08x); length=%d\n",
+	  "preliminary processing of JP2 box: "
+	  "type=%c%s%c (0x%08x); length=%"PRIuFAST32"\n",
 	  '"', boxinfo->name, '"', box->type, box->len
 	  ));
 	if (box->len == 1) {
+		JAS_DBGLOG(10, ("big length\n"));
 		if (jp2_getuint64(in, &extlen)) {
 			goto error;
 		}
 		if (extlen > 0xffffffffUL) {
 			jas_eprintf("warning: cannot handle large 64-bit box length\n");
@@ -380,10 +390,11 @@ static int jp2_ihdr_getdata(jp2_box_t *box, jas_stream_t *in)
 
 static int jp2_bpcc_getdata(jp2_box_t *box, jas_stream_t *in)
 {
 	jp2_bpcc_t *bpcc = &box->data.bpcc;
 	unsigned int i;
+	bpcc->bpcs = 0;
 	bpcc->numcmpts = box->datalen;
 	if (!(bpcc->bpcs = jas_alloc2(bpcc->numcmpts, sizeof(uint_fast8_t)))) {
 		return -1;
 	}
 	for (i = 0; i < bpcc->numcmpts; ++i) {
@@ -460,10 +471,11 @@ static void jp2_colr_destroy(jp2_box_t *box)
 static int jp2_cdef_getdata(jp2_box_t *box, jas_stream_t *in)
 {
 	jp2_cdef_t *cdef = &box->data.cdef;
 	jp2_cdefchan_t *chan;
 	unsigned int channo;
+	cdef->ents = 0;
 	if (jp2_getuint16(in, &cdef->numchans)) {
 		return -1;
 	}
 	if (!(cdef->ents = jas_alloc2(cdef->numchans, sizeof(jp2_cdefchan_t)))) {
 		return -1;
@@ -516,11 +528,13 @@ int jp2_box_put(jp2_box_t *box, jas_stream_t *out)
 			goto error;
 		}
 	}
 
 	if (dataflag) {
-		if (jas_stream_copy(out, tmpstream, box->len - JP2_BOX_HDRLEN(false))) {
+		if (jas_stream_copy(out, tmpstream, box->len -
+		  JP2_BOX_HDRLEN(false))) {
+			jas_eprintf("cannot copy box data\n");
 			goto error;
 		}
 		jas_stream_close(tmpstream);
 	}
 
@@ -775,10 +789,11 @@ static void jp2_cmap_destroy(jp2_box_t *box)
 static int jp2_cmap_getdata(jp2_box_t *box, jas_stream_t *in)
 {
 	jp2_cmap_t *cmap = &box->data.cmap;
 	jp2_cmapent_t *ent;
 	unsigned int i;
+	cmap->ents = 0;
 
 	cmap->numchans = (box->datalen) / 4;
 	if (!(cmap->ents = jas_alloc2(cmap->numchans, sizeof(jp2_cmapent_t)))) {
 		return -1;
 	}
@@ -833,10 +848,11 @@ static int jp2_pclr_getdata(jp2_box_t *box, jas_stream_t *in)
 	unsigned int i;
 	unsigned int j;
 	int_fast32_t x;
 
 	pclr->lutdata = 0;
+	pclr->bpc = 0;
 
 	if (jp2_getuint16(in, &pclr->numlutents) ||
 	  jp2_getuint8(in, &pclr->numchans)) {
 		return -1;
 	}
@@ -867,13 +883,13 @@ static int jp2_pclr_getdata(jp2_box_t *box, jas_stream_t *in)
 static int jp2_pclr_putdata(jp2_box_t *box, jas_stream_t *out)
 {
 #if 0
 	jp2_pclr_t *pclr = &box->data.pclr;
 #endif
-/* Eliminate warning about unused variable. */
-box = 0;
-out = 0;
+	/* Eliminate warning about unused variable. */
+	box = 0;
+	out = 0;
 	return -1;
 }
 
 static void jp2_pclr_dumpdata(jp2_box_t *box, FILE *out)
 {

Vulnerable code: jp2_box_t *jp2_box_create(int type)
	jp2_boxinfo_t *boxinfo;

	if (!(box = jas_malloc(sizeof(jp2_box_t)))) {

	// Mark the box data as never having been constructed
	// so that we will not errantly attempt to destroy it later.
	box->ops = &jp2_boxinfo_unk.ops;

	  "preliminary processing of JP2 box: type=%c%s%c (0x%08x); length=%d\n",
		if (jas_stream_copy(out, tmpstream, box->len - JP2_BOX_HDRLEN(false))) {
/* Eliminate warning about unused variable. */
box = 0;
out = 0;
Fixed code: /* FIXME integral type */
/* FIXME integral type */
/* FIXME integral type */
/* FIXME integral type */
/* FIXME integral type */
/* FIXME integral type */
/* FIXME integral type */
/* FIXME integral type */
/* FIXME integral type */
/* FIXME integral type */
/* FIXME integral type */
/* FIXME integral type */
/* FIXME integral type */
/* FIXME integral type */
/* FIXME integral type */
/* FIXME integral type */
/* FIXME integral type */
/* FIXME integral type */
jp2_box_t *jp2_box_create0()
	box->type = 0;
	box->len = 0;
	// Mark the box data as never having been constructed
	// so that we will not errantly attempt to destroy it later.
	box->ops = &jp2_boxinfo_unk.ops;
	return box;
}

jp2_box_t *jp2_box_create(int type)
{
	jp2_box_t *box;
	jp2_boxinfo_t *boxinfo;
	if (!(box = jp2_box_create0())) {
		return 0;
	}
	if (!(box = jp2_box_create0())) {
	  "preliminary processing of JP2 box: "
	  "type=%c%s%c (0x%08x); length=%"PRIuFAST32"\n",
		JAS_DBGLOG(10, ("big length\n"));
	bpcc->bpcs = 0;
	cdef->ents = 0;
		if (jas_stream_copy(out, tmpstream, box->len -
		  JP2_BOX_HDRLEN(false))) {
			jas_eprintf("cannot copy box data\n");
	cmap->ents = 0;
	pclr->bpc = 0;
	/* Eliminate warning about unused variable. */
	box = 0;
	out = 0;