summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortgl <tgl>2012-06-15 21:44:31 +0000
committertgl <tgl>2012-06-15 21:44:31 +0000
commit2be6a8052e98adf6804990a951e0c0f028edba2b (patch)
tree849891eeaaa0339814b024f0c2acb917f828b7e1
parent90b636094d2d5815f080d28466fd71d710ce8281 (diff)
downloadlibtiff-2be6a8052e98adf6804990a951e0c0f028edba2b.tar.gz
Fix CVE-2012-2113
-rw-r--r--ChangeLog5
-rw-r--r--tools/tiff2pdf.c135
2 files changed, 112 insertions, 28 deletions
diff --git a/ChangeLog b/ChangeLog
index d8c1b468..16711866 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2012-06-15 Tom Lane <tgl@sss.pgh.pa.us>
+
+ * tools/tiff2pdf.c: Defend against integer overflows while
+ calculating required buffer sizes (CVE-2012-2113).
+
2012-06-12 Frank Warmerdam <warmerdam@google.com>
* libtiff/tif_print.c: Be careful about printing corrupt inknames.
diff --git a/tools/tiff2pdf.c b/tools/tiff2pdf.c
index 48272d93..484d9e5f 100644
--- a/tools/tiff2pdf.c
+++ b/tools/tiff2pdf.c
@@ -1,4 +1,4 @@
-/* $Id: tiff2pdf.c,v 1.65 2011-05-31 17:00:03 bfriesen Exp $
+/* $Id: tiff2pdf.c,v 1.66 2012-06-15 21:44:31 tgl Exp $
*
* tiff2pdf - converts a TIFF image to a PDF document
*
@@ -435,6 +435,34 @@ t2p_unmapproc(thandle_t handle, void *data, toff_t offset)
(void) handle, (void) data, (void) offset;
}
+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.
@@ -1776,9 +1804,7 @@ void t2p_read_tiff_size(T2P* t2p, TIFF* input){
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
@@ -1806,19 +1832,25 @@ void t2p_read_tiff_size(T2P* t2p, TIFF* input){
}
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;
+ if((uint64)t2p->tiff_datasize < k) {
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;
@@ -1831,9 +1863,14 @@ void t2p_read_tiff_size(T2P* t2p, TIFF* input){
}
}
}
- 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
@@ -1842,11 +1879,11 @@ void t2p_read_tiff_size(T2P* t2p, TIFF* input){
uint32 count = 0;
if(TIFFGetField(input, TIFFTAG_JPEGTABLES, &count, &jpt) != 0 ){
if(count > 4){
- t2p->tiff_datasize += count;
- t2p->tiff_datasize -= 2; /* don't use EOI of header */
+ k += count;
+ 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)){
@@ -1857,18 +1894,33 @@ void t2p_read_tiff_size(T2P* t2p, TIFF* input){
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 */
return;
}
#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;
@@ -1886,6 +1938,7 @@ void t2p_read_tiff_size_tile(T2P* t2p, TIFF* input, ttile_t tile){
#ifdef JPEG_SUPPORT
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);
@@ -1897,14 +1950,17 @@ void t2p_read_tiff_size_tile(T2P* t2p, TIFF* input, ttile_t tile){
#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=(tmsize_t)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
@@ -1912,18 +1968,33 @@ void t2p_read_tiff_size_tile(T2P* t2p, TIFF* input, ttile_t tile){
uint32 count = 0;
if(TIFFGetField(input, TIFFTAG_JPEGTABLES, &count, &jpt)!=0){
if(count > 4){
- t2p->tiff_datasize += count;
- t2p->tiff_datasize -= 2; /* don't use EOI of header or SOI of tile */
+ k = checkAdd64(k, count, t2p);
+ k -= 2; /* 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;
@@ -2016,6 +2087,10 @@ tsize_t t2p_readwrite_pdf_image(T2P* t2p, TIFF* input, TIFF* output){
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){
@@ -2590,6 +2665,10 @@ tsize_t t2p_readwrite_pdf_image_tile(T2P* t2p, TIFF* input, TIFF* output, ttile_
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);