summaryrefslogtreecommitdiff
path: root/libtiff
diff options
context:
space:
mode:
authorEven Rouault <even.rouault@spatialys.com>2022-12-13 15:14:47 +0100
committerEven Rouault <even.rouault@spatialys.com>2022-12-13 15:14:47 +0100
commit2c0f2ed803c84ec9244236c59dacf4dc32447ecc (patch)
tree7dec947c3ca18d4c0e4d57fc1538cc6b351ac4e3 /libtiff
parent2c1d4b6b01102fb8733bad6d00af5a8c21aa8e45 (diff)
downloadlibtiff-git-2c0f2ed803c84ec9244236c59dacf4dc32447ecc.tar.gz
Fix IFD loop detection
Diffstat (limited to 'libtiff')
-rw-r--r--libtiff/tif_dir.c7
-rw-r--r--libtiff/tif_dirread.c78
-rw-r--r--libtiff/tif_hash_set.c2
-rw-r--r--libtiff/tif_hash_set.h3
-rw-r--r--libtiff/tif_open.c3
-rw-r--r--libtiff/tiffiop.h4
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)