File tiff-3.8.2-CVE-2012-2113.patch of Package tiff

Description: fix possible arbitrary code execution via integer
 overflows in tiff2pdf
Origin: thanks to Red Hat
Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/tiff/+bug/1016324
Bug-Debian: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=678140
Bug-RedHat: https://bugzilla.redhat.com/show_bug.cgi?id=810551

diff -Naurp tiff-3.8.2.ori/tools/tiff2pdf.c tiff-3.8.2/tools/tiff2pdf.c
--- tiff-3.8.2.ori/tools/tiff2pdf.c	2012-07-04 11:08:21.743665954 -0400
+++ tiff-3.8.2/tools/tiff2pdf.c	2012-07-04 11:14:58.847676122 -0400
@@ -28,6 +28,7 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <stdint.h>
 #include <string.h>
 #include <ctype.h>
 #include <time.h>
@@ -42,6 +43,8 @@
 #define NULL ((void*)0)
 #endif
 
+typedef uint64_t uint64;
+
 #if defined(VMS)
 #define unlink remove
 #endif
@@ -313,6 +316,34 @@ tsize_t t2p_write_pdf_xobject_stream_fil
 tsize_t t2p_write_pdf_xreftable(T2P*, TIFF*);
 tsize_t t2p_write_pdf_trailer(T2P*, TIFF*);
 
