CVE-2016-8690: NULL Pointer Dereference (CWE-476)
value: The bmp_getdata function in libjasper/bmp/bmp_dec.c in JasPer before 1.900.5 allows remote attackers to cause a denial of service (NULL pointer dereference) via a crafted BMP image in an imginfo command.
CWE description: The product dereferences a pointer that it expects to be valid but is NULL.
CVSS v3 base score: 5.5
Published: 2017-02-15T19:59Z
Repository: https://github.com/mdadams/jasper
Language: C
Files changed: src/appl/imginfo.c, src/libjasper/bmp/bmp_dec.c
Commit date: 2016-10-15 20:32:23 -0700
Commit message: Fixed a sanitizer failure in the BMP codec.
Also, added a --debug-level command line option to the imginfo command
for debugging purposes.

Diff: diff --git a/src/appl/imginfo.c b/src/appl/imginfo.c
index 8af19e9..f458a97 100644
--- a/src/appl/imginfo.c
+++ b/src/appl/imginfo.c
@@ -83,11 +83,12 @@
 
 typedef enum {
 	OPT_HELP,
 	OPT_VERSION,
 	OPT_VERBOSE,
-	OPT_INFILE
+	OPT_INFILE,
+	OPT_DEBUG
 } optid_t;
 
 /******************************************************************************\
 *
 \******************************************************************************/
@@ -102,10 +103,11 @@ static void cmdinfo(void);
 static jas_opt_t opts[] = {
 	{OPT_HELP, "help", 0},
 	{OPT_VERSION, "version", 0},
 	{OPT_VERBOSE, "verbose", 0},
 	{OPT_INFILE, "f", JAS_OPT_HASARG},
+	{OPT_DEBUG, "debug-level", JAS_OPT_HASARG},
 	{-1, 0, 0}
 };
 
 static char *cmdname = 0;
 
@@ -124,19 +126,21 @@ int main(int argc, char **argv)
 	int height;
 	int depth;
 	int numcmpts;
 	int verbose;
 	char *fmtname;
+	int debug;
 
 	if (jas_init()) {
 		abort();
 	}
 
 	cmdname = argv[0];
 
 	infile = 0;
 	verbose = 0;
+	debug = 0;
 
 	/* Parse the command line options. */
 	while ((id = jas_getopt(argc, argv, opts)) >= 0) {
 		switch (id) {
 		case OPT_VERBOSE:
@@ -144,20 +148,25 @@ int main(int argc, char **argv)
 			break;
 		case OPT_VERSION:
 			printf("%s\n", JAS_VERSION);
 			exit(EXIT_SUCCESS);
 			break;
+		case OPT_DEBUG:
+			debug = atoi(jas_optarg);
+			break;
 		case OPT_INFILE:
 			infile = jas_optarg;
 			break;
 		case OPT_HELP:
 		default:
 			usage();
 			break;
 		}
 	}
 
+	jas_setdbglevel(debug);
+
 	/* Open the image file. */
 	if (infile) {
 		/* The image is to be read from a file. */
 		if (!(instream = jas_stream_fopen(infile, "rb"))) {
 			fprintf(stderr, "cannot open input image file %s\n", infile);
@@ -175,10 +184,11 @@ int main(int argc, char **argv)
 		fprintf(stderr, "unknown image format\n");
 	}
 
 	/* Decode the image. */
 	if (!(image = jas_image_decode(instream, fmtid, 0))) {
+		jas_stream_close(instream);
 		fprintf(stderr, "cannot load image\n");
 		return EXIT_FAILURE;
 	}
 
 	/* Close the image file. */
diff --git a/src/libjasper/bmp/bmp_dec.c b/src/libjasper/bmp/bmp_dec.c
index 7a6dcb1..6e7d880 100644
--- a/src/libjasper/bmp/bmp_dec.c
+++ b/src/libjasper/bmp/bmp_dec.c
@@ -75,10 +75,11 @@
 
 #include "jasper/jas_types.h"
 #include "jasper/jas_stream.h"
 #include "jasper/jas_image.h"
 #include "jasper/jas_malloc.h"
+#include "jasper/jas_debug.h"
 
 #include "bmp_cod.h"
 
 /******************************************************************************\
 * Local prototypes.
@@ -120,16 +121,26 @@ jas_image_t *bmp_decode(jas_stream_t *in, char *optstr)
 	/* Read the bitmap header. */
 	if (bmp_gethdr(in, &hdr)) {
 		jas_eprintf("cannot get header\n");
 		return 0;
 	}
+	JAS_DBGLOG(1, (
+	  "BMP header: magic 0x%x; siz %d; res1 %d; res2 %d; off %d\n",
+	  hdr.magic, hdr.siz, hdr.reserved1, hdr.reserved2, hdr.off
+	  ));
 
 	/* Read the bitmap information. */
 	if (!(info = bmp_getinfo(in))) {
 		jas_eprintf("cannot get info\n");
 		return 0;
 	}
+	JAS_DBGLOG(1,
+	  ("BMP information: len %d; width %d; height %d; numplanes %d; "
+	  "depth %d; enctype %d; siz %d; hres %d; vres %d; numcolors %d; "
+	  "mincolors %d\n", info->len, info->width, info->height, info->numplanes,
+	  info->depth, info->enctype, info->siz, info->hres, info->vres,
+	  info->numcolors, info->mincolors));
 
 	/* Ensure that we support this type of BMP file. */
 	if (!bmp_issupported(&hdr, info)) {
 		jas_eprintf("error: unsupported BMP encoding\n");
 		bmp_info_destroy(info);
@@ -438,11 +449,11 @@ static int bmp_getint32(jas_stream_t *in, int_fast32_t *val)
 	int c;
 	for (n = 4, v = 0;;) {
 		if ((c = jas_stream_getc(in)) == EOF) {
 			return -1;
 		}
-		v |= (c << 24);
+		v |= (JAS_CAST(uint_fast32_t, c) << 24);
 		if (--n <= 0) {
 			break;
 		}
 		v >>= 8;
 	}

Vulnerable code: 	OPT_INFILE
		v |= (c << 24);
Fixed code: 	OPT_INFILE,
	OPT_DEBUG
	{OPT_DEBUG, "debug-level", JAS_OPT_HASARG},
	int debug;
	debug = 0;
		case OPT_DEBUG:
			debug = atoi(jas_optarg);
			break;
	jas_setdbglevel(debug);

		jas_stream_close(instream);
#include "jasper/jas_debug.h"
	JAS_DBGLOG(1, (
	  "BMP header: magic 0x%x; siz %d; res1 %d; res2 %d; off %d\n",
	  hdr.magic, hdr.siz, hdr.reserved1, hdr.reserved2, hdr.off
	  ));
	JAS_DBGLOG(1,
	  ("BMP information: len %d; width %d; height %d; numplanes %d; "
	  "depth %d; enctype %d; siz %d; hres %d; vres %d; numcolors %d; "
	  "mincolors %d\n", info->len, info->width, info->height, info->numplanes,
	  info->depth, info->enctype, info->siz, info->hres, info->vres,
	  info->numcolors, info->mincolors));
		v |= (JAS_CAST(uint_fast32_t, c) << 24);