| From 473851d211cf8805a161820337ca74cc9615d6ef Mon Sep 17 00:00:00 2001 |
| From: Nathan Baker <nathanb@lenovo-chrome.com> |
| Date: Tue, 6 Feb 2018 10:13:57 -0500 |
| Subject: [PATCH] Fix for bug 2772 |
| |
| It is possible to craft a TIFF document where the IFD list is circular, |
| leading to an infinite loop while traversing the chain. The libtiff |
| directory reader has a failsafe that will break out of this loop after |
| reading 65535 directory entries, but it will continue processing, |
| consuming time and resources to process what is essentially a bogus TIFF |
| document. |
| |
| This change fixes the above behavior by breaking out of processing when |
| a TIFF document has >= 65535 directories and terminating with an error. |
| |
| contrib/addtiffo/tif_overview.c | 14 +++++++++++++- |
| tools/tiff2pdf.c | 10 ++++++++++ |
| tools/tiffcrop.c | 13 +++++++++++-- |
| 3 files changed, 34 insertions(+), 3 deletions(-) |
| |
| diff --git a/contrib/addtiffo/tif_overview.c b/contrib/addtiffo/tif_overview.c |
| index c61ffbb..03b3573 100644 |
| |
| |
| @@ -65,6 +65,8 @@ |
| # define MAX(a,b) ((a>b) ? a : b) |
| #endif |
| |
| +#define TIFF_DIR_MAX 65534 |
| + |
| void TIFFBuildOverviews( TIFF *, int, int *, int, const char *, |
| int (*)(double,void*), void * ); |
| |
| @@ -91,6 +93,7 @@ uint32 TIFF_WriteOverview( TIFF *hTIFF, uint32 nXSize, uint32 nYSize, |
| { |
| toff_t nBaseDirOffset; |
| toff_t nOffset; |
| + tdir_t iNumDir; |
| |
| (void) bUseSubIFDs; |
| |
| @@ -147,7 +150,16 @@ uint32 TIFF_WriteOverview( TIFF *hTIFF, uint32 nXSize, uint32 nYSize, |
| return 0; |
| |
| TIFFWriteDirectory( hTIFF ); |
| - TIFFSetDirectory( hTIFF, (tdir_t) (TIFFNumberOfDirectories(hTIFF)-1) ); |
| + iNumDir = TIFFNumberOfDirectories(hTIFF); |
| + if( iNumDir > TIFF_DIR_MAX ) |
| + { |
| + TIFFErrorExt( TIFFClientdata(hTIFF), |
| + "TIFF_WriteOverview", |
| + "File `%s' has too many directories.\n", |
| + TIFFFileName(hTIFF) ); |
| + exit(-1); |
| + } |
| + TIFFSetDirectory( hTIFF, (tdir_t) (iNumDir - 1) ); |
| |
| nOffset = TIFFCurrentDirOffset( hTIFF ); |
| |
| diff --git a/tools/tiff2pdf.c b/tools/tiff2pdf.c |
| index 984ef65..832a247 100644 |
| |
| |
| @@ -68,6 +68,8 @@ extern int getopt(int, char**, char*); |
| |
| #define PS_UNIT_SIZE 72.0F |
| |
| +#define TIFF_DIR_MAX 65534 |
| + |
| /* This type is of PDF color spaces. */ |
| typedef enum { |
| T2P_CS_BILEVEL = 0x01, /* Bilevel, black and white */ |
| @@ -1049,6 +1053,14 @@ void t2p_read_tiff_init(T2P* t2p, TIFF* input){ |
| uint16* tiff_transferfunction[3]; |
| |
| directorycount=TIFFNumberOfDirectories(input); |
| + if(directorycount > TIFF_DIR_MAX) { |
| + TIFFError( |
| + TIFF2PDF_MODULE, |
| + "TIFF contains too many directories, %s", |
| + TIFFFileName(input)); |
| + t2p->t2p_error = T2P_ERR_ERROR; |
| + return; |
| + } |
| t2p->tiff_pages = (T2P_PAGE*) _TIFFmalloc(TIFFSafeMultiply(tmsize_t,directorycount,sizeof(T2P_PAGE))); |
| if(t2p->tiff_pages==NULL){ |
| TIFFError( |
| diff --git a/tools/tiffcrop.c b/tools/tiffcrop.c |
| index 91a38f6..e466dae 100644 |
| |
| |
| @@ -217,6 +215,8 @@ extern int getopt(int argc, char * const argv[], const char *optstring); |
| #define DUMP_TEXT 1 |
| #define DUMP_RAW 2 |
| |
| +#define TIFF_DIR_MAX 65534 |
| + |
| /* Offsets into buffer for margins and fixed width and length segments */ |
| struct offset { |
| uint32 tmargin; |
| @@ -2233,7 +2234,7 @@ main(int argc, char* argv[]) |
| pageNum = -1; |
| else |
| total_images = 0; |
| - /* read multiple input files and write to output file(s) */ |
| + /* Read multiple input files and write to output file(s) */ |
| while (optind < argc - 1) |
| { |
| in = TIFFOpen (argv[optind], "r"); |
| @@ -2241,7 +2242,14 @@ main(int argc, char* argv[]) |
| return (-3); |
| |
| /* If only one input file is specified, we can use directory count */ |
| - total_images = TIFFNumberOfDirectories(in); |
| + total_images = TIFFNumberOfDirectories(in); |
| + if (total_images > TIFF_DIR_MAX) |
| + { |
| + TIFFError (TIFFFileName(in), "File contains too many directories"); |
| + if (out != NULL) |
| + (void) TIFFClose(out); |
| + return (1); |
| + } |
| if (image_count == 0) |
| { |
| dirnum = 0; |
| -- |
| libgit2 0.26.0 |
| |