+static uint64
+checkAdd64(uint64 summand1, uint64 summand2, T2P* t2p)
+{
+	uint64 bytes = summand1 + summand2;
+
+	if (bytes - summand1 != summand2) {
+		TIFFError(TIFF2PDF_MODULE, "Integer overflow");
+		t2p->t2p_error = T2P_ERR_ERROR;
+		bytes = 0;
+	}
+
+	return bytes;
+}
+
+static uint64
+checkMultiply64(uint64 first, uint64 second, T2P* t2p)
+{
+	uint64 bytes = first * second;
+
+	if (second && bytes / second != first) {
+		TIFFError(TIFF2PDF_MODULE, "Integer overflow");
+		t2p->t2p_error = T2P_ERR_ERROR;
+		bytes = 0;
+	}
+
+	return bytes;
+}
+
 /*
 
   This is the main function.
@@ -1754,9 +1785,7 @@ void t2p_read_tiff_size(T2P* t2p, TIFF*
 	tstrip_t i=0;
 	tstrip_t stripcount=0;
 #endif
-#ifdef OJPEG_SUPPORT
-        tsize_t k = 0;
-#endif
+        uint64 k = 0;
 
 	if(t2p->pdf_transcode == T2P_TRANSCODE_RAW){
 #ifdef CCITT_SUPPORT
@@ -1784,19 +1813,25 @@ void t2p_read_tiff_size(T2P* t2p, TIFF*
 			}
 			stripcount=TIFFNumberOfStrips(input);
 			for(i=0;i<stripcount;i++){
-				k += sbc[i];
+				k = checkAdd64(k, sbc[i], t2p);
 			}
 			if(TIFFGetField(input, TIFFTAG_JPEGIFOFFSET, &(t2p->tiff_dataoffset))){
 				if(t2p->tiff_dataoffset != 0){
 					if(TIFFGetField(input, TIFFTAG_JPEGIFBYTECOUNT, &(t2p->tiff_datasize))!=0){
 						if(t2p->tiff_datasize < k) {
-							t2p->pdf_ojpegiflength=t2p->tiff_datasize;
-							t2p->tiff_datasize+=k;
-							t2p->tiff_datasize+=6;
-							t2p->tiff_datasize+=2*stripcount;
 							TIFFWarning(TIFF2PDF_MODULE, 
 								"Input file %s has short JPEG interchange file byte count", 
 								TIFFFileName(input));
+							t2p->pdf_ojpegiflength=t2p->tiff_datasize;
+							k = checkAdd64(k, t2p->tiff_datasize, t2p);
+							k = checkAdd64(k, 6, t2p);
+							k = checkAdd64(k, stripcount, t2p);
+							k = checkAdd64(k, stripcount, t2p);
+							t2p->tiff_datasize = (tsize_t) k;
+							if ((uint64) t2p->tiff_datasize != k) {
+								TIFFError(TIFF2PDF_MODULE, "Integer overflow");
+								t2p->t2p_error = T2P_ERR_ERROR;
+							}
 							return;
 						}
 						return;
@@ -1809,9 +1844,14 @@ void t2p_read_tiff_size(T2P* t2p, TIFF*
 					}
 				}
 			}
-			t2p->tiff_datasize+=k;
-			t2p->tiff_datasize+=2*stripcount;
-			t2p->tiff_datasize+=2048;
+			k = checkAdd64(k, stripcount, t2p);
+			k = checkAdd64(k, stripcount, t2p);
+			k = checkAdd64(k, 2048, t2p);
+			t2p->tiff_datasize = (tsize_t) k;
+			if ((uint64) t2p->tiff_datasize != k) {
+				TIFFError(TIFF2PDF_MODULE, "Integer overflow");
+				t2p->t2p_error = T2P_ERR_ERROR;
+			}
 			return;
 		}
 #endif
@@ -1819,11 +1859,11 @@ void t2p_read_tiff_size(T2P* t2p, TIFF*
 		if(t2p->tiff_compression == COMPRESSION_JPEG){
 			if(TIFFGetField(input, TIFFTAG_JPEGTABLES, &xuint16, &jpt) != 0 ){
 				if(xuint16>4){
-					t2p->tiff_datasize+= xuint16;
-					t2p->tiff_datasize -=2; /* don't use EOI of header */
+					k += xuint16;
+					k -= 2; /* don't use EOI of header */
 				}
 			} else {
-				t2p->tiff_datasize=2; /* SOI for first strip */
+				k = 2; /* SOI for first strip */
 			}
 			stripcount=TIFFNumberOfStrips(input);
 			if(!TIFFGetField(input, TIFFTAG_STRIPBYTECOUNTS, &sbc)){
@@ -1834,17 +1874,32 @@ void t2p_read_tiff_size(T2P* t2p, TIFF*
 				return;
 			}
 			for(i=0;i<stripcount;i++){
-				t2p->tiff_datasize += sbc[i];
-				t2p->tiff_datasize -=4; /* don't use SOI or EOI of strip */
+				k = checkAdd64(k, sbc[i], t2p);
+				k -=4; /* don't use SOI or EOI of strip */
+			}
+			k = checkAdd64(k, 2, t2p); /* use EOI of last strip */
+			t2p->tiff_datasize = (tsize_t) k;
+			if ((uint64) t2p->tiff_datasize != k) {
+				TIFFError(TIFF2PDF_MODULE, "Integer overflow");
+				t2p->t2p_error = T2P_ERR_ERROR;
 			}
-			t2p->tiff_datasize +=2; /* use EOI of last strip */
 		}
 #endif
 		(void) 0;
 	}
-	t2p->tiff_datasize=TIFFScanlineSize(input) * t2p->tiff_length;
+	k = checkMultiply64(TIFFScanlineSize(input), t2p->tiff_length, t2p);
 	if(t2p->tiff_planar==PLANARCONFIG_SEPARATE){
-		t2p->tiff_datasize*= t2p->tiff_samplesperpixel;
+		k = checkMultiply64(k, t2p->tiff_samplesperpixel, t2p);
+	}
+	if (k == 0) {
+		/* Assume we had overflow inside TIFFScanlineSize */
+		t2p->t2p_error = T2P_ERR_ERROR;
+	}
+
+	t2p->tiff_datasize = (tsize_t) k;
+	if ((uint64) t2p->tiff_datasize != k) {
+		TIFFError(TIFF2PDF_MODULE, "Integer overflow");
+		t2p->t2p_error = T2P_ERR_ERROR;
 	}
 
 	return;
