Move IFD looping checking code in the separate function TIFFCheckDirOffset().

This commit is contained in:
Andrey Kiselev 2006-06-08 14:27:17 +00:00
parent c0e99e81f8
commit 0a27311394
3 changed files with 65 additions and 28 deletions

View File

@ -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 * Copyright (c) 1988-1997 Sam Leffler
@ -41,9 +41,11 @@ extern void TIFFCvtIEEEFloatToNative(TIFF*, uint32, float*);
extern void TIFFCvtIEEEDoubleToNative(TIFF*, uint32, double*); extern void TIFFCvtIEEEDoubleToNative(TIFF*, uint32, double*);
#endif #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 int EstimateStripByteCounts(TIFF*, TIFFDirEntry*, uint16);
static void MissingRequired(TIFF*, const char*); static void MissingRequired(TIFF*, const char*);
static int TIFFCheckDirOffset(TIFF*);
static int CheckDirCount(TIFF*, TIFFDirEntry*, uint32); static int CheckDirCount(TIFF*, TIFFDirEntry*, uint32);
static tsize_t TIFFFetchData(TIFF*, TIFFDirEntry*, char*); static tsize_t TIFFFetchData(TIFF*, TIFFDirEntry*, char*);
static tsize_t TIFFFetchString(TIFF*, TIFFDirEntry*, char*); static tsize_t TIFFFetchString(TIFF*, TIFFDirEntry*, char*);
@ -82,32 +84,21 @@ TIFFReadDirectory(TIFF* tif)
uint16 dircount; uint16 dircount;
toff_t nextdiroff; toff_t nextdiroff;
int diroutoforderwarning = 0; int diroutoforderwarning = 0;
toff_t* new_dirlist;
tif->tif_diroff = tif->tif_nextdiroff; tif->tif_diroff = tif->tif_nextdiroff;
if (tif->tif_diroff == 0) /* no more directories */ if (tif->tif_diroff == 0) /* no more directories */
return (0); 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 * XXX: Trick to prevent IFD looping. The one can create TIFF file
* with looped directory pointers. We will maintain a list of already * with looped directory pointers. We will maintain a list of already
* seen directories and check every IFD offset against this list. * 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. * Cleanup any previous compression state.
@ -1048,10 +1039,49 @@ MissingRequired(TIFF* tif, const char* tagname)
} }
/* /*
* Check the count field of a directory * Check the directory offset against the list of already seen directory
* entry against a known value. The caller * offsets. This is a trick to prevent IFD looping. The one can create TIFF
* is expected to skip/ignore the tag if * file with looped directory pointers. We will maintain a list of already
* there is a mismatch. * 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 static int
CheckDirCount(TIFF* tif, TIFFDirEntry* dir, uint32 count) CheckDirCount(TIFF* tif, TIFFDirEntry* dir, uint32 count)

View File

@ -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 * Copyright (c) 1988-1997 Sam Leffler
@ -307,7 +307,8 @@ TIFFClientOpen(
if (tif->tif_mode & O_TRUNC || if (tif->tif_mode & O_TRUNC ||
!ReadOK(tif, &tif->tif_header, sizeof (TIFFHeader))) { !ReadOK(tif, &tif->tif_header, sizeof (TIFFHeader))) {
if (tif->tif_mode == O_RDONLY) { 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; goto bad;
} }
/* /*
@ -336,7 +337,8 @@ TIFFClientOpen(
TIFFSeekFile( tif, 0, SEEK_SET ); TIFFSeekFile( tif, 0, SEEK_SET );
if (!WriteOK(tif, &tif->tif_header, sizeof (TIFFHeader))) { 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; goto bad;
} }
/* /*
@ -350,6 +352,7 @@ TIFFClientOpen(
goto bad; goto bad;
tif->tif_diroff = 0; tif->tif_diroff = 0;
tif->tif_dirlist = NULL; tif->tif_dirlist = NULL;
tif->tif_dirlistsize = 0;
tif->tif_dirnumber = 0; tif->tif_dirnumber = 0;
return (tif); return (tif);
} }
@ -366,10 +369,12 @@ TIFFClientOpen(
tif->tif_header.tiff_magic != MDI_LITTLEENDIAN tif->tif_header.tiff_magic != MDI_LITTLEENDIAN
#endif #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 #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 #endif
tif->tif_header.tiff_magic, tif->tif_header.tiff_magic,
tif->tif_header.tiff_magic); tif->tif_header.tiff_magic);

View File

@ -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 * Copyright (c) 1988-1997 Sam Leffler
@ -120,6 +120,7 @@ struct tiff {
toff_t tif_nextdiroff; /* file offset of following directory */ toff_t tif_nextdiroff; /* file offset of following directory */
toff_t* tif_dirlist; /* list of offsets to already seen */ toff_t* tif_dirlist; /* list of offsets to already seen */
/* directories to prevent IFD looping */ /* directories to prevent IFD looping */
tsize_t tif_dirlistsize;/* number of entires in offset list */
uint16 tif_dirnumber; /* number of already seen directories */ uint16 tif_dirnumber; /* number of already seen directories */
TIFFDirectory tif_dir; /* internal rep of current directory */ TIFFDirectory tif_dir; /* internal rep of current directory */
TIFFHeader tif_header; /* file's header block */ TIFFHeader tif_header; /* file's header block */
@ -275,6 +276,7 @@ extern TIFFErrorHandlerExt _TIFFwarningHandlerExt;
extern TIFFErrorHandlerExt _TIFFerrorHandlerExt; extern TIFFErrorHandlerExt _TIFFerrorHandlerExt;
extern tdata_t _TIFFCheckMalloc(TIFF*, size_t, size_t, const char*); 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); extern int TIFFInitDumpMode(TIFF*, int);
#ifdef PACKBITS_SUPPORT #ifdef PACKBITS_SUPPORT