libtiff: Merge branch '_TIFFCleanupIFDOffsetAndNumberMaps' into 'master'

From 4eea4d5d934f4d59e676085274bbbc5439cfc80e Mon Sep 17 00:00:00 2001
From: Even Rouault <[EMAIL REDACTED]>
Date: Fri, 6 Jan 2023 00:33:09 +0100
Subject: [PATCH 1/5] Add _TIFFCleanupIFDOffsetAndNumberMaps() and call it from
 TIFFUnlinkDirectory()

---
 libtiff/tif_close.c | 21 +++++++++++++++++++--
 libtiff/tif_dir.c   |  2 ++
 libtiff/tiffiop.h   |  2 ++
 3 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/libtiff/tif_close.c b/libtiff/tif_close.c
index 06aa29f5..985d290c 100644
--- a/libtiff/tif_close.c
+++ b/libtiff/tif_close.c
@@ -51,8 +51,7 @@ void TIFFCleanup(TIFF *tif)
     (*tif->tif_cleanup)(tif);
     TIFFFreeDirectory(tif);
 
-    TIFFHashSetDestroy(tif->tif_map_dir_offset_to_number);
-    TIFFHashSetDestroy(tif->tif_map_dir_number_to_offset);
+    _TIFFCleanupIFDOffsetAndNumberMaps(tif);
 
     /*
      * Clean up client info links.
@@ -114,6 +113,24 @@ void TIFFCleanup(TIFF *tif)
     _TIFFfreeExt(NULL, tif);
 }
 
+/************************************************************************/
+/*                    _TIFFCleanupIFDOffsetAndNumberMaps()              */
+/************************************************************************/
+
+void _TIFFCleanupIFDOffsetAndNumberMaps(TIFF *tif)
+{
+    if (tif->tif_map_dir_offset_to_number)
+    {
+        TIFFHashSetDestroy(tif->tif_map_dir_offset_to_number);
+        tif->tif_map_dir_offset_to_number = NULL;
+    }
+    if (tif->tif_map_dir_number_to_offset)
+    {
+        TIFFHashSetDestroy(tif->tif_map_dir_number_to_offset);
+        tif->tif_map_dir_number_to_offset = NULL;
+    }
+}
+
 /************************************************************************/
 /*                            TIFFClose()                               */
 /************************************************************************/
diff --git a/libtiff/tif_dir.c b/libtiff/tif_dir.c
index c7789bb8..804ed6f9 100644
--- a/libtiff/tif_dir.c
+++ b/libtiff/tif_dir.c
@@ -2231,5 +2231,7 @@ int TIFFUnlinkDirectory(TIFF *tif, tdir_t dirn)
     tif->tif_curoff = 0;
     tif->tif_row = (uint32_t)-1;
     tif->tif_curstrip = (uint32_t)-1;
+    tif->tif_curdir = TIFF_NON_EXISTENT_DIR_NUMBER;
+    _TIFFCleanupIFDOffsetAndNumberMaps(tif);
     return (1);
 }
diff --git a/libtiff/tiffiop.h b/libtiff/tiffiop.h
index 791881a3..bf8afb2a 100644
--- a/libtiff/tiffiop.h
+++ b/libtiff/tiffiop.h
@@ -444,6 +444,8 @@ extern "C"
     extern float _TIFFClampDoubleToFloat(double);
     extern uint32_t _TIFFClampDoubleToUInt32(double);
 
+    extern void _TIFFCleanupIFDOffsetAndNumberMaps(TIFF *tif);
+
     extern tmsize_t _TIFFReadEncodedStripAndAllocBuffer(TIFF *tif,
                                                         uint32_t strip,
                                                         void **buf,

From e146a61d9d4f55164de2e416584b1138d1a38b88 Mon Sep 17 00:00:00 2001
From: Even Rouault <even.rouault@spatialys.com>
Date: Fri, 6 Jan 2023 15:17:58 +0100
Subject: [PATCH 2/5] TIFFUnlinkDirectory(): reset tif_dirnumber

---
 libtiff/tif_dir.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/libtiff/tif_dir.c b/libtiff/tif_dir.c
index 804ed6f9..396fbd93 100644
--- a/libtiff/tif_dir.c
+++ b/libtiff/tif_dir.c
@@ -2232,6 +2232,7 @@ int TIFFUnlinkDirectory(TIFF *tif, tdir_t dirn)
     tif->tif_row = (uint32_t)-1;
     tif->tif_curstrip = (uint32_t)-1;
     tif->tif_curdir = TIFF_NON_EXISTENT_DIR_NUMBER;
+    tif->tif_dirnumber = 0;
     _TIFFCleanupIFDOffsetAndNumberMaps(tif);
     return (1);
 }

