8ca2e9
Defend against integer overflow in buffer size calculations within tiff2pdf.
8ca2e9
CVE-2012-2113
8ca2e9
8ca2e9
8ca2e9
diff -Naur tiff-3.9.4.orig/tools/tiff2pdf.c tiff-3.9.4/tools/tiff2pdf.c
8ca2e9
--- tiff-3.9.4.orig/tools/tiff2pdf.c	2010-06-13 16:51:44.000000000 -0400
8ca2e9
+++ tiff-3.9.4/tools/tiff2pdf.c	2012-06-27 13:13:44.581229393 -0400
8ca2e9
@@ -44,6 +44,7 @@
8ca2e9
 # include <io.h>
8ca2e9
 #endif
8ca2e9
 
8ca2e9
+#include "tiffiop.h"
8ca2e9
 #include "tiffio.h"
8ca2e9
 
8ca2e9
 #ifndef HAVE_GETOPT
8ca2e9
@@ -414,6 +415,34 @@
8ca2e9
 	(void) handle, (void) data, (void) offset;
8ca2e9
 }
8ca2e9
 
8ca2e9
+static uint64
8ca2e9
+checkAdd64(uint64 summand1, uint64 summand2, T2P* t2p)
8ca2e9
+{
8ca2e9
+	uint64 bytes = summand1 + summand2;
8ca2e9
+
8ca2e9
+	if (bytes - summand1 != summand2) {
8ca2e9
+		TIFFError(TIFF2PDF_MODULE, "Integer overflow");
8ca2e9
+		t2p->t2p_error = T2P_ERR_ERROR;
8ca2e9
+		bytes = 0;
8ca2e9
+	}
8ca2e9
+
8ca2e9
+	return bytes;
8ca2e9
+}
8ca2e9
+
8ca2e9
+static uint64
8ca2e9
+checkMultiply64(uint64 first, uint64 second, T2P* t2p)
8ca2e9
+{
8ca2e9
+	uint64 bytes = first * second;
8ca2e9
+
8ca2e9
+	if (second && bytes / second != first) {
8ca2e9
+		TIFFError(TIFF2PDF_MODULE, "Integer overflow");
8ca2e9
+		t2p->t2p_error = T2P_ERR_ERROR;
8ca2e9
+		bytes = 0;
8ca2e9
+	}
8ca2e9
+
8ca2e9
+	return bytes;
8ca2e9
+}
8ca2e9
+
8ca2e9
 /*
8ca2e9
 
8ca2e9
   This is the main function.
8ca2e9
@@ -1828,9 +1857,7 @@
8ca2e9
 	tstrip_t i=0;
8ca2e9
 	tstrip_t stripcount=0;
8ca2e9
 #endif
8ca2e9
-#ifdef OJPEG_SUPPORT
8ca2e9
-        tsize_t k = 0;
8ca2e9
-#endif
8ca2e9
+        uint64 k = 0;
8ca2e9
 
8ca2e9
 	if(t2p->pdf_transcode == T2P_TRANSCODE_RAW){
8ca2e9
 #ifdef CCITT_SUPPORT
8ca2e9
@@ -1858,19 +1885,25 @@
8ca2e9
 			}
8ca2e9
 			stripcount=TIFFNumberOfStrips(input);
8ca2e9
 			for(i=0;i
8ca2e9
-				k += sbc[i];
8ca2e9
+				k = checkAdd64(k, sbc[i], t2p);
8ca2e9
 			}
8ca2e9
 			if(TIFFGetField(input, TIFFTAG_JPEGIFOFFSET, &(t2p->tiff_dataoffset))){
8ca2e9
 				if(t2p->tiff_dataoffset != 0){
8ca2e9
 					if(TIFFGetField(input, TIFFTAG_JPEGIFBYTECOUNT, &(t2p->tiff_datasize))!=0){
8ca2e9
 						if(t2p->tiff_datasize < k) {
8ca2e9
-							t2p->pdf_ojpegiflength=t2p->tiff_datasize;
8ca2e9
-							t2p->tiff_datasize+=k;
8ca2e9
-							t2p->tiff_datasize+=6;
8ca2e9
-							t2p->tiff_datasize+=2*stripcount;
8ca2e9
 							TIFFWarning(TIFF2PDF_MODULE, 
8ca2e9
 								"Input file %s has short JPEG interchange file byte count", 
8ca2e9
 								TIFFFileName(input));
8ca2e9
+							t2p->pdf_ojpegiflength=t2p->tiff_datasize;
8ca2e9
+							k = checkAdd64(k, t2p->tiff_datasize, t2p);
8ca2e9
+							k = checkAdd64(k, 6, t2p);
8ca2e9
+							k = checkAdd64(k, stripcount, t2p);
8ca2e9
+							k = checkAdd64(k, stripcount, t2p);
8ca2e9
+							t2p->tiff_datasize = (tsize_t) k;
8ca2e9
+							if ((uint64) t2p->tiff_datasize != k) {
8ca2e9
+								TIFFError(TIFF2PDF_MODULE, "Integer overflow");
8ca2e9
+								t2p->t2p_error = T2P_ERR_ERROR;
8ca2e9
+							}
8ca2e9
 							return;
8ca2e9
 						}
8ca2e9
 						return;
8ca2e9
@@ -1883,9 +1916,14 @@
8ca2e9
 					}
8ca2e9
 				}
8ca2e9
 			}
8ca2e9
-			t2p->tiff_datasize+=k;
8ca2e9
-			t2p->tiff_datasize+=2*stripcount;
8ca2e9
-			t2p->tiff_datasize+=2048;
8ca2e9
+			k = checkAdd64(k, stripcount, t2p);
8ca2e9
+			k = checkAdd64(k, stripcount, t2p);
8ca2e9
+			k = checkAdd64(k, 2048, t2p);
8ca2e9
+			t2p->tiff_datasize = (tsize_t) k;
8ca2e9
+			if ((uint64) t2p->tiff_datasize != k) {
8ca2e9
+				TIFFError(TIFF2PDF_MODULE, "Integer overflow");
8ca2e9
+				t2p->t2p_error = T2P_ERR_ERROR;
8ca2e9
+			}
8ca2e9
 			return;
8ca2e9
 		}
8ca2e9
 #endif
8ca2e9
@@ -1894,11 +1932,11 @@
8ca2e9
 			uint32 count = 0;
8ca2e9
 			if(TIFFGetField(input, TIFFTAG_JPEGTABLES, &count, &jpt) != 0 ){
8ca2e9
 				if(count > 4){
8ca2e9
-					t2p->tiff_datasize += count;
8ca2e9
-					t2p->tiff_datasize -= 2; /* don't use EOI of header */
8ca2e9
+					k += count;
8ca2e9
+					k -= 2; /* don't use EOI of header */
8ca2e9
 				}
