diff options
author | Even Rouault <even.rouault@spatialys.com> | 2022-12-13 15:14:47 +0100 |
---|---|---|
committer | Even Rouault <even.rouault@spatialys.com> | 2022-12-13 15:14:47 +0100 |
commit | 2c0f2ed803c84ec9244236c59dacf4dc32447ecc (patch) | |
tree | 7dec947c3ca18d4c0e4d57fc1538cc6b351ac4e3 /libtiff | |
parent | 2c1d4b6b01102fb8733bad6d00af5a8c21aa8e45 (diff) | |
download | libtiff-git-2c0f2ed803c84ec9244236c59dacf4dc32447ecc.tar.gz |
Fix IFD loop detection
Diffstat (limited to 'libtiff')
-rw-r--r-- | libtiff/tif_dir.c | 7 | ||||
-rw-r--r-- | libtiff/tif_dirread.c | 78 | ||||
-rw-r--r-- | libtiff/tif_hash_set.c | 2 | ||||
-rw-r--r-- | libtiff/tif_hash_set.h | 3 | ||||
-rw-r--r-- | libtiff/tif_open.c | 3 | ||||
-rw-r--r-- | libtiff/tiffiop.h | 4 |
6 files changed, 68 insertions, 29 deletions
diff --git a/libtiff/tif_dir.c b/libtiff/tif_dir.c index 97fb5eb9..901dff82 100644 --- a/libtiff/tif_dir.c +++ b/libtiff/tif_dir.c @@ -2071,7 +2071,7 @@ int TIFFSetSubDirectory(TIFF *tif, uint64_t diroff) if (diroff == 0) { /* Special case to invalidate the tif_lastdiroff member. */ - tif->tif_curdir = UINT_MAX; + tif->tif_curdir = TIFF_NON_EXISTENT_DIR_NUMBER; } else { @@ -2081,7 +2081,8 @@ int TIFFSetSubDirectory(TIFF *tif, uint64_t diroff) probablySubIFD = 1; } /* -1 because TIFFReadDirectory() will increment tif_curdir. */ - tif->tif_curdir = curdir == 0 ? UINT_MAX : curdir - 1; + tif->tif_curdir = + curdir == 0 ? TIFF_NON_EXISTENT_DIR_NUMBER : curdir - 1; } tif->tif_nextdiroff = diroff; @@ -2090,7 +2091,7 @@ int TIFFSetSubDirectory(TIFF *tif, uint64_t diroff) * back. */ if (!retval) { - if (tif->tif_curdir == UINT_MAX) + if (tif->tif_curdir == TIFF_NON_EXISTENT_DIR_NUMBER) tif->tif_curdir = 0; else tif->tif_curdir++; diff --git a/libtiff/tif_dirread.c b/libtiff/tif_dirread.c index fc21851b..b9606f58 100644 --- a/libtiff/tif_dirread.c +++ b/libtiff/tif_dirread.c @@ -4076,9 +4076,12 @@ int TIFFReadDirectory(TIFF *tif) /* tif_curdir++ and tif_nextdiroff should only be updated after SUCCESSFUL * reading of the directory. Otherwise, invalid IFD offsets could corrupt * the IFD list. */ - if (!_TIFFCheckDirNumberAndOffset( - tif, tif->tif_curdir == UINT_MAX ? 0 : tif->tif_curdir + 1, - nextdiroff)) + if (!_TIFFCheckDirNumberAndOffset(tif, + tif->tif_curdir == + TIFF_NON_EXISTENT_DIR_NUMBER + ? 0 + : tif->tif_curdir + 1, + nextdiroff)) { return 0; /* bad offset (IFD looping or more than TIFF_MAX_DIR_COUNT IFDs) */ @@ -4094,7 +4097,7 @@ int TIFFReadDirectory(TIFF *tif) /* Set global values after a valid directory has been fetched. * tif_diroff is already set to nextdiroff in TIFFFetchDirectory() in the * beginning. */ - if (tif->tif_curdir == UINT_MAX) + if (tif->tif_curdir == TIFF_NON_EXISTENT_DIR_NUMBER) tif->tif_curdir = 0; else tif->tif_curdir++; @@ -5345,8 +5348,10 @@ int _TIFFCheckDirNumberAndOffset(TIFF *tif, tdir_t dirn, uint64_t diroff) if (tif->tif_map_dir_number_to_offset == NULL) { + /* No free callback for this map, as it shares the same items as + * tif->tif_map_dir_offset_to_number. */ tif->tif_map_dir_number_to_offset = TIFFHashSetNew( - hashFuncNumberToOffset, equalFuncNumberToOffset, free); + hashFuncNumberToOffset, equalFuncNumberToOffset, NULL); if (tif->tif_map_dir_number_to_offset == NULL) { TIFFErrorExtR(tif, "_TIFFCheckDirNumberAndOffset", @@ -5386,15 +5391,50 @@ int _TIFFCheckDirNumberAndOffset(TIFF *tif, tdir_t dirn, uint64_t diroff) /* Check if offset of an IFD has been changed and update offset of that IFD * number. */ - entry.dirNumber = dirn; - entry.offset = 0; /* not used */ - foundEntry = (TIFFOffsetAndDirNumber *)TIFFHashSetLookup( tif->tif_map_dir_number_to_offset, &entry); if (foundEntry) { - /* tif_dirlistdirn can have IFD numbers dirn in random order */ - foundEntry->offset = diroff; + if (foundEntry->offset != diroff) + { + TIFFOffsetAndDirNumber entryOld; + entryOld.offset = diroff; + entryOld.dirNumber = foundEntry->offset; + TIFFOffsetAndDirNumber *foundEntryOld = + (TIFFOffsetAndDirNumber *)TIFFHashSetLookup( + tif->tif_map_dir_offset_to_number, &entryOld); + if (foundEntryOld) + { + TIFFHashSetRemove(tif->tif_map_dir_offset_to_number, + foundEntryOld); + } + foundEntryOld = (TIFFOffsetAndDirNumber *)TIFFHashSetLookup( + tif->tif_map_dir_number_to_offset, &entryOld); + if (foundEntryOld) + { + TIFFHashSetRemove(tif->tif_map_dir_number_to_offset, + foundEntryOld); + } + + TIFFOffsetAndDirNumber *entryPtr = (TIFFOffsetAndDirNumber *)malloc( + sizeof(TIFFOffsetAndDirNumber)); + if (entryPtr == NULL) + { + return 0; + } + + /* Add IFD offset and dirn to IFD directory list */ + *entryPtr = entry; + + if (!TIFFHashSetInsert(tif->tif_map_dir_offset_to_number, entryPtr)) + { + return 0; + } + if (!TIFFHashSetInsert(tif->tif_map_dir_number_to_offset, entryPtr)) + { + return 0; + } + } return 1; } @@ -5407,30 +5447,22 @@ int _TIFFCheckDirNumberAndOffset(TIFF *tif, tdir_t dirn, uint64_t diroff) return 0; } - TIFFOffsetAndDirNumber *entry1 = - (TIFFOffsetAndDirNumber *)malloc(sizeof(TIFFOffsetAndDirNumber)); - TIFFOffsetAndDirNumber *entry2 = + TIFFOffsetAndDirNumber *entryPtr = (TIFFOffsetAndDirNumber *)malloc(sizeof(TIFFOffsetAndDirNumber)); - if (entry1 == NULL || entry2 == NULL) + if (entryPtr == NULL) { - free(entry1); - free(entry2); return 0; } /* Add IFD offset and dirn to IFD directory list */ - *entry1 = entry; - *entry2 = entry; + *entryPtr = entry; - if (!TIFFHashSetInsert(tif->tif_map_dir_offset_to_number, entry1)) + if (!TIFFHashSetInsert(tif->tif_map_dir_offset_to_number, entryPtr)) { - free(entry1); - free(entry2); return 0; } - if (!TIFFHashSetInsert(tif->tif_map_dir_number_to_offset, entry2)) + if (!TIFFHashSetInsert(tif->tif_map_dir_number_to_offset, entryPtr)) { - free(entry2); return 0; } diff --git a/libtiff/tif_hash_set.c b/libtiff/tif_hash_set.c index e2b18331..5fbfbbea 100644 --- a/libtiff/tif_hash_set.c +++ b/libtiff/tif_hash_set.c @@ -504,7 +504,6 @@ void *TIFFHashSetLookup(TIFFHashSet *set, const void *elt) return NULL; } -#ifdef notused /************************************************************************/ /* TIFFHashSetRemoveInternal() */ /************************************************************************/ @@ -575,6 +574,7 @@ bool TIFFHashSetRemove(TIFFHashSet *set, const void *elt) return TIFFHashSetRemoveInternal(set, elt, false); } +#ifdef notused /************************************************************************/ /* TIFFHashSetRemoveDeferRehash() */ /************************************************************************/ diff --git a/libtiff/tif_hash_set.h b/libtiff/tif_hash_set.h index 5d412468..1a3f8da6 100644 --- a/libtiff/tif_hash_set.h +++ b/libtiff/tif_hash_set.h @@ -87,8 +87,9 @@ extern "C" void *TIFFHashSetLookup(TIFFHashSet *set, const void *elt); -#ifdef notused bool TIFFHashSetRemove(TIFFHashSet *set, const void *elt); + +#ifdef notused bool TIFFHashSetRemoveDeferRehash(TIFFHashSet *set, const void *elt); #endif diff --git a/libtiff/tif_open.c b/libtiff/tif_open.c index 953d8258..8a86a269 100644 --- a/libtiff/tif_open.c +++ b/libtiff/tif_open.c @@ -26,6 +26,7 @@ * TIFF Library. */ #include "tiffiop.h" +#include <limits.h> /* * Dummy functions to fill the omitted client procedures. @@ -241,7 +242,7 @@ TIFF *TIFFClientOpenExt(const char *name, const char *mode, tif->tif_name = (char *)tif + sizeof(TIFF); strcpy(tif->tif_name, name); tif->tif_mode = m & ~(O_CREAT | O_TRUNC); - tif->tif_curdir = (uint16_t)-1; /* non-existent directory */ + tif->tif_curdir = TIFF_NON_EXISTENT_DIR_NUMBER; /* non-existent directory */ tif->tif_curoff = 0; tif->tif_curstrip = (uint32_t)-1; /* invalid strip */ tif->tif_row = (uint32_t)-1; /* read/write pre-increment */ diff --git a/libtiff/tiffiop.h b/libtiff/tiffiop.h index fe677071..791881a3 100644 --- a/libtiff/tiffiop.h +++ b/libtiff/tiffiop.h @@ -51,6 +51,8 @@ #include "tif_dir.h" +#include <limits.h> + #ifndef STRIP_SIZE_DEFAULT #define STRIP_SIZE_DEFAULT 8192 #endif @@ -59,6 +61,8 @@ #define TIFF_MAX_DIR_COUNT 1048576 #endif +#define TIFF_NON_EXISTENT_DIR_NUMBER UINT_MAX + #define streq(a, b) (strcmp(a, b) == 0) #define strneq(a, b, n) (strncmp(a, b, n) == 0) |