diff options
author | tgl <tgl> | 2012-06-15 21:44:31 +0000 |
---|---|---|
committer | tgl <tgl> | 2012-06-15 21:44:31 +0000 |
commit | 2be6a8052e98adf6804990a951e0c0f028edba2b (patch) | |
tree | 849891eeaaa0339814b024f0c2acb917f828b7e1 | |
parent | 90b636094d2d5815f080d28466fd71d710ce8281 (diff) | |
download | libtiff-2be6a8052e98adf6804990a951e0c0f028edba2b.tar.gz |
Fix CVE-2012-2113
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | tools/tiff2pdf.c | 135 |
2 files changed, 112 insertions, 28 deletions
@@ -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); |