From 1123f312b4a2cdba920ed42dc5793cc876bb9982 Mon Sep 17 00:00:00 2001
From: Even Rouault <even.rouault@spatialys.com>
Date: Fri, 6 Jan 2023 15:18:36 +0100
Subject: [PATCH 3/5] struct tiff: remove unused tif_dirlistoff

---
 libtiff/tiffiop.h | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/libtiff/tiffiop.h b/libtiff/tiffiop.h
index bf8afb2a..f593163e 100644
--- a/libtiff/tiffiop.h
+++ b/libtiff/tiffiop.h
@@ -143,11 +143,9 @@ struct tiff
 #define TIFF_CHOPPEDUPARRAYS                                                   \
     0x4000000U /* set when allocChoppedUpStripArrays() has modified strip      \
                   array */
-    uint64_t tif_diroff;      /* file offset of current directory */
-    uint64_t tif_nextdiroff;  /* file offset of following directory */
-    uint64_t tif_lastdiroff;  /* file offset of last directory written so far */
-    uint64_t *tif_dirlistoff; /* list of offsets to already seen directories to
-                                 prevent IFD looping */
+    uint64_t tif_diroff;     /* file offset of current directory */
+    uint64_t tif_nextdiroff; /* file offset of following directory */
+    uint64_t tif_lastdiroff; /* file offset of last directory written so far */
     TIFFHashSet *tif_map_dir_offset_to_number;
     TIFFHashSet *tif_map_dir_number_to_offset;
     tdir_t tif_dirnumber;  /* number of already seen directories */

From 47591619e1e5a7041787c25df88cc9af344972d6 Mon Sep 17 00:00:00 2001
From: Even Rouault <even.rouault@spatialys.com>
Date: Fri, 6 Jan 2023 15:19:40 +0100
Subject: [PATCH 4/5] TIFFSetSubDirectory(): call
 _TIFFCleanupIFDOffsetAndNumberMaps()

---
 libtiff/tif_dir.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/libtiff/tif_dir.c b/libtiff/tif_dir.c
index 396fbd93..4a3211e2 100644
--- a/libtiff/tif_dir.c
+++ b/libtiff/tif_dir.c
@@ -2105,6 +2105,7 @@ int TIFFSetSubDirectory(TIFF *tif, uint64_t diroff)
         /* Reset IFD list to start new one for SubIFD chain and also start
          * SubIFD chain with tif_curdir=0. */
         tif->tif_dirnumber = 0;
+        _TIFFCleanupIFDOffsetAndNumberMaps(tif); /* invalidate IFD loop lists */
         tif->tif_curdir = 0; /* first directory of new chain */
         /* add this offset to new IFD list */
         _TIFFCheckDirNumberAndOffset(tif, tif->tif_curdir, diroff);

From c074eb73d3b0618ecb9d95941bc82a39de727e1c Mon Sep 17 00:00:00 2001
From: Even Rouault <even.rouault@spatialys.com>
Date: Fri, 6 Jan 2023 15:23:06 +0100
Subject: [PATCH 5/5] Remove use of tif_dirnumber

---
 libtiff/tif_dir.c      |  2 --
 libtiff/tif_dirread.c  | 12 ++----------
 libtiff/tif_hash_set.c |  2 --
 libtiff/tif_hash_set.h |  4 ++--
 libtiff/tif_open.c     |  1 -
 libtiff/tiffiop.h      |  1 -
 6 files changed, 4 insertions(+), 18 deletions(-)

diff --git a/libtiff/tif_dir.c b/libtiff/tif_dir.c
index 4a3211e2..8c275e04 100644
--- a/libtiff/tif_dir.c
+++ b/libtiff/tif_dir.c
@@ -2104,7 +2104,6 @@ int TIFFSetSubDirectory(TIFF *tif, uint64_t diroff)
     {
         /* Reset IFD list to start new one for SubIFD chain and also start
          * SubIFD chain with tif_curdir=0. */
-        tif->tif_dirnumber = 0;
         _TIFFCleanupIFDOffsetAndNumberMaps(tif); /* invalidate IFD loop lists */
         tif->tif_curdir = 0; /* first directory of new chain */
         /* add this offset to new IFD list */
@@ -2233,7 +2232,6 @@ int TIFFUnlinkDirectory(TIFF *tif, tdir_t dirn)
     tif->tif_row = (uint32_t)-1;
     tif->tif_curstrip = (uint32_t)-1;
     tif->tif_curdir = TIFF_NON_EXISTENT_DIR_NUMBER;
-    tif->tif_dirnumber = 0;
     _TIFFCleanupIFDOffsetAndNumberMaps(tif);
     return (1);
 }
