From 473851d211cf8805a161820337ca74cc9615d6ef Mon Sep 17 00:00:00 2001 From: Nathan Baker 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 --- a/contrib/addtiffo/tif_overview.c +++ b/contrib/addtiffo/tif_overview.c @@ -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 --- a/tools/tiff2pdf.c +++ b/tools/tiff2pdf.c @@ -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 */ @@ -1051,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 --- a/tools/tiffcrop.c +++ b/tools/tiffcrop.c @@ -215,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; @@ -2232,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"); @@ -2240,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