@@ -1863,6 +1918,7 @@ void t2p_read_tiff_size_tile(T2P* t2p, T
 	uint16 xuint16=0;
 	unsigned char* jpt;
 #endif
+        uint64 k;
 
 	edge |= t2p_tile_is_right_edge(t2p->tiff_tiles[t2p->pdf_page], tile);
 	edge |= t2p_tile_is_bottom_edge(t2p->tiff_tiles[t2p->pdf_page], tile);
@@ -1874,32 +1930,50 @@ void t2p_read_tiff_size_tile(T2P* t2p, T
 #endif
 		){
 			t2p->tiff_datasize=TIFFTileSize(input);
+			if (t2p->tiff_datasize == 0) {
+				/* Assume we had overflow inside TIFFTileSize */
+				t2p->t2p_error = T2P_ERR_ERROR;
+			}
 			return;
 		} else {
 			TIFFGetField(input, TIFFTAG_TILEBYTECOUNTS, &tbc);
-			t2p->tiff_datasize=tbc[tile];
+			k=tbc[tile];
 #ifdef OJPEG_SUPPORT
 			if(t2p->tiff_compression==COMPRESSION_OJPEG){
-				t2p->tiff_datasize+=2048;
-				return;
+			  	k = checkAdd64(k, 2048, t2p);
 			}
 #endif
 #ifdef JPEG_SUPPORT
 			if(t2p->tiff_compression==COMPRESSION_JPEG){
 				if(TIFFGetField(input, TIFFTAG_JPEGTABLES, &xuint16, &jpt)!=0){
 					if(xuint16>4){
-						t2p->tiff_datasize+=xuint16;
-						t2p->tiff_datasize-=4; /* don't use EOI of header or SOI of tile */
+						k = checkAdd64(k, xuint16, t2p);
+						k -= 4; /* don't use EOI of header or SOI of tile */
 					}
 				}
 			}
 #endif
+			t2p->tiff_datasize = (tsize_t) k;
+			if ((uint64) t2p->tiff_datasize != k) {
+				TIFFError(TIFF2PDF_MODULE, "Integer overflow");
+				t2p->t2p_error = T2P_ERR_ERROR;
+			}
 			return;
 		}
 	}
-	t2p->tiff_datasize=TIFFTileSize(input);
+	k = TIFFTileSize(input);
 	if(t2p->tiff_planar==PLANARCONFIG_SEPARATE){
-		t2p->tiff_datasize*= t2p->tiff_samplesperpixel;
+		k = checkMultiply64(k, t2p->tiff_samplesperpixel, t2p);
+	}
+	if (k == 0) {
+		/* Assume we had overflow inside TIFFTileSize */
+		t2p->t2p_error = T2P_ERR_ERROR;
+	}
+
+	t2p->tiff_datasize = (tsize_t) k;
+	if ((uint64) t2p->tiff_datasize != k) {
+		TIFFError(TIFF2PDF_MODULE, "Integer overflow");
+		t2p->t2p_error = T2P_ERR_ERROR;
 	}
 
 	return;
@@ -2045,6 +2119,10 @@ tsize_t t2p_readwrite_pdf_image(T2P* t2p
 	uint32 max_striplength=0;
 #endif
 
+	/* Fail if prior error (in particular, can't trust tiff_datasize) */
+	if (t2p->t2p_error != T2P_ERR_OK)
+		return(0);
+
 	if(t2p->pdf_transcode == T2P_TRANSCODE_RAW){
 #ifdef CCITT_SUPPORT
 		if(t2p->pdf_compression == T2P_COMPRESS_G4){
@@ -2582,6 +2660,10 @@ tsize_t t2p_readwrite_pdf_image_tile(T2P
 	uint32 xuint32=0;
 #endif
 
+	/* Fail if prior error (in particular, can't trust tiff_datasize) */
+	if (t2p->t2p_error != T2P_ERR_OK)
+		return(0);
+
 	edge |= t2p_tile_is_right_edge(t2p->tiff_tiles[t2p->pdf_page], tile);
 	edge |= t2p_tile_is_bottom_edge(t2p->tiff_tiles[t2p->pdf_page], tile);
 
openSUSE Build Service is sponsored by