CVE-2015-8784: Out-of-bounds Write (CWE-787)
value: The NeXTDecode function in tif_next.c in LibTIFF allows remote attackers to cause a denial of service (out-of-bounds write) via a crafted TIFF image, as demonstrated by libtiff5.tif.
CWE description: The product writes data past the end, or before the beginning, of the intended buffer.
CVSS v3 base score: 6.5
Published: 2016-04-13T17:59Z
Repository: https://github.com/vadz/libtiff
Language: Other
Files changed: ChangeLog, libtiff/tif_next.c
Commit date: 2015-12-27 16:55:20 +0000
Commit message: * libtiff/tif_next.c: fix potential out-of-bound write in NeXTDecode()
triggered by http://lcamtuf.coredump.cx/afl/vulns/libtiff5.tif
(bugzilla #2508)

Diff: diff --git a/ChangeLog b/ChangeLog
index b8aa23c8..04926a38 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
+2015-12-27  Even Rouault <even.rouault at spatialys.com>
+
+	* libtiff/tif_next.c: fix potential out-of-bound write in NeXTDecode()
+	triggered by http://lcamtuf.coredump.cx/afl/vulns/libtiff5.tif
+	(bugzilla #2508)
+
 2015-12-27  Even Rouault <even.rouault at spatialys.com>
 
 	* libtiff/tif_luv.c: fix potential out-of-bound writes in decode
 	functions in non debug builds by replacing assert()s by regular if
 	checks (bugzilla #2522).
diff --git a/libtiff/tif_next.c b/libtiff/tif_next.c
index dd669cc7..0a5b6352 100644
--- a/libtiff/tif_next.c
+++ b/libtiff/tif_next.c
@@ -35,11 +35,11 @@
 #define SETPIXEL(op, v) {			\
 	switch (npixels++ & 3) {		\
 	case 0:	op[0]  = (unsigned char) ((v) << 6); break;	\
 	case 1:	op[0] |= (v) << 4; break;	\
 	case 2:	op[0] |= (v) << 2; break;	\
-	case 3:	*op++ |= (v);	   break;	\
+	case 3:	*op++ |= (v);	   op_offset++; break;	\
 	}					\
 }
 
 #define LITERALROW	0x00
 #define LITERALSPAN	0x40
@@ -104,10 +104,11 @@ NeXTDecode(TIFF* tif, uint8* buf, tmsize_t occ, uint16 s)
 		default: {
 			uint32 npixels = 0, grey;
 			uint32 imagewidth = tif->tif_dir.td_imagewidth;
             if( isTiled(tif) )
                 imagewidth = tif->tif_dir.td_tilewidth;
+            tmsize_t op_offset = 0;
 
 			/*
 			 * The scanline is composed of a sequence of constant
 			 * color ``runs''.  We shift into ``run mode'' and
 			 * interpret bytes as codes of the form
@@ -120,14 +121,19 @@ NeXTDecode(TIFF* tif, uint8* buf, tmsize_t occ, uint16 s)
 				/*
 				 * Ensure the run does not exceed the scanline
 				 * bounds, potentially resulting in a security
 				 * issue.
 				 */
-				while (n-- > 0 && npixels < imagewidth)
+				while (n-- > 0 && npixels < imagewidth && op_offset < scanline)
 					SETPIXEL(op, grey);
 				if (npixels >= imagewidth)
 					break;
+                if (op_offset >= scanline ) {
+                    TIFFErrorExt(tif->tif_clientdata, module, "Invalid data for scanline %ld",
+                        (long) tif->tif_row);
+                    return (0);
+                }
 				if (cc == 0)
 					goto bad;
 				n = *bp++, cc--;
 			}
 			break;

Vulnerable code: 	case 3:	*op++ |= (v);	   break;	\
				while (n-- > 0 && npixels < imagewidth)
Fixed code: 2015-12-27  Even Rouault <even.rouault at spatialys.com>

	* libtiff/tif_next.c: fix potential out-of-bound write in NeXTDecode()
	triggered by http://lcamtuf.coredump.cx/afl/vulns/libtiff5.tif
	(bugzilla #2508)

	case 3:	*op++ |= (v);	   op_offset++; break;	\
            tmsize_t op_offset = 0;
				while (n-- > 0 && npixels < imagewidth && op_offset < scanline)
                if (op_offset >= scanline ) {
                    TIFFErrorExt(tif->tif_clientdata, module, "Invalid data for scanline %ld",
                        (long) tif->tif_row);
                    return (0);
                }