8ca2e9
 			} else {
8ca2e9
-				t2p->tiff_datasize = 2; /* SOI for first strip */
8ca2e9
+				k = 2; /* SOI for first strip */
8ca2e9
 			}
8ca2e9
 			stripcount=TIFFNumberOfStrips(input);
8ca2e9
 			if(!TIFFGetField(input, TIFFTAG_STRIPBYTECOUNTS, &sbc)){
8ca2e9
@@ -1909,18 +1947,33 @@
8ca2e9
 				return;
8ca2e9
 			}
8ca2e9
 			for(i=0;i
8ca2e9
-				t2p->tiff_datasize += sbc[i];
8ca2e9
-				t2p->tiff_datasize -=4; /* don't use SOI or EOI of strip */
8ca2e9
+				k = checkAdd64(k, sbc[i], t2p);
8ca2e9
+				k -=4; /* don't use SOI or EOI of strip */
8ca2e9
+			}
8ca2e9
+			k = checkAdd64(k, 2, t2p); /* use EOI of last strip */
8ca2e9
+			t2p->tiff_datasize = (tsize_t) k;
8ca2e9
+			if ((uint64) t2p->tiff_datasize != k) {
8ca2e9
+				TIFFError(TIFF2PDF_MODULE, "Integer overflow");
8ca2e9
+				t2p->t2p_error = T2P_ERR_ERROR;
8ca2e9
 			}
8ca2e9
-			t2p->tiff_datasize +=2; /* use EOI of last strip */
8ca2e9
 			return;
8ca2e9
 		}
8ca2e9
 #endif
8ca2e9
 		(void) 0;
8ca2e9
 	}
8ca2e9
-	t2p->tiff_datasize=TIFFScanlineSize(input) * t2p->tiff_length;
8ca2e9
+	k = checkMultiply64(TIFFScanlineSize(input), t2p->tiff_length, t2p);
8ca2e9
 	if(t2p->tiff_planar==PLANARCONFIG_SEPARATE){
8ca2e9
-		t2p->tiff_datasize*= t2p->tiff_samplesperpixel;
8ca2e9
+		k = checkMultiply64(k, t2p->tiff_samplesperpixel, t2p);
8ca2e9
+	}
8ca2e9
+	if (k == 0) {
8ca2e9
+		/* Assume we had overflow inside TIFFScanlineSize */
8ca2e9
+		t2p->t2p_error = T2P_ERR_ERROR;
8ca2e9
+	}
8ca2e9
+
8ca2e9
+	t2p->tiff_datasize = (tsize_t) k;
8ca2e9
+	if ((uint64) t2p->tiff_datasize != k) {
8ca2e9
+		TIFFError(TIFF2PDF_MODULE, "Integer overflow");
8ca2e9
+		t2p->t2p_error = T2P_ERR_ERROR;
8ca2e9
 	}
8ca2e9
 
8ca2e9
 	return;
8ca2e9
@@ -1938,6 +1991,7 @@
8ca2e9
 #ifdef JPEG_SUPPORT
8ca2e9
 	unsigned char* jpt;
8ca2e9
 #endif
8ca2e9
+        uint64 k;
8ca2e9
 
8ca2e9
 	edge |= t2p_tile_is_right_edge(t2p->tiff_tiles[t2p->pdf_page], tile);
