libtiff: _TIFFCheckDirNumberAndOffset(): fix recently introduced use-after-free found by CIFuzz on GDAL

From ff9a315b42b66f18a01378cf21e2eb405fbc131e Mon Sep 17 00:00:00 2001
From: Even Rouault <[EMAIL REDACTED]>
Date: Tue, 13 Dec 2022 18:06:33 +0100
Subject: [PATCH] _TIFFCheckDirNumberAndOffset(): fix recently introduced
 use-after-free found by CIFuzz on GDAL

---
 libtiff/tif_dirread.c | 23 +++++++++++++++++++----
 1 file changed, 19 insertions(+), 4 deletions(-)

diff --git a/libtiff/tif_dirread.c b/libtiff/tif_dirread.c
index 1be962ce..35425b4b 100644
--- a/libtiff/tif_dirread.c
+++ b/libtiff/tif_dirread.c
@@ -5400,19 +5400,22 @@ int _TIFFCheckDirNumberAndOffset(TIFF *tif, tdir_t dirn, uint64_t diroff)
             TIFFOffsetAndDirNumber entryOld;
             entryOld.offset = foundEntry->offset;
             entryOld.dirNumber = dirn;
+            /* We must remove first from tif_map_dir_number_to_offset as the */
+            /* entry is owned (and thus freed) by */
+            /* tif_map_dir_offset_to_number */
             TIFFOffsetAndDirNumber *foundEntryOld =
                 (TIFFOffsetAndDirNumber *)TIFFHashSetLookup(
-                    tif->tif_map_dir_offset_to_number, &entryOld);
+                    tif->tif_map_dir_number_to_offset, &entryOld);
             if (foundEntryOld)
             {
-                TIFFHashSetRemove(tif->tif_map_dir_offset_to_number,
+                TIFFHashSetRemove(tif->tif_map_dir_number_to_offset,
                                   foundEntryOld);
             }
             foundEntryOld = (TIFFOffsetAndDirNumber *)TIFFHashSetLookup(
-                tif->tif_map_dir_number_to_offset, &entryOld);
+                tif->tif_map_dir_offset_to_number, &entryOld);
             if (foundEntryOld)
             {
-                TIFFHashSetRemove(tif->tif_map_dir_number_to_offset,
+                TIFFHashSetRemove(tif->tif_map_dir_offset_to_number,
                                   foundEntryOld);
             }
 
@@ -5428,10 +5431,16 @@ int _TIFFCheckDirNumberAndOffset(TIFF *tif, tdir_t dirn, uint64_t diroff)
 
             if (!TIFFHashSetInsert(tif->tif_map_dir_offset_to_number, entryPtr))
             {
+                TIFFErrorExtR(
+                    tif, "_TIFFCheckDirNumberAndOffset",
+                    "Insertion in tif_map_dir_offset_to_number failed");
                 return 0;
             }
             if (!TIFFHashSetInsert(tif->tif_map_dir_number_to_offset, entryPtr))
             {
+                TIFFErrorExtR(
+                    tif, "_TIFFCheckDirNumberAndOffset",
+                    "Insertion in tif_map_dir_number_to_offset failed");
                 return 0;
             }
         }
@@ -5451,6 +5460,8 @@ int _TIFFCheckDirNumberAndOffset(TIFF *tif, tdir_t dirn, uint64_t diroff)
         (TIFFOffsetAndDirNumber *)malloc(sizeof(TIFFOffsetAndDirNumber));
     if (entryPtr == NULL)
     {
+        TIFFErrorExtR(tif, "_TIFFCheckDirNumberAndOffset",
+                      "malloc(sizeof(TIFFOffsetAndDirNumber)) failed");
         return 0;
     }
 
@@ -5459,10 +5470,14 @@ int _TIFFCheckDirNumberAndOffset(TIFF *tif, tdir_t dirn, uint64_t diroff)
 
     if (!TIFFHashSetInsert(tif->tif_map_dir_offset_to_number, entryPtr))
     {
+        TIFFErrorExtR(tif, "_TIFFCheckDirNumberAndOffset",
+                      "Insertion in tif_map_dir_offset_to_number failed");
         return 0;
     }
     if (!TIFFHashSetInsert(tif->tif_map_dir_number_to_offset, entryPtr))
     {
+        TIFFErrorExtR(tif, "_TIFFCheckDirNumberAndOffset",
+                      "Insertion in tif_map_dir_number_to_offset failed");
         return 0;
     }