diff --git a/libtiff/tif_dirread.c b/libtiff/tif_dirread.c
index 35425b4b..ef21f7f5 100644
--- a/libtiff/tif_dirread.c
+++ b/libtiff/tif_dirread.c
@@ -5448,7 +5448,8 @@ int _TIFFCheckDirNumberAndOffset(TIFF *tif, tdir_t dirn, uint64_t diroff)
     }
 
     /* Arbitrary (hopefully big enough) limit */
-    if (tif->tif_dirnumber >= TIFF_MAX_DIR_COUNT)
+    if (TIFFHashSetSize(tif->tif_map_dir_offset_to_number) >=
+        TIFF_MAX_DIR_COUNT)
     {
         TIFFErrorExtR(tif, "_TIFFCheckDirNumberAndOffset",
                       "Cannot handle more than %u TIFF directories",
@@ -5481,8 +5482,6 @@ int _TIFFCheckDirNumberAndOffset(TIFF *tif, tdir_t dirn, uint64_t diroff)
         return 0;
     }
 
-    tif->tif_dirnumber++;
-
     return 1;
 } /* --- _TIFFCheckDirNumberAndOffset() ---*/
 
@@ -5497,13 +5496,6 @@ int _TIFFGetDirNumberFromOffset(TIFF *tif, uint64_t diroff, tdir_t *dirn)
 {
     if (diroff == 0) /* no more directories */
         return 0;
-    if (tif->tif_dirnumber >= TIFF_MAX_DIR_COUNT)
-    {
-        TIFFErrorExtR(tif, "_TIFFGetDirNumberFromOffset",
-                      "Cannot handle more than %u TIFF directories",
-                      TIFF_MAX_DIR_COUNT);
-        return 0;
-    }
 
     /* Check if offset is already in the list and return matching directory
      * number. Otherwise update IFD list using TIFFNumberOfDirectories() and
diff --git a/libtiff/tif_hash_set.c b/libtiff/tif_hash_set.c
index 37adf61a..22f05d03 100644
--- a/libtiff/tif_hash_set.c
+++ b/libtiff/tif_hash_set.c
@@ -162,7 +162,6 @@ TIFFHashSet *TIFFHashSetNew(TIFFHashSetHashFunc fnHashFunc,
     return set;
 }
 
-#ifdef notdef
 /************************************************************************/
 /*                          TIFFHashSetSize()                            */
 /************************************************************************/
@@ -182,7 +181,6 @@ int TIFFHashSetSize(const TIFFHashSet *set)
     assert(set != NULL);
     return set->nSize;
 }
-#endif
 
 /************************************************************************/
 /*                       TIFFHashSetGetNewListElt()                      */
diff --git a/libtiff/tif_hash_set.h b/libtiff/tif_hash_set.h
index 1a3f8da6..f60e2c67 100644
--- a/libtiff/tif_hash_set.h
+++ b/libtiff/tif_hash_set.h
@@ -71,11 +71,11 @@ extern "C"
 
     void TIFFHashSetDestroy(TIFFHashSet *set);
 
+    int TIFFHashSetSize(const TIFFHashSet *set);
+
 #ifdef notused
     void TIFFHashSetClear(TIFFHashSet *set);
 
-    int TIFFHashSetSize(const TIFFHashSet *set);
-
     /** TIFFHashSetIterEltFunc */
     typedef int (*TIFFHashSetIterEltFunc)(void *elt, void *user_data);
 
diff --git a/libtiff/tif_open.c b/libtiff/tif_open.c
index 8a86a269..e84ef6d2 100644
--- a/libtiff/tif_open.c
+++ b/libtiff/tif_open.c
@@ -485,7 +485,6 @@ TIFF *TIFFClientOpenExt(const char *name, const char *mode,
             goto bad;
         tif->tif_diroff = 0;
         tif->tif_lastdiroff = 0;
-        tif->tif_dirnumber = 0;
         return (tif);
     }
     /*
diff --git a/libtiff/tiffiop.h b/libtiff/tiffiop.h
index f593163e..c419608d 100644
--- a/libtiff/tiffiop.h
+++ b/libtiff/tiffiop.h
@@ -148,7 +148,6 @@ struct tiff
     uint64_t tif_lastdiroff; /* file offset of last directory written so far */
     TIFFHashSet *tif_map_dir_offset_to_number;
     TIFFHashSet *tif_map_dir_number_to_offset;
-    tdir_t tif_dirnumber;  /* number of already seen directories */
     TIFFDirectory tif_dir; /* internal rep of current directory */
     TIFFDirectory
         tif_customdir; /* custom IFDs are separated from the main ones */