8ca2e9
 	edge |= t2p_tile_is_bottom_edge(t2p->tiff_tiles[t2p->pdf_page], tile);
8ca2e9
@@ -1949,14 +2003,17 @@
8ca2e9
 #endif
8ca2e9
 		){
8ca2e9
 			t2p->tiff_datasize=TIFFTileSize(input);
8ca2e9
+			if (t2p->tiff_datasize == 0) {
8ca2e9
+				/* Assume we had overflow inside TIFFTileSize */
8ca2e9
+				t2p->t2p_error = T2P_ERR_ERROR;
8ca2e9
+			}
8ca2e9
 			return;
8ca2e9
 		} else {
8ca2e9
 			TIFFGetField(input, TIFFTAG_TILEBYTECOUNTS, &tbc;;
8ca2e9
-			t2p->tiff_datasize=tbc[tile];
8ca2e9
+			k=tbc[tile];
8ca2e9
 #ifdef OJPEG_SUPPORT
8ca2e9
 			if(t2p->tiff_compression==COMPRESSION_OJPEG){
8ca2e9
-				t2p->tiff_datasize+=2048;
8ca2e9
-				return;
8ca2e9
+			  	k = checkAdd64(k, 2048, t2p);
8ca2e9
 			}
8ca2e9
 #endif
8ca2e9
 #ifdef JPEG_SUPPORT
8ca2e9
@@ -1964,18 +2021,33 @@
8ca2e9
 				uint32 count = 0;
8ca2e9
 				if(TIFFGetField(input, TIFFTAG_JPEGTABLES, &count, &jpt)!=0){
8ca2e9
 					if(count > 4){
8ca2e9
-						t2p->tiff_datasize += count;
8ca2e9
-						t2p->tiff_datasize -= 4; /* don't use EOI of header or SOI of tile */
8ca2e9
+						k = checkAdd64(k, count, t2p);
8ca2e9
+						k -= 4; /* don't use EOI of header or SOI of tile */
8ca2e9
 					}
8ca2e9
 				}
8ca2e9
 			}
8ca2e9
 #endif
8ca2e9
+			t2p->tiff_datasize = (tsize_t) k;
8ca2e9
+			if ((uint64) t2p->tiff_datasize != k) {
8ca2e9
+				TIFFError(TIFF2PDF_MODULE, "Integer overflow");
8ca2e9
+				t2p->t2p_error = T2P_ERR_ERROR;
8ca2e9
+			}
8ca2e9
 			return;
8ca2e9
 		}
8ca2e9
 	}
8ca2e9
-	t2p->tiff_datasize=TIFFTileSize(input);
8ca2e9
+	k = TIFFTileSize(input);
8ca2e9
 	if(t2p->tiff_planar==PLANARCONFIG_SEPARATE){
8ca2e9
-		t2p->tiff_datasize*= t2p->tiff_samplesperpixel;
8ca2e9
+		k = checkMultiply64(k, t2p->tiff_samplesperpixel, t2p);
8ca2e9
+	}
8ca2e9
+	if (k == 0) {
8ca2e9
+		/* Assume we had overflow inside TIFFTileSize */
8ca2e9
+		t2p->t2p_error = T2P_ERR_ERROR;
8ca2e9
+	}
8ca2e9
+
8ca2e9
+	t2p->tiff_datasize = (tsize_t) k;
8ca2e9
+	if ((uint64) t2p->tiff_datasize != k) {
8ca2e9
+		TIFFError(TIFF2PDF_MODULE, "Integer overflow");
8ca2e9
+		t2p->t2p_error = T2P_ERR_ERROR;
8ca2e9
 	}
8ca2e9
 
8ca2e9
 	return;
8ca2e9
@@ -2068,6 +2140,10 @@
8ca2e9
 	uint32 max_striplength=0;
8ca2e9
 #endif
8ca2e9
 
8ca2e9
+	/* Fail if prior error (in particular, can't trust tiff_datasize) */
8ca2e9
+	if (t2p->t2p_error != T2P_ERR_OK)
8ca2e9
+		return(0);
8ca2e9
+
8ca2e9
 	if(t2p->pdf_transcode == T2P_TRANSCODE_RAW){
8ca2e9
 #ifdef CCITT_SUPPORT
8ca2e9
 		if(t2p->pdf_compression == T2P_COMPRESS_G4){
8ca2e9
@@ -2641,6 +2717,10 @@
8ca2e9
 	uint32 xuint32=0;
8ca2e9
 #endif
8ca2e9
 
8ca2e9
+	/* Fail if prior error (in particular, can't trust tiff_datasize) */
8ca2e9
+	if (t2p->t2p_error != T2P_ERR_OK)
8ca2e9
+		return(0);
8ca2e9
+
8ca2e9
 	edge |= t2p_tile_is_right_edge(t2p->tiff_tiles[t2p->pdf_page], tile);
8ca2e9
 	edge |= t2p_tile_is_bottom_edge(t2p->tiff_tiles[t2p->pdf_page], tile);
8ca2e9