diff --git a/libtiff/tif_dirread.c b/libtiff/tif_dirread.c index 9606c233..78c1be06 100644 --- a/libtiff/tif_dirread.c +++ b/libtiff/tif_dirread.c @@ -1,4 +1,4 @@ -/* $Id: tif_dirread.c,v 1.84 2006-04-04 02:00:08 joris Exp $ */ +/* $Id: tif_dirread.c,v 1.85 2006-06-08 14:27:17 dron Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler @@ -41,9 +41,11 @@ extern void TIFFCvtIEEEFloatToNative(TIFF*, uint32, float*); extern void TIFFCvtIEEEDoubleToNative(TIFF*, uint32, double*); #endif -static TIFFDirEntry* TIFFReadDirectoryFind(TIFFDirEntry* dir, uint16 dircount, uint16 tagid); +static TIFFDirEntry* TIFFReadDirectoryFind(TIFFDirEntry* dir, + uint16 dircount, uint16 tagid); static int EstimateStripByteCounts(TIFF*, TIFFDirEntry*, uint16); static void MissingRequired(TIFF*, const char*); +static int TIFFCheckDirOffset(TIFF*); static int CheckDirCount(TIFF*, TIFFDirEntry*, uint32); static tsize_t TIFFFetchData(TIFF*, TIFFDirEntry*, char*); static tsize_t TIFFFetchString(TIFF*, TIFFDirEntry*, char*); @@ -82,32 +84,21 @@ TIFFReadDirectory(TIFF* tif) uint16 dircount; toff_t nextdiroff; int diroutoforderwarning = 0; - toff_t* new_dirlist; tif->tif_diroff = tif->tif_nextdiroff; if (tif->tif_diroff == 0) /* no more directories */ return (0); + /* + * XXX: Check offset to prevent IFD looping. + */ + if (!TIFFCheckDirOffset(tif)) + return 0; /* * XXX: Trick to prevent IFD looping. The one can create TIFF file * with looped directory pointers. We will maintain a list of already * seen directories and check every IFD offset against this list. */ - for (n = 0; n < tif->tif_dirnumber; n++) { - if (tif->tif_dirlist[n] == tif->tif_diroff) - return (0); - } - tif->tif_dirnumber++; - new_dirlist = (toff_t *)_TIFFrealloc(tif->tif_dirlist, - tif->tif_dirnumber * sizeof(toff_t)); - if (!new_dirlist) { - TIFFErrorExt(tif->tif_clientdata, module, - "%s: Failed to allocate space for IFD list", - tif->tif_name); - return (0); - } - tif->tif_dirlist = new_dirlist; - tif->tif_dirlist[tif->tif_dirnumber - 1] = tif->tif_diroff; /* * Cleanup any previous compression state. @@ -1048,10 +1039,49 @@ MissingRequired(TIFF* tif, const char* tagname) } /* - * Check the count field of a directory - * entry against a known value. The caller - * is expected to skip/ignore the tag if - * there is a mismatch. + * Check the directory offset against the list of already seen directory + * offsets. This is a trick to prevent IFD looping. The one can create TIFF + * file with looped directory pointers. We will maintain a list of already + * seen directories and check every IFD offset against that list. + */ +static int +TIFFCheckDirOffset(TIFF* tif) +{ + uint16 n; + + for (n = 0; n < tif->tif_dirnumber && tif->tif_dirlist; n++) { + if (tif->tif_dirlist[n] == tif->tif_diroff) + return 0; + } + + tif->tif_dirnumber++; + + if (tif->tif_dirnumber > tif->tif_dirlistsize) { + toff_t* new_dirlist; + + /* + * XXX: Reduce memory allocation granularity of the dirlist + * array. + */ + new_dirlist = (toff_t *)_TIFFCheckRealloc(tif, + tif->tif_dirlist, + tif->tif_dirnumber, + 2 * sizeof(toff_t), + "for IFD list"); + if (!new_dirlist) + return 0; + tif->tif_dirlistsize = 2 * tif->tif_dirnumber; + tif->tif_dirlist = new_dirlist; + } + + tif->tif_dirlist[tif->tif_dirnumber - 1] = tif->tif_diroff; + + return 1; +} + +/* + * Check the count field of a directory entry against a known value. The + * caller is expected to skip/ignore the tag if there is a mismatch. */ static int CheckDirCount(TIFF* tif, TIFFDirEntry* dir, uint32 count) diff --git a/libtiff/tif_open.c b/libtiff/tif_open.c index 2a54682a..5fa7aa0d 100644 --- a/libtiff/tif_open.c +++ b/libtiff/tif_open.c @@ -1,4 +1,4 @@ -/* $Id: tif_open.c,v 1.32 2006-03-25 03:09:24 joris Exp $ */ +/* $Id: tif_open.c,v 1.33 2006-06-08 14:27:17 dron Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler @@ -307,7 +307,8 @@ TIFFClientOpen( if (tif->tif_mode & O_TRUNC || !ReadOK(tif, &tif->tif_header, sizeof (TIFFHeader))) { if (tif->tif_mode == O_RDONLY) { - TIFFErrorExt(tif->tif_clientdata, name, "Cannot read TIFF header"); + TIFFErrorExt(tif->tif_clientdata, name, + "Cannot read TIFF header"); goto bad; } /* @@ -336,7 +337,8 @@ TIFFClientOpen( TIFFSeekFile( tif, 0, SEEK_SET ); if (!WriteOK(tif, &tif->tif_header, sizeof (TIFFHeader))) { - TIFFErrorExt(tif->tif_clientdata, name, "Error writing TIFF header"); + TIFFErrorExt(tif->tif_clientdata, name, + "Error writing TIFF header"); goto bad; } /* @@ -350,6 +352,7 @@ TIFFClientOpen( goto bad; tif->tif_diroff = 0; tif->tif_dirlist = NULL; + tif->tif_dirlistsize = 0; tif->tif_dirnumber = 0; return (tif); } @@ -366,10 +369,12 @@ TIFFClientOpen( tif->tif_header.tiff_magic != MDI_LITTLEENDIAN #endif ) { - TIFFErrorExt(tif->tif_clientdata, name, "Not a TIFF or MDI file, bad magic number %d (0x%x)", + TIFFErrorExt(tif->tif_clientdata, name, + "Not a TIFF or MDI file, bad magic number %d (0x%x)", #else ) { - TIFFErrorExt(tif->tif_clientdata, name, "Not a TIFF file, bad magic number %d (0x%x)", + TIFFErrorExt(tif->tif_clientdata, name, + "Not a TIFF file, bad magic number %d (0x%x)", #endif tif->tif_header.tiff_magic, tif->tif_header.tiff_magic); diff --git a/libtiff/tiffiop.h b/libtiff/tiffiop.h index b66fb4e1..3f2df726 100644 --- a/libtiff/tiffiop.h +++ b/libtiff/tiffiop.h @@ -1,4 +1,4 @@ -/* $Id: tiffiop.h,v 1.47 2006-03-25 03:09:24 joris Exp $ */ +/* $Id: tiffiop.h,v 1.48 2006-06-08 14:27:17 dron Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler @@ -120,6 +120,7 @@ struct tiff { toff_t tif_nextdiroff; /* file offset of following directory */ toff_t* tif_dirlist; /* list of offsets to already seen */ /* directories to prevent IFD looping */ + tsize_t tif_dirlistsize;/* number of entires in offset list */ uint16 tif_dirnumber; /* number of already seen directories */ TIFFDirectory tif_dir; /* internal rep of current directory */ TIFFHeader tif_header; /* file's header block */ @@ -275,6 +276,7 @@ extern TIFFErrorHandlerExt _TIFFwarningHandlerExt; extern TIFFErrorHandlerExt _TIFFerrorHandlerExt; extern tdata_t _TIFFCheckMalloc(TIFF*, size_t, size_t, const char*); +extern tdata_t _TIFFCheckRealloc(TIFF*, tdata_t, size_t, size_t, const char*); extern int TIFFInitDumpMode(TIFF*, int); #ifdef PACKBITS_SUPPORT