CVE-2016-10266: Divide By Zero (CWE-369)
value: LibTIFF 4.0.7 allows remote attackers to cause a denial of service (divide-by-zero error and application crash) via a crafted TIFF image, related to libtiff/tif_read.c:351:22.
CWE description: The product divides a value by zero.
CVSS v3 base score: 5.5
Published: 2017-03-24T19:59Z
Repository: https://github.com/vadz/libtiff
Language: Other
Files changed: ChangeLog, libtiff/tif_read.c, libtiff/tiffiop.h
Commit date: 2016-12-02 21:56:56 +0000
Commit message: * libtiff/tif_read.c, libtiff/tiffiop.h: fix uint32 overflow in
TIFFReadEncodedStrip() that caused an integer division by zero.
Reported by Agostino Sarubbo.
Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2596

Diff: diff --git a/ChangeLog b/ChangeLog
index 46a5d7c57..668b66add 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
+2016-12-02 Even Rouault <even.rouault at spatialys.com>
+
+	* libtiff/tif_read.c, libtiff/tiffiop.h: fix uint32 overflow in
+	TIFFReadEncodedStrip() that caused an integer division by zero.
+	Reported by Agostino Sarubbo.
+	Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2596
+
 2016-11-20 Even Rouault <even.rouault at spatialys.com>
 
 	* libtiff/tif_getimage.c, libtiff/tif_open.c: add parenthesis to
 	fix cppcheck clarifyCalculation warnings
 	* libtiff/tif_predict.c, libtiff/tif_print.c: fix printf unsigned
diff --git a/libtiff/tif_read.c b/libtiff/tif_read.c
index c26c55f44..52bbf507f 100644
--- a/libtiff/tif_read.c
+++ b/libtiff/tif_read.c
@@ -344,11 +344,11 @@ TIFFReadEncodedStrip(TIFF* tif, uint32 strip, void* buf, tmsize_t size)
 	 * of the separations).
 	 */
 	rowsperstrip=td->td_rowsperstrip;
 	if (rowsperstrip>td->td_imagelength)
 		rowsperstrip=td->td_imagelength;
-	stripsperplane=((td->td_imagelength+rowsperstrip-1)/rowsperstrip);
+	stripsperplane= TIFFhowmany_32_maxuint_compat(td->td_imagelength, rowsperstrip);
 	stripinplane=(strip%stripsperplane);
 	plane=(uint16)(strip/stripsperplane);
 	rows=td->td_imagelength-stripinplane*rowsperstrip;
 	if (rows>rowsperstrip)
 		rows=rowsperstrip;
diff --git a/libtiff/tiffiop.h b/libtiff/tiffiop.h
index ffbb647bc..cb59460ae 100644
--- a/libtiff/tiffiop.h
+++ b/libtiff/tiffiop.h
@@ -248,10 +248,14 @@ struct tiff {
 
 /* NB: the uint32 casts are to silence certain ANSI-C compilers */
 #define TIFFhowmany_32(x, y) (((uint32)x < (0xffffffff - (uint32)(y-1))) ? \
 			   ((((uint32)(x))+(((uint32)(y))-1))/((uint32)(y))) : \
 			   0U)
+/* Variant of TIFFhowmany_32() that doesn't return 0 if x close to MAXUINT. */
+/* Caution: TIFFhowmany_32_maxuint_compat(x,y)*y might overflow */
+#define TIFFhowmany_32_maxuint_compat(x, y) \
+			   (((uint32)(x) / (uint32)(y)) + ((((uint32)(x) % (uint32)(y)) != 0) ? 1 : 0))
 #define TIFFhowmany8_32(x) (((x)&0x07)?((uint32)(x)>>3)+1:(uint32)(x)>>3)
 #define TIFFroundup_32(x, y) (TIFFhowmany_32(x,y)*(y))
 #define TIFFhowmany_64(x, y) ((((uint64)(x))+(((uint64)(y))-1))/((uint64)(y)))
 #define TIFFhowmany8_64(x) (((x)&0x07)?((uint64)(x)>>3)+1:(uint64)(x)>>3)
 #define TIFFroundup_64(x, y) (TIFFhowmany_64(x,y)*(y))

Vulnerable code: 	stripsperplane=((td->td_imagelength+rowsperstrip-1)/rowsperstrip);
Fixed code: 2016-12-02 Even Rouault <even.rouault at spatialys.com>

	* libtiff/tif_read.c, libtiff/tiffiop.h: fix uint32 overflow in
	TIFFReadEncodedStrip() that caused an integer division by zero.
	Reported by Agostino Sarubbo.
	Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2596

	stripsperplane= TIFFhowmany_32_maxuint_compat(td->td_imagelength, rowsperstrip);
/* Variant of TIFFhowmany_32() that doesn't return 0 if x close to MAXUINT. */
/* Caution: TIFFhowmany_32_maxuint_compat(x,y)*y might overflow */
#define TIFFhowmany_32_maxuint_compat(x, y) \
			   (((uint32)(x) / (uint32)(y)) + ((((uint32)(x) % (uint32)(y)) != 0) ? 1 : 0))