Upgrade libtiff from 4.7.1 to 4.7.2

Change-Id: I1ba302a3a911b414b99485de73199286dcb1e683
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/152530
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/third_party/libtiff/0034-tiff-jpeg-overflow.patch b/third_party/libtiff/0034-tiff-jpeg-overflow.patch
deleted file mode 100644
index f03fa94..0000000
--- a/third_party/libtiff/0034-tiff-jpeg-overflow.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-commit 0f726d9477a11e15eb67ca349c03907f6cfb82a9
-Author: Mikhail Khachaiants <mkhachaiants@gmail.com>
-Date:   Mon Dec 1 22:26:34 2025 +0200
-
-    tif_jpeg: reject mismatched JPEG data precision to avoid write overflow
-    
-    Ensure TIFF BitsPerSample matches both BITS_IN_JSAMPLE and the JPEG
-    header data_precision for JPEG-compressed images. This prevents
-    under-sized scanline buffers that can lead to write buffer overflows
-    in jdcolor.c/null_convert when decoding malformed inputs.
-
-diff --git a/libtiff/tif_jpeg.c b/libtiff/tif_jpeg.c
-index aba5f99b..4d6370b5 100644
---- a/libtiff/tif_jpeg.c
-+++ b/libtiff/tif_jpeg.c
-@@ -1282,7 +1282,8 @@ int TIFFJPEGIsFullStripRequired(TIFF *tif)
-     sp->cinfo.d.data_precision = td->td_bitspersample;
-     sp->cinfo.d.bits_in_jsample = td->td_bitspersample;
- #else
--    if (sp->cinfo.d.data_precision != td->td_bitspersample)
-+    if (td->td_bitspersample != BITS_IN_JSAMPLE ||
-+        sp->cinfo.d.data_precision != td->td_bitspersample)
-     {
-         TIFFErrorExtR(tif, module, "Improper JPEG data precision");
-         return (0);
diff --git a/third_party/libtiff/0035-ycbcr-tile-overflow.patch b/third_party/libtiff/0035-ycbcr-tile-overflow.patch
deleted file mode 100644
index 7f43f9a..0000000
--- a/third_party/libtiff/0035-ycbcr-tile-overflow.patch
+++ /dev/null
@@ -1,48 +0,0 @@
-commit 782a11d6b5b61c6dc21e714950a4af5bf89f023c
-Author: Even Rouault <even.rouault@spatialys.com>
-Date:   Sun Feb 22 23:32:47 2026 +0100
-
-    TIFFReadRGBAImage(): prevent integer overflow and later heap overflow on images with huge width in YCbCr tile decoding functions
-    
-    Fixes https://gitlab.com/libtiff/libtiff/-/issues/787
-
-diff --git a/libtiff/tif_getimage.c b/libtiff/tif_getimage.c
-index 4543ddda..fa82d091 100644
---- a/libtiff/tif_getimage.c
-+++ b/libtiff/tif_getimage.c
-@@ -2224,7 +2224,7 @@ DECLAREContigPutFunc(putcontig8bitYCbCr44tile)
-     uint32_t *cp1 = cp + w + toskew;
-     uint32_t *cp2 = cp1 + w + toskew;
-     uint32_t *cp3 = cp2 + w + toskew;
--    int32_t incr = 3 * w + 4 * toskew;
-+    const tmsize_t incr = 3 * (tmsize_t)w + 4 * (tmsize_t)toskew;
- 
-     (void)y;
-     /* adjust fromskew */
-@@ -2364,7 +2364,7 @@ DECLAREContigPutFunc(putcontig8bitYCbCr44tile)
- DECLAREContigPutFunc(putcontig8bitYCbCr42tile)
- {
-     uint32_t *cp1 = cp + w + toskew;
--    int32_t incr = 2 * toskew + w;
-+    const tmsize_t incr = 2 * (tmsize_t)toskew + w;
- 
-     (void)y;
-     fromskew = (fromskew / 4) * (4 * 2 + 2);
-@@ -2522,7 +2522,7 @@ DECLAREContigPutFunc(putcontig8bitYCbCr41tile)
- DECLAREContigPutFunc(putcontig8bitYCbCr22tile)
- {
-     uint32_t *cp2;
--    int32_t incr = 2 * toskew + w;
-+    const tmsize_t incr = 2 * (tmsize_t)toskew + w;
-     (void)y;
-     fromskew = (fromskew / 2) * (2 * 2 + 2);
-     cp2 = cp + w + toskew;
-@@ -2625,7 +2625,7 @@ DECLAREContigPutFunc(putcontig8bitYCbCr21tile)
- DECLAREContigPutFunc(putcontig8bitYCbCr12tile)
- {
-     uint32_t *cp2;
--    int32_t incr = 2 * toskew + w;
-+    const tmsize_t incr = 2 * (tmsize_t)toskew + w;
-     (void)y;
-     fromskew = (fromskew / 1) * (1 * 2 + 2);
-     cp2 = cp + w + toskew;
diff --git a/third_party/libtiff/README.pdfium b/third_party/libtiff/README.pdfium
index b275649..17d27a7 100644
--- a/third_party/libtiff/README.pdfium
+++ b/third_party/libtiff/README.pdfium
@@ -1,9 +1,9 @@
 Name: LibTIFF
 URL: https://gitlab.com/libtiff/libtiff
-Version: 4.7.1
-Revision: 5fe20d0e9aba49a6a350ed533459d1505203838f
+Version: 4.7.2
+Revision: d01a94be176f5f6a87f7ee1c0b32e65416aa2b4d
 Update Mechanism: Manual
-CPEPrefix: cpe:/a:libtiff:libtiff:4.7.1
+CPEPrefix: cpe:/a:libtiff:libtiff:4.7.2
 Security Critical: yes
 Shipped: yes
 License: libtiff
@@ -19,5 +19,3 @@
 0028-nstrips-OOM.patch: return error for excess number of tiles/strips.
 0031-safe_size_ingtStripContig.patch: return error if the size to read overflow from int32.
 0033-avail-out-overflow.patch: signed comparison in PixarLogDecode().
-0034-tiff-jpeg-overflow.patch: reject mismatched JPEG data precision.
-0035-ycbcr-tile-overflow.patch: prevent integer overflows in YCbCr tile decoding functions
diff --git a/third_party/libtiff/tif_aux.c b/third_party/libtiff/tif_aux.c
index 31b2400..1b2db76 100644
--- a/third_party/libtiff/tif_aux.c
+++ b/third_party/libtiff/tif_aux.c
@@ -56,6 +56,21 @@
     return first * second;
 }
 
+uint64_t _TIFFAdd64(TIFF *tif, uint64_t first, uint64_t second,
+                    const char *where)
+{
+    if (first > UINT64_MAX - second)
+    {
+        if (tif != NULL && where != NULL)
+        {
+            TIFFErrorExtR(tif, where, "Integer overflow in %s", where);
+        }
+        return 0;
+    }
+
+    return first + second;
+}
+
 tmsize_t _TIFFMultiplySSize(TIFF *tif, tmsize_t first, tmsize_t second,
                             const char *where)
 {
@@ -81,6 +96,30 @@
     return first * second;
 }
 
+tmsize_t _TIFFAddSSize(TIFF *tif, tmsize_t first, tmsize_t second,
+                       const char *where)
+{
+    if (first < 0 || second < 0)
+    {
+        if (tif != NULL && where != NULL)
+        {
+            TIFFErrorExtR(tif, where,
+                          "Invalid argument to _TIFFAddSSize() in %s", where);
+        }
+        return 0;
+    }
+
+    if (first > TIFF_TMSIZE_T_MAX - second)
+    {
+        if (tif != NULL && where != NULL)
+        {
+            TIFFErrorExtR(tif, where, "Integer overflow in %s", where);
+        }
+        return 0;
+    }
+    return first + second;
+}
+
 tmsize_t _TIFFCastUInt64ToSSize(TIFF *tif, uint64_t val, const char *module)
 {
     if (val > (uint64_t)TIFF_TMSIZE_T_MAX)
@@ -94,6 +133,55 @@
     return (tmsize_t)val;
 }
 
+uint32_t _TIFFCastUInt64ToUInt32(TIFF *tif, uint64_t val, const char *module)
+{
+    if (val > UINT32_MAX)
+    {
+        if (tif != NULL && module != NULL)
+        {
+            TIFFErrorExtR(tif, module, "Integer overflow");
+        }
+        return 0;
+    }
+    return (uint32_t)val;
+}
+
+tmsize_t _TIFFComputeRowOffset(TIFF *tif, tmsize_t rowstride, uint32_t row,
+                               const char *where)
+{
+    if (row == 0)
+        return 0;
+    return _TIFFMultiplySSize(tif, rowstride, (tmsize_t)row, where);
+}
+
+uint64_t _TIFFComputeBitOffset(TIFF *tif, uint32_t col, uint16_t spp,
+                               uint16_t bps, const char *where)
+{
+    uint64_t samples = _TIFFMultiply64(tif, col, spp, where);
+    if (samples == 0 && col != 0)
+        return 0;
+    return _TIFFMultiply64(tif, samples, bps, where);
+}
+
+/*
+ * Returns 0 on overflow or invalid zero-sized row inputs. Callers that
+ * intentionally allow empty rows should not use this helper directly.
+ */
+uint64_t _TIFFComputeRowSize64(TIFF *tif, uint32_t width, uint16_t spp,
+                               uint16_t bps, const char *where)
+{
+    uint64_t samples = _TIFFMultiply64(tif, width, spp, where);
+    uint64_t bits;
+    if (samples == 0)
+        return 0;
+
+    bits = _TIFFMultiply64(tif, samples, bps, where);
+    if (bits == 0)
+        return 0;
+
+    return TIFFhowmany8_64(bits);
+}
+
 void *_TIFFCheckRealloc(TIFF *tif, void *buffer, tmsize_t nmemb,
                         tmsize_t elem_size, const char *what)
 {
@@ -137,8 +225,8 @@
     if (td->td_bitspersample > 24)
         return 0;
 
-    n = ((tmsize_t)1) << td->td_bitspersample;
-    nbytes = n * sizeof(uint16_t);
+    n = (tmsize_t)(1ULL << td->td_bitspersample);
+    nbytes = (tmsize_t)((uint64_t)n * sizeof(uint16_t));
     tf[0] = (uint16_t *)_TIFFmallocExt(tif, nbytes);
     if (tf[0] == NULL)
         return 0;
@@ -186,10 +274,10 @@
          * YCbCr (Class Y) images must have the ReferenceBlackWhite
          * tag set. Fix the broken images, which lacks that tag.
          */
-        td->td_refblackwhite[0] = 0.0F;
+        td->td_refblackwhite[0] = 0.0f;
         td->td_refblackwhite[1] = td->td_refblackwhite[3] =
-            td->td_refblackwhite[5] = 255.0F;
-        td->td_refblackwhite[2] = td->td_refblackwhite[4] = 128.0F;
+            td->td_refblackwhite[5] = 255.0f;
+        td->td_refblackwhite[2] = td->td_refblackwhite[4] = 128.0f;
     }
     else
     {
@@ -199,8 +287,11 @@
         for (i = 0; i < 3; i++)
         {
             td->td_refblackwhite[2 * i + 0] = 0;
-            td->td_refblackwhite[2 * i + 1] =
-                (float)((1L << td->td_bitspersample) - 1L);
+            if (td->td_bitspersample < 64)
+                td->td_refblackwhite[2 * i + 1] =
+                    (float)((1ULL << td->td_bitspersample) - 1ULL);
+            else
+                td->td_refblackwhite[2 * i + 1] = (float)UINT64_MAX;
         }
     }
     return 1;
@@ -258,8 +349,8 @@
                  * 65535 even if td_bitspersamle is > 16 */
                 if (td->td_bitspersample <= 16)
                 {
-                    maxsamplevalue = (1 << td->td_bitspersample) -
-                                     1; /* 2**(BitsPerSample) - 1 */
+                    maxsamplevalue = (uint16_t)((1U << td->td_bitspersample) -
+                                                1); /* 2**(BitsPerSample) - 1 */
                 }
                 else
                 {
@@ -295,7 +386,11 @@
         }
         case TIFFTAG_DOTRANGE:
             *va_arg(ap, uint16_t *) = 0;
-            *va_arg(ap, uint16_t *) = (1 << td->td_bitspersample) - 1;
+            if (td->td_bitspersample <= 16)
+                *va_arg(ap, uint16_t *) =
+                    (uint16_t)((1U << td->td_bitspersample) - 1);
+            else
+                *va_arg(ap, uint16_t *) = 65535;
             return (1);
         case TIFFTAG_INKSET:
             *va_arg(ap, uint16_t *) = INKSET_CMYK;
@@ -309,14 +404,14 @@
             return (1);
         case TIFFTAG_MATTEING:
             *va_arg(ap, uint16_t *) =
-                (td->td_extrasamples == 1 &&
+                (td->td_extrasamples == 1 && td->td_sampleinfo &&
                  td->td_sampleinfo[0] == EXTRASAMPLE_ASSOCALPHA);
             return (1);
         case TIFFTAG_TILEDEPTH:
             *va_arg(ap, uint32_t *) = td->td_tiledepth;
             return (1);
         case TIFFTAG_DATATYPE:
-            *va_arg(ap, uint16_t *) = td->td_sampleformat - 1;
+            *va_arg(ap, uint16_t *) = (uint16_t)(td->td_sampleformat - 1);
             return (1);
         case TIFFTAG_SAMPLEFORMAT:
             *va_arg(ap, uint16_t *) = td->td_sampleformat;
@@ -369,6 +464,8 @@
                 return (0);
             *va_arg(ap, const float **) = td->td_refblackwhite;
             return (1);
+        default:
+            break;
     }
     return 0;
 }
@@ -390,9 +487,9 @@
 
 float _TIFFClampDoubleToFloat(double val)
 {
-    if (val > FLT_MAX)
+    if (val > (double)FLT_MAX)
         return FLT_MAX;
-    if (val < -FLT_MAX)
+    if (val < -(double)FLT_MAX)
         return -FLT_MAX;
     return (float)val;
 }
@@ -401,7 +498,7 @@
 {
     if (val < 0)
         return 0;
-    if (val > 0xFFFFFFFFU || val != val)
+    if (val > 0xFFFFFFFFU || isnan(val))
         return 0xFFFFFFFFU;
     return (uint32_t)val;
 }
diff --git a/third_party/libtiff/tif_close.c b/third_party/libtiff/tif_close.c
index d498010..e60aba7 100644
--- a/third_party/libtiff/tif_close.c
+++ b/third_party/libtiff/tif_close.c
@@ -88,7 +88,7 @@
                      */
                     TIFFFieldIsAnonymous(fld))
                 {
-                    _TIFFfreeExt(tif, fld->field_name);
+                    _TIFFfreeExt(tif, (void *)fld->field_name);
                     _TIFFfreeExt(tif, fld);
                 }
             }
@@ -121,7 +121,7 @@
 }
 
 /************************************************************************/
-/*                    _TIFFCleanupIFDOffsetAndNumberMaps()              */
+/*                 _TIFFCleanupIFDOffsetAndNumberMaps()                 */
 /************************************************************************/
 
 void _TIFFCleanupIFDOffsetAndNumberMaps(TIFF *tif)
@@ -139,7 +139,7 @@
 }
 
 /************************************************************************/
-/*                            TIFFClose()                               */
+/*                             TIFFClose()                              */
 /************************************************************************/
 
 /**
diff --git a/third_party/libtiff/tif_color.c b/third_party/libtiff/tif_color.c
index a52fdac..4a17914 100644
--- a/third_party/libtiff/tif_color.c
+++ b/third_party/libtiff/tif_color.c
@@ -55,34 +55,34 @@
 void TIFFCIELab16ToXYZ(TIFFCIELabToRGB *cielab, uint32_t l, int32_t a,
                        int32_t b, float *X, float *Y, float *Z)
 {
-    float L = (float)l * 100.0F / 65535.0F;
+    float L = (float)l * 100.0f / 65535.0f;
     float cby, tmp;
 
-    if (L < 8.856F)
+    if (L < 8.856f)
     {
-        *Y = (L * cielab->Y0) / 903.292F;
-        cby = 7.787F * (*Y / cielab->Y0) + 16.0F / 116.0F;
+        *Y = (L * cielab->Y0) / 903.292f;
+        cby = 7.787f * (*Y / cielab->Y0) + 16.0f / 116.0f;
     }
     else
     {
-        cby = (L + 16.0F) / 116.0F;
+        cby = (L + 16.0f) / 116.0f;
         *Y = cielab->Y0 * cby * cby * cby;
     }
 
-    tmp = (float)a / 256.0F / 500.0F + cby;
-    if (tmp < 0.2069F)
-        *X = cielab->X0 * (tmp - 0.13793F) / 7.787F;
+    tmp = (float)a / 256.0f / 500.0f + cby;
+    if (tmp < 0.2069f)
+        *X = cielab->X0 * (tmp - 0.13793f) / 7.787f;
     else
         *X = cielab->X0 * tmp * tmp * tmp;
 
-    tmp = cby - (float)b / 256.0F / 200.0F;
-    if (tmp < 0.2069F)
-        *Z = cielab->Z0 * (tmp - 0.13793F) / 7.787F;
+    tmp = cby - (float)b / 256.0f / 200.0f;
+    if (tmp < 0.2069f)
+        *Z = cielab->Z0 * (tmp - 0.13793f) / 7.787f;
     else
         *Z = cielab->Z0 * tmp * tmp * tmp;
 }
 
-#define RINT(R) ((uint32_t)((R) > 0 ? ((R) + 0.5) : ((R)-0.5)))
+#define RINT(R) ((uint32_t)((R) > 0 ? ((R) + 0.5f) : ((R) - 0.5f)))
 /*
  * Convert color value from the XYZ space to RGB.
  */
@@ -143,32 +143,32 @@
     _TIFFmemcpy(&cielab->display, display, sizeof(TIFFDisplay));
 
     /* Red */
-    dfGamma = 1.0 / cielab->display.d_gammaR;
+    dfGamma = 1.0 / (double)cielab->display.d_gammaR;
     cielab->rstep =
-        (cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range;
+        (cielab->display.d_YCR - cielab->display.d_Y0R) / (float)cielab->range;
     for (i = 0; i <= (size_t)cielab->range; i++)
     {
-        cielab->Yr2r[i] = cielab->display.d_Vrwr *
+        cielab->Yr2r[i] = (float)cielab->display.d_Vrwr *
                           ((float)pow((double)i / cielab->range, dfGamma));
     }
 
     /* Green */
-    dfGamma = 1.0 / cielab->display.d_gammaG;
+    dfGamma = 1.0 / (double)cielab->display.d_gammaG;
     cielab->gstep =
-        (cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range;
+        (cielab->display.d_YCR - cielab->display.d_Y0R) / (float)cielab->range;
     for (i = 0; i <= (size_t)cielab->range; i++)
     {
-        cielab->Yg2g[i] = cielab->display.d_Vrwg *
+        cielab->Yg2g[i] = (float)cielab->display.d_Vrwg *
                           ((float)pow((double)i / cielab->range, dfGamma));
     }
 
     /* Blue */
-    dfGamma = 1.0 / cielab->display.d_gammaB;
+    dfGamma = 1.0 / (double)cielab->display.d_gammaB;
     cielab->bstep =
-        (cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range;
+        (cielab->display.d_YCR - cielab->display.d_Y0R) / (float)cielab->range;
     for (i = 0; i <= (size_t)cielab->range; i++)
     {
-        cielab->Yb2b[i] = cielab->display.d_Vrwb *
+        cielab->Yb2b[i] = (float)cielab->display.d_Vrwb *
                           ((float)pow((double)i / cielab->range, dfGamma));
     }
 
@@ -186,11 +186,11 @@
  * see below for more information on how it works.
  */
 #define SHIFT 16
-#define FIX(x) ((int32_t)((x) * (1L << SHIFT) + 0.5))
+#define FIX(x) ((int32_t)((double)(x) * (1L << SHIFT) + 0.5))
 #define ONE_HALF ((int32_t)(1 << (SHIFT - 1)))
 #define Code2V(c, RB, RW, CR)                                                  \
-    ((((c) - (int32_t)(RB)) * (float)(CR)) /                                   \
-     (float)(((RW) - (RB) != 0) ? ((RW) - (RB)) : 1))
+    (((float)((c) - (int32_t)(RB)) * (float)(CR)) /                            \
+     ((!TIFF_FLOAT_EQ((RW), (RB))) ? ((RW) - (RB)) : 1.0f))
 /* !((f)>=(min)) written that way to deal with NaN */
 #define CLAMP(f, min, max)                                                     \
     ((!((f) >= (min))) ? (min) : (f) > (max) ? (max) : (f))
@@ -207,12 +207,12 @@
     Cr = CLAMP(Cr, 0, 255);
 
     i = ycbcr->Y_tab[Y] + ycbcr->Cr_r_tab[Cr];
-    *r = CLAMP(i, 0, 255);
+    *r = (uint32_t)CLAMP(i, 0, 255);
     i = ycbcr->Y_tab[Y] +
-        (int)((ycbcr->Cb_g_tab[Cb] + ycbcr->Cr_g_tab[Cr]) >> SHIFT);
-    *g = CLAMP(i, 0, 255);
+        ((ycbcr->Cb_g_tab[Cb] + ycbcr->Cr_g_tab[Cr]) >> SHIFT);
+    *g = (uint32_t)CLAMP(i, 0, 255);
     i = ycbcr->Y_tab[Y] + ycbcr->Cb_b_tab[Cb];
-    *b = CLAMP(i, 0, 255);
+    *b = (uint32_t)CLAMP(i, 0, 255);
 }
 
 /* Clamp function for sanitization purposes. Normally clamping should not */
@@ -258,8 +258,7 @@
 #define LumaBlue luma[2]
 
     clamptab =
-        (TIFFRGBValue *)((uint8_t *)ycbcr +
-                         TIFFroundup_32(sizeof(TIFFYCbCrToRGB), sizeof(long)));
+        (uint8_t *)ycbcr + TIFFroundup_32(sizeof(TIFFYCbCrToRGB), sizeof(long));
     _TIFFmemset(clamptab, 0, 256); /* v < 0 => 0 */
     ycbcr->clamptab = (clamptab += 256);
     for (i = 0; i < 256; i++)
@@ -273,13 +272,13 @@
 
     {
         float f1 = 2 - 2 * LumaRed;
-        int32_t D1 = FIX(CLAMP(f1, 0.0F, 2.0F));
+        int32_t D1 = FIX(CLAMP(f1, 0.0f, 2.0f));
         float f2 = LumaRed * f1 / LumaGreen;
-        int32_t D2 = -FIX(CLAMP(f2, 0.0F, 2.0F));
+        int32_t D2 = -FIX(CLAMP(f2, 0.0f, 2.0f));
         float f3 = 2 - 2 * LumaBlue;
-        int32_t D3 = FIX(CLAMP(f3, 0.0F, 2.0F));
+        int32_t D3 = FIX(CLAMP(f3, 0.0f, 2.0f));
         float f4 = LumaBlue * f3 / LumaGreen;
-        int32_t D4 = -FIX(CLAMP(f4, 0.0F, 2.0F));
+        int32_t D4 = -FIX(CLAMP(f4, 0.0f, 2.0f));
         int x;
 
 #undef LumaBlue
@@ -295,12 +294,12 @@
          */
         for (i = 0, x = -128; i < 256; i++, x++)
         {
-            int32_t Cr = (int32_t)CLAMPw(Code2V(x, refBlackWhite[4] - 128.0F,
-                                                refBlackWhite[5] - 128.0F, 127),
-                                         -128.0F * 32, 128.0F * 32);
-            int32_t Cb = (int32_t)CLAMPw(Code2V(x, refBlackWhite[2] - 128.0F,
-                                                refBlackWhite[3] - 128.0F, 127),
-                                         -128.0F * 32, 128.0F * 32);
+            int32_t Cr = (int32_t)CLAMPw(Code2V(x, refBlackWhite[4] - 128.0f,
+                                                refBlackWhite[5] - 128.0f, 127),
+                                         -128.0f * 32, 128.0f * 32);
+            int32_t Cb = (int32_t)CLAMPw(Code2V(x, refBlackWhite[2] - 128.0f,
+                                                refBlackWhite[3] - 128.0f, 127),
+                                         -128.0f * 32, 128.0f * 32);
 
             ycbcr->Cr_r_tab[i] = (int32_t)((D1 * Cr + ONE_HALF) >> SHIFT);
             ycbcr->Cb_b_tab[i] = (int32_t)((D3 * Cb + ONE_HALF) >> SHIFT);
@@ -308,7 +307,7 @@
             ycbcr->Cb_g_tab[i] = D4 * Cb + ONE_HALF;
             ycbcr->Y_tab[i] = (int32_t)CLAMPw(
                 Code2V(x + 128, refBlackWhite[0], refBlackWhite[1], 255),
-                -128.0F * 32, 128.0F * 32);
+                -128.0f * 32, 128.0f * 32);
         }
     }
 
diff --git a/third_party/libtiff/tif_compress.c b/third_party/libtiff/tif_compress.c
index c6e17d3..3002083 100644
--- a/third_party/libtiff/tif_compress.c
+++ b/third_party/libtiff/tif_compress.c
@@ -139,6 +139,18 @@
 }
 static void _TIFFvoid(TIFF *tif) { (void)tif; }
 
+static uint64_t _TIFFDefaultGetMaxCompressionRatio(TIFF *tif)
+{
+    (void)tif;
+    return 0; /* unknown */
+}
+
+static uint64_t _TIFFGetMaxCompressionRatioOne(TIFF *tif)
+{
+    (void)tif;
+    return 1; /* no compression */
+}
+
 void _TIFFSetDefaultCompressionState(TIFF *tif)
 {
     tif->tif_fixuptags = _TIFFNoFixupTags;
@@ -160,6 +172,7 @@
     tif->tif_cleanup = _TIFFvoid;
     tif->tif_defstripsize = _TIFFDefaultStripSize;
     tif->tif_deftilesize = _TIFFDefaultTileSize;
+    tif->tif_getmaxcompressionratio = _TIFFDefaultGetMaxCompressionRatio;
     tif->tif_flags &= ~(TIFF_NOBITREV | TIFF_NOREADRAW);
 }
 
@@ -168,6 +181,8 @@
     const TIFFCodec *c = TIFFFindCODEC((uint16_t)scheme);
 
     _TIFFSetDefaultCompressionState(tif);
+    if (scheme == COMPRESSION_NONE)
+        tif->tif_getmaxcompressionratio = _TIFFGetMaxCompressionRatioOne;
     /*
      * Don't treat an unknown compression scheme as an error.
      * This permits applications to open files with data that
@@ -177,6 +192,13 @@
     return (c ? (*c->init)(tif, scheme) : 1);
 }
 
+uint64_t TIFFGetMaxCompressionRatio(TIFF *tif)
+{
+    if (tif->tif_getmaxcompressionratio)
+        return tif->tif_getmaxcompressionratio(tif);
+    return 0;
+}
+
 /*
  * Other compression schemes may be registered.  Registered
  * schemes can also override the builtin versions provided
@@ -200,7 +222,7 @@
     for (c = _TIFFBuiltinCODECS; c->name; c++)
         if (c->scheme == scheme)
             return (c);
-    return ((const TIFFCodec *)0);
+    return NULL;
 }
 
 TIFFCodec *TIFFRegisterCODEC(uint16_t scheme, const char *name,
@@ -212,9 +234,11 @@
 
     if (cd != NULL)
     {
+        char *codec_name;
         cd->info = (TIFFCodec *)((uint8_t *)cd + sizeof(codec_t));
-        cd->info->name = (char *)((uint8_t *)cd->info + sizeof(TIFFCodec));
-        strcpy(cd->info->name, name);
+        codec_name = (char *)((uint8_t *)cd->info + sizeof(TIFFCodec));
+        strcpy(codec_name, name);
+        cd->info->name = codec_name;
         cd->info->scheme = scheme;
         cd->info->init = init;
         cd->next = registeredCODECS;
@@ -247,7 +271,7 @@
 }
 
 /************************************************************************/
-/*                       TIFFGetConfisuredCODECs()                      */
+/*                      TIFFGetConfiguredCODECs()                       */
 /************************************************************************/
 
 /**
@@ -258,7 +282,7 @@
  * or NULL if function failed.
  */
 
-TIFFCodec *TIFFGetConfiguredCODECs()
+TIFFCodec *TIFFGetConfiguredCODECs(void)
 {
     int i = 1;
     codec_t *cd;
@@ -268,8 +292,8 @@
 
     for (cd = registeredCODECS; cd; cd = cd->next)
     {
-        new_codecs =
-            (TIFFCodec *)_TIFFreallocExt(NULL, codecs, i * sizeof(TIFFCodec));
+        new_codecs = (TIFFCodec *)_TIFFreallocExt(
+            NULL, codecs, (tmsize_t)((size_t)i * sizeof(TIFFCodec)));
         if (!new_codecs)
         {
             _TIFFfreeExt(NULL, codecs);
@@ -283,21 +307,21 @@
     {
         if (TIFFIsCODECConfigured(c->scheme))
         {
-            new_codecs = (TIFFCodec *)_TIFFreallocExt(NULL, codecs,
-                                                      i * sizeof(TIFFCodec));
+            new_codecs = (TIFFCodec *)_TIFFreallocExt(
+                NULL, codecs, (tmsize_t)((size_t)i * sizeof(TIFFCodec)));
             if (!new_codecs)
             {
                 _TIFFfreeExt(NULL, codecs);
                 return NULL;
             }
             codecs = new_codecs;
-            _TIFFmemcpy(codecs + i - 1, (const void *)c, sizeof(TIFFCodec));
+            _TIFFmemcpy(codecs + i - 1, c, sizeof(TIFFCodec));
             i++;
         }
     }
 
-    new_codecs =
-        (TIFFCodec *)_TIFFreallocExt(NULL, codecs, i * sizeof(TIFFCodec));
+    new_codecs = (TIFFCodec *)_TIFFreallocExt(
+        NULL, codecs, (tmsize_t)((size_t)i * sizeof(TIFFCodec)));
     if (!new_codecs)
     {
         _TIFFfreeExt(NULL, codecs);
diff --git a/third_party/libtiff/tif_dir.c b/third_party/libtiff/tif_dir.c
index 7421c73..999a245 100644
--- a/third_party/libtiff/tif_dir.c
+++ b/third_party/libtiff/tif_dir.c
@@ -31,6 +31,7 @@
 #include "tiffiop.h"
 #include <float.h> /*--: for Rational2Double */
 #include <limits.h>
+#include <math.h>
 
 /*
  * These are used in the backwards compatibility code...
@@ -50,7 +51,8 @@
     }
     if (vp)
     {
-        tmsize_t bytes = _TIFFMultiplySSize(NULL, nmemb, elem_size, NULL);
+        tmsize_t bytes = _TIFFMultiplySSize(NULL, (tmsize_t)nmemb,
+                                            (tmsize_t)elem_size, NULL);
         if (bytes)
             *vpp = (void *)_TIFFmallocExt(tif, bytes);
         if (*vpp)
@@ -121,7 +123,8 @@
 {
     if (*vpp)
         _TIFFfreeExt(tif, *vpp);
-    *vpp = _TIFFmallocExt(tif, nmemb * sizeof(double));
+    *vpp = (double *)_TIFFmallocExt(tif,
+                                    (tmsize_t)nmemb * (tmsize_t)sizeof(double));
     if (*vpp)
     {
         while (nmemb--)
@@ -294,7 +297,7 @@
             /*
              * Setup new compression routine state.
              */
-            if ((status = TIFFSetCompressionScheme(tif, v)) != 0)
+            if ((status = TIFFSetCompressionScheme(tif, (int)v)) != 0)
                 td->td_compression = (uint16_t)v;
             else
                 status = 0;
@@ -402,13 +405,13 @@
             break;
         case TIFFTAG_XRESOLUTION:
             dblval = va_arg(ap, double);
-            if (dblval != dblval || dblval < 0)
+            if (isnan(dblval) || dblval < 0)
                 goto badvaluedouble;
             td->td_xresolution = _TIFFClampDoubleToFloat(dblval);
             break;
         case TIFFTAG_YRESOLUTION:
             dblval = va_arg(ap, double);
-            if (dblval != dblval || dblval < 0)
+            if (isnan(dblval) || dblval < 0)
                 goto badvaluedouble;
             td->td_yresolution = _TIFFClampDoubleToFloat(dblval);
             break;
@@ -439,7 +442,12 @@
             td->td_halftonehints[1] = (uint16_t)va_arg(ap, uint16_vap);
             break;
         case TIFFTAG_COLORMAP:
-            v32 = (uint32_t)(1L << td->td_bitspersample);
+            if (td->td_bitspersample >= 32)
+            {
+                v = td->td_bitspersample;
+                goto badvalue;
+            }
+            v32 = 1U << td->td_bitspersample;
             _TIFFsetShortArrayExt(tif, &td->td_colormap[0],
                                   va_arg(ap, uint16_t *), v32);
             _TIFFsetShortArrayExt(tif, &td->td_colormap[1],
@@ -557,11 +565,17 @@
         case TIFFTAG_TRANSFERFUNCTION:
         {
             uint32_t i;
+            uint32_t count;
+            if (td->td_bitspersample >= 32)
+            {
+                v = td->td_bitspersample;
+                goto badvalue;
+            }
+            count = 1U << td->td_bitspersample;
             v = (td->td_samplesperpixel - td->td_extrasamples) > 1 ? 3 : 1;
             for (i = 0; i < v; i++)
                 _TIFFsetShortArrayExt(tif, &td->td_transferfunction[i],
-                                      va_arg(ap, uint16_t *),
-                                      1U << td->td_bitspersample);
+                                      va_arg(ap, uint16_t *), count);
             break;
         }
         case TIFFTAG_REFERENCEBLACKWHITE:
@@ -579,7 +593,7 @@
             if (ninksinstring > 0)
             {
                 _TIFFsetNString(tif, &td->td_inknames, s, v);
-                td->td_inknameslen = v;
+                td->td_inknameslen = (int)v;
                 /* Set NumberOfInks to the value ninksinstring */
                 if (TIFFFieldSet(tif, FIELD_NUMBEROFINKS))
                 {
@@ -725,7 +739,8 @@
 
                 new_customValues = (TIFFTagValue *)_TIFFreallocExt(
                     tif, td->td_customValues,
-                    sizeof(TIFFTagValue) * (td->td_customValueCount + 1));
+                    (tmsize_t)(sizeof(TIFFTagValue) *
+                               (size_t)(td->td_customValueCount + 1)));
                 if (!new_customValues)
                 {
                     TIFFErrorExtR(tif, module,
@@ -754,7 +769,7 @@
             if (tv_size == 0)
             {
                 status = 0;
-                TIFFErrorExtR(tif, module, "%s: Bad field type %d for \"%s\"",
+                TIFFErrorExtR(tif, module, "%s: Bad field type %u for \"%s\"",
                               tif->tif_name, fip->field_type, fip->field_name);
                 goto end;
             }
@@ -784,7 +799,7 @@
                     }
                     ma = (uint32_t)len;
                 }
-                tv->count = ma;
+                tv->count = (int)ma;
                 setByteArray(tif, &tv->value, mb, ma, 1);
             }
             else
@@ -792,9 +807,9 @@
                 if (fip->field_passcount)
                 {
                     if (fip->field_writecount == TIFF_VARIABLE2)
-                        tv->count = (uint32_t)va_arg(ap, uint32_t);
+                        tv->count = (int)va_arg(ap, uint32_t);
                     else
-                        tv->count = (int)va_arg(ap, int);
+                        tv->count = va_arg(ap, int);
                 }
                 else if (fip->field_writecount == TIFF_VARIABLE ||
                          fip->field_writecount == TIFF_VARIABLE2)
@@ -808,7 +823,7 @@
                 {
                     TIFFWarningExtR(tif, module,
                                     "%s: Null count for \"%s\" (type "
-                                    "%d, writecount %d, passcount %d)",
+                                    "%u, writecount %d, passcount %d)",
                                     tif->tif_name, fip->field_name,
                                     fip->field_type, fip->field_writecount,
                                     fip->field_passcount);
@@ -845,11 +860,12 @@
                      * 4 or 8 according to fip->set_get_field_type! */
                     _TIFFmemcpy(tv->value, va_arg(ap, void *),
                                 tv->count * tv_size);
-                    /* Test here for too big values for LONG8, SLONG8 in
+                    /* Test here for too big values for LONG8, IFD8, SLONG8 in
                      * ClassicTIFF and delete custom field from custom list */
                     if (!(tif->tif_flags & TIFF_BIGTIFF))
                     {
-                        if (tv->info->field_type == TIFF_LONG8)
+                        if (tv->info->field_type == TIFF_LONG8 ||
+                            tv->info->field_type == TIFF_IFD8)
                         {
                             uint64_t *pui64 = (uint64_t *)tv->value;
                             for (int i = 0; i < tv->count; i++)
@@ -858,12 +874,15 @@
                                 {
                                     TIFFErrorExtR(
                                         tif, module,
-                                        "%s: Bad LONG8 value %" PRIu64
+                                        "%s: Bad %s value %" PRIu64
                                         " at %d. array position for \"%s\" tag "
-                                        "%d in ClassicTIFF. Tag won't be "
+                                        "%u in ClassicTIFF. Tag won't be "
                                         "written to file",
-                                        tif->tif_name, pui64[i], i,
-                                        fip->field_name, tag);
+                                        tif->tif_name,
+                                        (tv->info->field_type == TIFF_LONG8
+                                             ? "LONG8"
+                                             : "IFD8"),
+                                        pui64[i], i, fip->field_name, tag);
                                     goto badvalueifd8long8;
                                 }
                             }
@@ -880,7 +899,7 @@
                                         tif, module,
                                         "%s: Bad SLONG8 value %" PRIi64
                                         " at %d. array position for \"%s\" tag "
-                                        "%d in ClassicTIFF. Tag won't be "
+                                        "%u in ClassicTIFF. Tag won't be "
                                         "written to file",
                                         tif->tif_name, pi64[i], i,
                                         fip->field_name, tag);
@@ -948,7 +967,7 @@
                                 TIFFErrorExtR(
                                     tif, module,
                                     "%s: Bad LONG8 or IFD8 value %" PRIu64
-                                    " for \"%s\" tag %d in ClassicTIFF. Tag "
+                                    " for \"%s\" tag %u in ClassicTIFF. Tag "
                                     "won't be written to file",
                                     tif->tif_name, v2, fip->field_name, tag);
                                 goto badvalueifd8long8;
@@ -967,7 +986,7 @@
                                 TIFFErrorExtR(
                                     tif, module,
                                     "%s: Bad SLONG8 value %" PRIi64
-                                    " for \"%s\" tag %d in ClassicTIFF. Tag "
+                                    " for \"%s\" tag %u in ClassicTIFF. Tag "
                                     "won't be written to file",
                                     tif->tif_name, v2, fip->field_name, tag);
                                 goto badvalueifd8long8;
@@ -1018,6 +1037,8 @@
                             _TIFFmemcpy(val, &v2, tv_size);
                         }
                         break;
+                        case TIFF_NOTYPE:
+                        case TIFF_ASCII:
                         default:
                             _TIFFmemset(val, 0, tv_size);
                             status = 0;
@@ -1345,7 +1366,7 @@
             break;
         case TIFFTAG_MATTEING:
             *va_arg(ap, uint16_t *) =
-                (td->td_extrasamples == 1 &&
+                (td->td_extrasamples == 1 && td->td_sampleinfo &&
                  td->td_sampleinfo[0] == EXTRASAMPLE_ASSOCALPHA);
             break;
         case TIFFTAG_EXTRASAMPLES:
@@ -1376,6 +1397,8 @@
                 case SAMPLEFORMAT_VOID:
                     *va_arg(ap, uint16_t *) = DATATYPE_VOID;
                     break;
+                default:
+                    break;
             }
             break;
         case TIFFTAG_SAMPLEFORMAT:
@@ -1562,6 +1585,8 @@
                                 *va_arg(ap, double *) = *(double *)val;
                                 ret_val = 1;
                                 break;
+                            case TIFF_NOTYPE:
+                            case TIFF_ASCII:
                             default:
                                 ret_val = 0;
                                 break;
@@ -1614,6 +1639,21 @@
     }
 
 /*
+ * Reset tif->tif_dir structure to zero and
+ * initialize some IFD strile counter and index parameters.
+ */
+void _TIFFResetTifDirAndInitStrileCounters(TIFFDirectory *td)
+{
+    _TIFFmemset(td, 0, sizeof(*td));
+    td->td_curstrip = NOSTRIP;      /* invalid strip = NOSTRIP */
+    td->td_row = (uint32_t)-1;      /* read/write pre-increment */
+    td->td_col = (uint32_t)-1;      /* read/write pre-increment */
+    td->td_scanlinesize = 0;        /* initialize to zero */
+    td->td_curtile = NOTILE;        /* invalid tile = NOTILE */
+    td->td_tilesize = (tmsize_t)-1; /* invalidate tilezize */
+}
+
+/*
  * Release storage associated with a directory.
  */
 void TIFFFreeDirectory(TIFF *tif)
@@ -1664,6 +1704,7 @@
         tif->tif_dir.td_dirdatasize_Noffsets = 0;
     }
     tif->tif_dir.td_iswrittentofile = FALSE;
+    /* Note: tif->tif_dir structure is set to zero in TIFFDefaultDirectory() */
 }
 #undef CleanupField
 
@@ -1694,10 +1735,7 @@
     tif->tif_diroff = 0;
     tif->tif_nextdiroff = 0;
     tif->tif_curoff = 0;
-    tif->tif_row = (uint32_t)-1;
-    tif->tif_curstrip = (uint32_t)-1;
     tif->tif_dir.td_iswrittentofile = FALSE;
-
     return 0;
 }
 
@@ -1717,15 +1755,12 @@
     tif->tif_diroff = 0;
     tif->tif_nextdiroff = 0;
     tif->tif_curoff = 0;
-    tif->tif_row = (uint32_t)-1;
-    tif->tif_curstrip = (uint32_t)-1;
     /* invalidate directory index */
     tif->tif_curdir = TIFF_NON_EXISTENT_DIR_NUMBER;
     /* invalidate IFD loop lists */
     _TIFFCleanupIFDOffsetAndNumberMaps(tif);
     /* To be able to return from SubIFD or custom-IFD to main-IFD */
     tif->tif_setdirectory_force_absolute = TRUE;
-
     return 0;
 }
 
@@ -1751,13 +1786,14 @@
  */
 int TIFFDefaultDirectory(TIFF *tif)
 {
-    register TIFFDirectory *td = &tif->tif_dir;
+    TIFFDirectory *td = &tif->tif_dir;
     const TIFFFieldArray *tiffFieldArray;
 
     tiffFieldArray = _TIFFGetFields();
     _TIFFSetupFields(tif, tiffFieldArray);
-
-    _TIFFmemset(td, 0, sizeof(*td));
+    /* Reset tif->tif_dir structure to zero and
+     * initialize some IFD strile counter and index parameters. */
+    _TIFFResetTifDirAndInitStrileCounters(td);
     td->td_fillorder = FILLORDER_MSB2LSB;
     td->td_bitspersample = 1;
     td->td_threshholding = THRESHHOLD_BILEVEL;
@@ -1860,10 +1896,8 @@
             tmsize_t poffa, poffb, poffc, poffd;
             uint16_t dircount;
             uint32_t nextdir32;
-            poffa = (tmsize_t)poff;
-            poffb = poffa + sizeof(uint16_t);
-            if (((uint64_t)poffa != poff) || (poffb < poffa) ||
-                (poffb < (tmsize_t)sizeof(uint16_t)) || (poffb > tif->tif_size))
+            if (poff > (uint64_t)TIFF_TMSIZE_T_MAX - sizeof(uint16_t) ||
+                poff > (uint64_t)tif->tif_size - sizeof(uint16_t))
             {
                 TIFFErrorExtR(tif, module,
                               "%s:%d: %s: Error fetching directory count",
@@ -1871,13 +1905,20 @@
                 *nextdiroff = 0;
                 return (0);
             }
+            poffa = (tmsize_t)poff;
+            poffb = poffa + (tmsize_t)sizeof(uint16_t);
             _TIFFmemcpy(&dircount, tif->tif_base + poffa, sizeof(uint16_t));
             if (tif->tif_flags & TIFF_SWAB)
                 TIFFSwabShort(&dircount);
+            if (poffb >
+                TIFF_TMSIZE_T_MAX - dircount * 12 - (tmsize_t)sizeof(uint32_t))
+            {
+                TIFFErrorExtR(tif, module, "Error fetching directory link");
+                return (0);
+            }
             poffc = poffb + dircount * 12;
-            poffd = poffc + sizeof(uint32_t);
-            if ((poffc < poffb) || (poffc < dircount * 12) || (poffd < poffc) ||
-                (poffd < (tmsize_t)sizeof(uint32_t)) || (poffd > tif->tif_size))
+            poffd = poffc + (tmsize_t)sizeof(uint32_t);
+            if (poffd > tif->tif_size)
             {
                 TIFFErrorExtR(tif, module, "Error fetching directory link");
                 return (0);
@@ -1893,7 +1934,6 @@
         {
             tmsize_t poffa, poffb, poffc, poffd;
             uint64_t dircount64;
-            uint16_t dircount16;
             if (poff > (uint64_t)TIFF_TMSIZE_T_MAX - sizeof(uint64_t))
             {
                 TIFFErrorExtR(tif, module,
@@ -1902,7 +1942,7 @@
                 return (0);
             }
             poffa = (tmsize_t)poff;
-            poffb = poffa + sizeof(uint64_t);
+            poffb = poffa + (tmsize_t)sizeof(uint64_t);
             if (poffb > tif->tif_size)
             {
                 TIFFErrorExtR(tif, module,
@@ -1919,15 +1959,14 @@
                               "Sanity check on directory count failed");
                 return (0);
             }
-            dircount16 = (uint16_t)dircount64;
-            if (poffb > TIFF_TMSIZE_T_MAX - (tmsize_t)(dircount16 * 20) -
+            if (poffb > TIFF_TMSIZE_T_MAX - (tmsize_t)(dircount64 * 20) -
                             (tmsize_t)sizeof(uint64_t))
             {
                 TIFFErrorExtR(tif, module, "Error fetching directory link");
                 return (0);
             }
-            poffc = poffb + dircount16 * 20;
-            poffd = poffc + sizeof(uint64_t);
+            poffc = poffb + (tmsize_t)(dircount64 * 20);
+            poffd = poffc + (tmsize_t)sizeof(uint64_t);
             if (poffd > tif->tif_size)
             {
                 TIFFErrorExtR(tif, module, "Error fetching directory link");
@@ -1957,9 +1996,9 @@
             if (tif->tif_flags & TIFF_SWAB)
                 TIFFSwabShort(&dircount);
             if (off != NULL)
-                *off = TIFFSeekFile(tif, dircount * 12, SEEK_CUR);
+                *off = TIFFSeekFile(tif, dircount * 12U, SEEK_CUR);
             else
-                (void)TIFFSeekFile(tif, dircount * 12, SEEK_CUR);
+                (void)TIFFSeekFile(tif, dircount * 12U, SEEK_CUR);
             if (!ReadOK(tif, &nextdir32, sizeof(uint32_t)))
             {
                 TIFFErrorExtR(tif, module, "%s: Error fetching directory link",
@@ -1973,7 +2012,6 @@
         else
         {
             uint64_t dircount64;
-            uint16_t dircount16;
             if (!SeekOK(tif, *nextdiroff) ||
                 !ReadOK(tif, &dircount64, sizeof(uint64_t)))
             {
@@ -1991,11 +2029,10 @@
                               __FILE__, __LINE__, tif->tif_name);
                 return (0);
             }
-            dircount16 = (uint16_t)dircount64;
             if (off != NULL)
-                *off = TIFFSeekFile(tif, dircount16 * 20, SEEK_CUR);
+                *off = TIFFSeekFile(tif, dircount64 * 20, SEEK_CUR);
             else
-                (void)TIFFSeekFile(tif, dircount16 * 20, SEEK_CUR);
+                (void)TIFFSeekFile(tif, dircount64 * 20, SEEK_CUR);
             if (!ReadOK(tif, nextdiroff, sizeof(uint64_t)))
             {
                 TIFFErrorExtR(tif, module, "%s: Error fetching directory link",
@@ -2354,8 +2391,6 @@
     tif->tif_nextdiroff = 0; /* next write must be at end */
     tif->tif_lastdiroff = 0; /* will be updated on next link */
     tif->tif_curoff = 0;
-    tif->tif_row = (uint32_t)-1;
-    tif->tif_curstrip = (uint32_t)-1;
     tif->tif_curdir = TIFF_NON_EXISTENT_DIR_NUMBER;
     if (tif->tif_curdircount > 0)
         tif->tif_curdircount--;
diff --git a/third_party/libtiff/tif_dir.h b/third_party/libtiff/tif_dir.h
index 44270f7..aed9722 100644
--- a/third_party/libtiff/tif_dir.h
+++ b/third_party/libtiff/tif_dir.h
@@ -104,6 +104,16 @@
     uint16_t td_halftonehints[2];
     uint16_t td_extrasamples;
     uint16_t *td_sampleinfo;
+    /* strip support */
+    uint32_t td_row;             /* current scanline */
+    uint32_t td_curstrip;        /* current strip for read/write */
+    tmsize_t td_scanlinesize;    /* # of bytes in a scanline */
+#define NOSTRIP ((uint32_t)(-1)) /* undefined state */
+    /* tiling support */
+    uint32_t td_col;            /* current column (offset by row too) */
+    uint32_t td_curtile;        /* current tile for read/write */
+    tmsize_t td_tilesize;       /* # of bytes in a tile */
+#define NOTILE ((uint32_t)(-1)) /* undefined state */
     /* even though the name is misleading, td_stripsperimage is the number
      * of striles (=strips or tiles) per plane, and td_nstrips the total
      * number of striles */
@@ -164,6 +174,8 @@
                                     entries. */
 } TIFFDirectory;
 
+extern void _TIFFResetTifDirAndInitStrileCounters(TIFFDirectory *td);
+
 /*
  * Field flags used to indicate fields that have been set in a directory, and
  * to reference fields when manipulating a directory.
@@ -231,7 +243,7 @@
 
 #define FIELD_LAST (32 * FIELDSET_ITEMS - 1)
 
-#define BITn(n) (((uint32_t)1L) << ((n)&0x1f))
+#define BITn(n) (1U << ((n) & 0x1f))
 #define BITFIELDn(tif, n) ((tif)->tif_dir.td_fieldsset[(n) / 32])
 #define TIFFFieldSet(tif, field) (BITFIELDn(tif, field) & BITn(field))
 #define TIFFSetFieldBit(tif, field) (BITFIELDn(tif, field) |= BITn(field))
@@ -340,7 +352,7 @@
         unsigned short field_bit;        /* bit in fieldsset bit vector */
         unsigned char field_oktochange;  /* if true, can change while writing */
         unsigned char field_passcount;   /* if true, pass dir count on set */
-        char *field_name;                /* ASCII name */
+        const char *field_name;          /* ASCII name */
         TIFFFieldArray *field_subfields; /* if field points to child ifds, child
                                             ifd field definition array */
     };
diff --git a/third_party/libtiff/tif_dirinfo.c b/third_party/libtiff/tif_dirinfo.c
index c038497..9218661 100644
--- a/third_party/libtiff/tif_dirinfo.c
+++ b/third_party/libtiff/tif_dirinfo.c
@@ -40,17 +40,47 @@
  *       values accordingly.
  */
 
-/* const object should be initialized */
-#ifdef _MSC_VER
+/* Forward declarations - definition follows after field arrays.
+ * Note: In C, we can forward declare static const objects and define them
+ * later. In C++, we need extern for the declaration, then define without
+ * extern. Since these are only used within this file via pointers, we use a
+ * workaround that works in both C and C++: declare as extern here, define as
+ * static later, but actually we need a different approach for C++
+ * compatibility.
+ *
+ * For C/C++ compatibility, we define a simple struct that holds the pointer
+ * and initialize it after the arrays are defined.
+ */
+#ifdef __cplusplus
+/* C++ doesn't allow forward declaration of const objects, so we use extern */
+extern const TIFFFieldArray tiffFieldArray;
+extern const TIFFFieldArray exifFieldArray;
+extern const TIFFFieldArray gpsFieldArray;
+#else
+/* C allows forward declaration of const objects, but C++ doesn't.
+ * We disable the C++-compat warning for this section since these circular
+ * dependencies are unavoidable with static initialization. */
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wc++-compat"
+#elif defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wc++-compat"
+#elif defined(_MSC_VER)
 #pragma warning(push)
 #pragma warning(disable : 4132)
 #endif
 static const TIFFFieldArray tiffFieldArray;
 static const TIFFFieldArray exifFieldArray;
 static const TIFFFieldArray gpsFieldArray;
-#ifdef _MSC_VER
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic pop
+#elif defined(__clang__)
+#pragma clang diagnostic pop
+#elif defined(_MSC_VER)
 #pragma warning(pop)
 #endif
+#endif
 /*--: Rational2Double: --
  * The Rational2Double upgraded libtiff functionality allows the definition and
  * achievement of true double-precision accuracy for TIFF tags of RATIONAL type
@@ -152,9 +182,9 @@
     /*--: EXIFIFD and GPSIFD specified as TIFF_LONG by Aware-Systems and not TIFF_IFD8 as in original LibTiff. However, for IFD-like tags,
      * libtiff uses the data type TIFF_IFD8 in tiffFields[]-tag definition combined with a special handling procedure in order to write either
      * a 32-bit value and the TIFF_IFD type-id into ClassicTIFF files or a 64-bit value and the TIFF_IFD8 type-id into BigTIFF files. */
-    {TIFFTAG_EXIFIFD, 1, 1, TIFF_IFD8, 0, TIFF_SETGET_IFD8,  FIELD_CUSTOM, 1, 0, "EXIFIFDOffset", (TIFFFieldArray *)&exifFieldArray},
+    {TIFFTAG_EXIFIFD, 1, 1, TIFF_LONG8, 0, TIFF_SETGET_UINT64,  FIELD_CUSTOM, 1, 0, "EXIFIFDOffset", (TIFFFieldArray *)&exifFieldArray},
     {TIFFTAG_ICCPROFILE, -3, -3, TIFF_UNDEFINED, 0, TIFF_SETGET_C32_UINT8,  FIELD_CUSTOM, 1, 1, "ICC Profile", NULL},
-    {TIFFTAG_GPSIFD, 1, 1, TIFF_IFD8, 0, TIFF_SETGET_IFD8,  FIELD_CUSTOM, 1, 0, "GPSIFDOffset", (TIFFFieldArray *)&gpsFieldArray},
+    {TIFFTAG_GPSIFD, 1, 1, TIFF_LONG8, 0, TIFF_SETGET_UINT64,  FIELD_CUSTOM, 1, 0, "GPSIFDOffset", (TIFFFieldArray *)&gpsFieldArray},
     {TIFFTAG_FAXRECVPARAMS, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32,  FIELD_CUSTOM, TRUE, FALSE, "FaxRecvParams", NULL},
     {TIFFTAG_FAXSUBADDRESS, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII,  FIELD_CUSTOM, TRUE, FALSE, "FaxSubAddress", NULL},
     {TIFFTAG_FAXRECVTIME, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32,  FIELD_CUSTOM, TRUE, FALSE, "FaxRecvTime", NULL},
@@ -479,12 +509,36 @@
     {GPSTAG_GPSHPOSITIONINGERROR, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE,  FIELD_CUSTOM, 1, 0, "HorizontalPositioningError", NULL}};
 /* clang-format on */ /* was off for better readability of tag comments */
 
+#ifdef __cplusplus
+/* In C++, the forward declaration used extern, so definitions must not be
+ * static */
+const TIFFFieldArray tiffFieldArray = {
+    tfiatImage, 0, TIFFArrayCount(tiffFields), (TIFFField *)tiffFields};
+const TIFFFieldArray exifFieldArray = {tfiatExif, 0, TIFFArrayCount(exifFields),
+                                       (TIFFField *)exifFields};
+const TIFFFieldArray gpsFieldArray = {tfiatGps, 0, TIFFArrayCount(gpsFields),
+                                      (TIFFField *)gpsFields};
+#else
+/* Suppress C++-compat warning for the definitions as well */
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wc++-compat"
+#elif defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wc++-compat"
+#endif
 static const TIFFFieldArray tiffFieldArray = {
     tfiatImage, 0, TIFFArrayCount(tiffFields), (TIFFField *)tiffFields};
 static const TIFFFieldArray exifFieldArray = {
     tfiatExif, 0, TIFFArrayCount(exifFields), (TIFFField *)exifFields};
 static const TIFFFieldArray gpsFieldArray = {
     tfiatGps, 0, TIFFArrayCount(gpsFields), (TIFFField *)gpsFields};
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic pop
+#elif defined(__clang__)
+#pragma clang diagnostic pop
+#endif
+#endif
 
 /*
  *  We have our own local lfind() equivalent to avoid subtle differences
@@ -523,7 +577,7 @@
             {
                 if (fld->field_bit == FIELD_CUSTOM && TIFFFieldIsAnonymous(fld))
                 {
-                    _TIFFfreeExt(tif, fld->field_name);
+                    _TIFFfreeExt(tif, (void *)fld->field_name);
                     /* caution: tif_fields[i] must not be the beginning of a
                      * fields-array. Otherwise the following tags are also freed
                      * with the first free().
@@ -579,22 +633,26 @@
 
     tif->tif_foundfield = NULL;
 
+    TIFFField **tif_newfields = NULL;
+
     if (tif->tif_fields && tif->tif_nfields > 0)
     {
-        tif->tif_fields = (TIFFField **)_TIFFCheckRealloc(
-            tif, tif->tif_fields, (tif->tif_nfields + n), sizeof(TIFFField *),
-            reason);
+        tif_newfields = (TIFFField **)_TIFFCheckRealloc(
+            tif, tif->tif_fields, (tmsize_t)tif->tif_nfields + n,
+            (tmsize_t)sizeof(TIFFField *), reason);
     }
     else
     {
-        tif->tif_fields =
+        tif_newfields =
             (TIFFField **)_TIFFCheckMalloc(tif, n, sizeof(TIFFField *), reason);
     }
-    if (!tif->tif_fields)
+    if (!tif_newfields)
     {
+        tif->tif_nfields = 0;
         TIFFErrorExtR(tif, module, "Failed to allocate fields array");
         return 0;
     }
+    tif->tif_fields = tif_newfields;
 
     /* tp = tif->tif_fields + tif->tif_nfields; */
     for (i = 0; i < n; i++)
@@ -612,7 +670,7 @@
     /* Sort the field info by tag number */
     qsort(tif->tif_fields, tif->tif_nfields, sizeof(TIFFField *), tagCompare);
 
-    return n;
+    return (int)n;
 }
 
 void _TIFFPrintFieldInfo(TIFF *tif, FILE *fd)
@@ -623,7 +681,7 @@
     for (i = 0; i < tif->tif_nfields; i++)
     {
         const TIFFField *fip = tif->tif_fields[i];
-        fprintf(fd, "field[%2d] %5lu, %2d, %2d, %d, %2d, %5s, %5s, %s\n",
+        fprintf(fd, "field[%2d] %5lu, %2d, %2d, %u, %2d, %5s, %5s, %s\n",
                 (int)i, (unsigned long)fip->field_tag, fip->field_readcount,
                 fip->field_writecount, fip->field_type, fip->field_bit,
                 fip->field_oktochange ? "TRUE" : "FALSE",
@@ -787,6 +845,34 @@
         case TIFF_SETGET_C32_DOUBLE:
         case TIFF_SETGET_C32_IFD8:
             return 4;
+        case TIFF_SETGET_UNDEFINED:
+        case TIFF_SETGET_ASCII:
+        case TIFF_SETGET_UINT8:
+        case TIFF_SETGET_SINT8:
+        case TIFF_SETGET_UINT16:
+        case TIFF_SETGET_SINT16:
+        case TIFF_SETGET_UINT32:
+        case TIFF_SETGET_SINT32:
+        case TIFF_SETGET_UINT64:
+        case TIFF_SETGET_SINT64:
+        case TIFF_SETGET_FLOAT:
+        case TIFF_SETGET_DOUBLE:
+        case TIFF_SETGET_IFD8:
+        case TIFF_SETGET_INT:
+        case TIFF_SETGET_UINT16_PAIR:
+        case TIFF_SETGET_C0_ASCII:
+        case TIFF_SETGET_C0_UINT8:
+        case TIFF_SETGET_C0_SINT8:
+        case TIFF_SETGET_C0_UINT16:
+        case TIFF_SETGET_C0_SINT16:
+        case TIFF_SETGET_C0_UINT32:
+        case TIFF_SETGET_C0_SINT32:
+        case TIFF_SETGET_C0_UINT64:
+        case TIFF_SETGET_C0_SINT64:
+        case TIFF_SETGET_C0_FLOAT:
+        case TIFF_SETGET_C0_DOUBLE:
+        case TIFF_SETGET_C0_IFD8:
+        case TIFF_SETGET_OTHER:
         default:
             return 0;
     }
@@ -794,7 +880,8 @@
 
 const TIFFField *TIFFFindField(TIFF *tif, uint32_t tag, TIFFDataType dt)
 {
-    TIFFField key = {0, 0, 0, TIFF_NOTYPE, 0, 0, 0, 0, 0, NULL, NULL};
+    TIFFField key = {0, 0, 0, TIFF_NOTYPE, 0,   TIFF_SETGET_UNDEFINED,
+                     0, 0, 0, NULL,        NULL};
     TIFFField *pkey = &key;
     const TIFFField **ret;
     if (tif->tif_foundfield && tif->tif_foundfield->field_tag == tag &&
@@ -818,7 +905,8 @@
 static const TIFFField *_TIFFFindFieldByName(TIFF *tif, const char *field_name,
                                              TIFFDataType dt)
 {
-    TIFFField key = {0, 0, 0, TIFF_NOTYPE, 0, 0, 0, 0, 0, NULL, NULL};
+    TIFFField key = {0, 0, 0, TIFF_NOTYPE, 0,   TIFF_SETGET_UNDEFINED,
+                     0, 0, 0, NULL,        NULL};
     TIFFField *pkey = &key;
     const TIFFField **ret;
     if (tif->tif_foundfield &&
@@ -876,7 +964,10 @@
 
 int TIFFFieldWriteCount(const TIFFField *fip) { return fip->field_writecount; }
 
-int TIFFFieldIsAnonymous(const TIFFField *fip) { return fip->field_anonymous; }
+int TIFFFieldIsAnonymous(const TIFFField *fip)
+{
+    return (int)fip->field_anonymous;
+}
 
 const TIFFField *_TIFFFindOrRegisterField(TIFF *tif, uint32_t tag,
                                           TIFFDataType dt)
@@ -954,6 +1045,7 @@
         case TIFF_SLONG8:
             fld->set_get_field_type = TIFF_SETGET_C32_SINT64;
             break;
+        case TIFF_NOTYPE:
         default:
             fld->set_get_field_type = TIFF_SETGET_UNDEFINED;
             break;
@@ -961,8 +1053,8 @@
     fld->field_bit = FIELD_CUSTOM;
     fld->field_oktochange = TRUE;
     fld->field_passcount = TRUE;
-    fld->field_name = (char *)_TIFFmallocExt(tif, 32);
-    if (fld->field_name == NULL)
+    char *field_name_buf = (char *)_TIFFmallocExt(tif, 32);
+    if (field_name_buf == NULL)
     {
         _TIFFfreeExt(tif, fld);
         return NULL;
@@ -975,7 +1067,8 @@
      * Update:
      *   This special sign is replaced by fld->field_anonymous  flag.
      */
-    (void)snprintf(fld->field_name, 32, "Tag %d", (int)tag);
+    (void)snprintf(field_name_buf, 32, "Tag %d", (int)tag);
+    fld->field_name = field_name_buf;
 
     return fld;
 }
@@ -1025,6 +1118,7 @@
                 return TIFF_SETGET_UINT64;
             case TIFF_SLONG8:
                 return TIFF_SETGET_SINT64;
+            case TIFF_NOTYPE:
             default:
                 return TIFF_SETGET_UNDEFINED;
         }
@@ -1062,6 +1156,7 @@
                 return TIFF_SETGET_C0_UINT64;
             case TIFF_SLONG8:
                 return TIFF_SETGET_C0_SINT64;
+            case TIFF_NOTYPE:
             default:
                 return TIFF_SETGET_UNDEFINED;
         }
@@ -1099,6 +1194,7 @@
                 return TIFF_SETGET_C16_UINT64;
             case TIFF_SLONG8:
                 return TIFF_SETGET_C16_SINT64;
+            case TIFF_NOTYPE:
             default:
                 return TIFF_SETGET_UNDEFINED;
         }
@@ -1136,6 +1232,7 @@
                 return TIFF_SETGET_C32_UINT64;
             case TIFF_SLONG8:
                 return TIFF_SETGET_C32_SINT64;
+            case TIFF_NOTYPE:
             default:
                 return TIFF_SETGET_UNDEFINED;
         }
@@ -1152,22 +1249,25 @@
     size_t nfields;
     uint32_t i;
 
+    TIFFFieldArray *tif_newfieldscompat = NULL;
+
     if (tif->tif_nfieldscompat > 0)
     {
-        tif->tif_fieldscompat = (TIFFFieldArray *)_TIFFCheckRealloc(
-            tif, tif->tif_fieldscompat, tif->tif_nfieldscompat + 1,
-            sizeof(TIFFFieldArray), reason);
+        tif_newfieldscompat = (TIFFFieldArray *)_TIFFCheckRealloc(
+            tif, tif->tif_fieldscompat, (tmsize_t)tif->tif_nfieldscompat + 1,
+            (tmsize_t)sizeof(TIFFFieldArray), reason);
     }
     else
     {
-        tif->tif_fieldscompat = (TIFFFieldArray *)_TIFFCheckMalloc(
+        tif_newfieldscompat = (TIFFFieldArray *)_TIFFCheckMalloc(
             tif, 1, sizeof(TIFFFieldArray), reason);
     }
-    if (!tif->tif_fieldscompat)
+    if (!tif_newfieldscompat)
     {
         TIFFErrorExtR(tif, module, "Failed to allocate fields array");
         return -1;
     }
+    tif->tif_fieldscompat = tif_newfieldscompat;
     nfields = tif->tif_nfieldscompat++;
 
     tif->tif_fieldscompat[nfields].type = tfiatOther;
@@ -1309,6 +1409,8 @@
                 case TIFFTAG_JPEGPROC:
                 case TIFFTAG_JPEGRESTARTINTERVAL:
                     return 1;
+                default:
+                    break;
             }
             break;
         case COMPRESSION_CCITTRLE:
@@ -1329,6 +1431,8 @@
                     if (tif->tif_dir.td_compression == COMPRESSION_CCITTFAX4)
                         return 1;
                     break;
+                default:
+                    break;
             }
             break;
         case COMPRESSION_JBIG:
@@ -1359,6 +1463,8 @@
             if (tag == TIFFTAG_LERC_PARAMETERS)
                 return 1;
             break;
+        default:
+            break;
     }
     return 0;
 }
diff --git a/third_party/libtiff/tif_dirread.c b/third_party/libtiff/tif_dirread.c
index 88e1bc6..3df651e 100644
--- a/third_party/libtiff/tif_dirread.c
+++ b/third_party/libtiff/tif_dirread.c
@@ -597,7 +597,7 @@
             err = TIFFReadDirEntryCheckRangeSshortShort(m);
             if (err != TIFFReadDirEntryErrOk)
                 return (err);
-            *value = (uint16_t)m;
+            *value = (int16_t)m;
             return (TIFFReadDirEntryErrOk);
         }
         case TIFF_SSHORT:
@@ -695,6 +695,7 @@
             return (TIFFReadDirEntryErrOk);
         }
         case TIFF_LONG:
+        case TIFF_IFD:
             TIFFReadDirEntryCheckedLong(tif, direntry, value);
             return (TIFFReadDirEntryErrOk);
         case TIFF_SLONG:
@@ -708,6 +709,7 @@
             return (TIFFReadDirEntryErrOk);
         }
         case TIFF_LONG8:
+        case TIFF_IFD8:
         {
             uint64_t m;
             err = TIFFReadDirEntryCheckedLong8(tif, direntry, &m);
@@ -857,6 +859,7 @@
             return (TIFFReadDirEntryErrOk);
         }
         case TIFF_LONG:
+        case TIFF_IFD:
         {
             uint32_t m;
             TIFFReadDirEntryCheckedLong(tif, direntry, &m);
@@ -874,6 +877,7 @@
             return (TIFFReadDirEntryErrOk);
         }
         case TIFF_LONG8:
+        case TIFF_IFD8:
             err = TIFFReadDirEntryCheckedLong8(tif, direntry, value);
             return (err);
         case TIFF_SLONG8:
@@ -1058,7 +1062,7 @@
             err = TIFFReadDirEntryCheckedDouble(tif, direntry, &m);
             if (err != TIFFReadDirEntryErrOk)
                 return (err);
-            if ((m > FLT_MAX) || (m < -FLT_MAX))
+            if ((m > (double)FLT_MAX) || (m < -(double)FLT_MAX))
                 return (TIFFReadDirEntryErrRange);
             *value = (float)m;
             return (TIFFReadDirEntryErrOk);
@@ -1237,6 +1241,8 @@
         *pdest = new_dest;
 
         bytes_read = TIFFReadFile(tif, (char *)*pdest + already_read, to_read);
+        if (bytes_read < 0)
+            return TIFFReadDirEntryErrIo;
         already_read += bytes_read;
         if (bytes_read != to_read)
         {
@@ -1260,7 +1266,7 @@
     void *data;
     uint64_t target_count64;
     int original_datasize_clamped;
-    typesize = TIFFDataWidth(direntry->tdir_type);
+    typesize = TIFFDataWidth((TIFFDataType)direntry->tdir_type);
 
     target_count64 =
         (direntry->tdir_count > maxcount) ? maxcount : direntry->tdir_count;
@@ -1284,13 +1290,13 @@
      * in either the current data type or the dest data type.  This also
      * avoids problems with overflow of tmsize_t on 32bit systems.
      */
-    if ((uint64_t)(MAX_SIZE_TAG_DATA / typesize) < target_count64)
+    if ((uint64_t)(MAX_SIZE_TAG_DATA / (unsigned int)typesize) < target_count64)
         return (TIFFReadDirEntryErrSizesan);
     if ((uint64_t)(MAX_SIZE_TAG_DATA / desttypesize) < target_count64)
         return (TIFFReadDirEntryErrSizesan);
 
     *count = (uint32_t)target_count64;
-    datasize = (*count) * typesize;
+    datasize = (uint32_t)(*count) * (unsigned int)typesize;
     assert((tmsize_t)datasize > 0);
 
     if (datasize > 100 * 1024 * 1024)
@@ -1440,6 +1446,8 @@
             *value = (uint8_t *)origdata;
             return (TIFFReadDirEntryErrOk);
         }
+        default:
+            break;
     }
     data = (uint8_t *)_TIFFmallocExt(tif, count);
     if (data == 0)
@@ -1557,6 +1565,8 @@
             }
         }
         break;
+        default:
+            break;
     }
     _TIFFfreeExt(tif, origdata);
     if (err != TIFFReadDirEntryErrOk)
@@ -1620,6 +1630,8 @@
         case TIFF_SBYTE:
             *value = (int8_t *)origdata;
             return (TIFFReadDirEntryErrOk);
+        default:
+            break;
     }
     data = (int8_t *)_TIFFmallocExt(tif, count);
     if (data == 0)
@@ -1737,6 +1749,8 @@
             }
         }
         break;
+        default:
+            break;
     }
     _TIFFfreeExt(tif, origdata);
     if (err != TIFFReadDirEntryErrOk)
@@ -1802,6 +1816,8 @@
             *value = (uint16_t *)origdata;
             return (TIFFReadDirEntryErrOk);
         }
+        default:
+            break;
     }
     data = (uint16_t *)_TIFFmallocExt(tif, count * 2);
     if (data == 0)
@@ -1910,6 +1926,8 @@
             }
         }
         break;
+        default:
+            break;
     }
     _TIFFfreeExt(tif, origdata);
     if (err != TIFFReadDirEntryErrOk)
@@ -1975,6 +1993,8 @@
             if (tif->tif_flags & TIFF_SWAB)
                 TIFFSwabArrayOfShort((uint16_t *)(*value), count);
             return (TIFFReadDirEntryErrOk);
+        default:
+            break;
     }
     data = (int16_t *)_TIFFmallocExt(tif, count * 2);
     if (data == 0)
@@ -2078,6 +2098,8 @@
             }
         }
         break;
+        default:
+            break;
     }
     _TIFFfreeExt(tif, origdata);
     if (err != TIFFReadDirEntryErrOk)
@@ -2106,6 +2128,8 @@
         case TIFF_SLONG:
         case TIFF_LONG8:
         case TIFF_SLONG8:
+        case TIFF_IFD:
+        case TIFF_IFD8:
             break;
         default:
             return (TIFFReadDirEntryErrType);
@@ -2119,6 +2143,7 @@
     switch (direntry->tdir_type)
     {
         case TIFF_LONG:
+        case TIFF_IFD:
             *value = (uint32_t *)origdata;
             if (tif->tif_flags & TIFF_SWAB)
                 TIFFSwabArrayOfLong(*value, count);
@@ -2143,6 +2168,8 @@
             *value = (uint32_t *)origdata;
             return (TIFFReadDirEntryErrOk);
         }
+        default:
+            break;
     }
     data = (uint32_t *)_TIFFmallocExt(tif, count * 4);
     if (data == 0)
@@ -2213,6 +2240,7 @@
         }
         break;
         case TIFF_LONG8:
+        case TIFF_IFD8:
         {
             uint64_t *ma;
             uint32_t *mb;
@@ -2248,6 +2276,8 @@
             }
         }
         break;
+        default:
+            break;
     }
     _TIFFfreeExt(tif, origdata);
     if (err != TIFFReadDirEntryErrOk)
@@ -2313,6 +2343,8 @@
             if (tif->tif_flags & TIFF_SWAB)
                 TIFFSwabArrayOfLong((uint32_t *)(*value), count);
             return (TIFFReadDirEntryErrOk);
+        default:
+            break;
     }
     data = (int32_t *)_TIFFmallocExt(tif, count * 4);
     if (data == 0)
@@ -2410,6 +2442,8 @@
             }
         }
         break;
+        default:
+            break;
     }
     _TIFFfreeExt(tif, origdata);
     if (err != TIFFReadDirEntryErrOk)
@@ -2439,6 +2473,8 @@
         case TIFF_SLONG:
         case TIFF_LONG8:
         case TIFF_SLONG8:
+        case TIFF_IFD:
+        case TIFF_IFD8:
             break;
         default:
             return (TIFFReadDirEntryErrType);
@@ -2453,6 +2489,7 @@
     switch (direntry->tdir_type)
     {
         case TIFF_LONG8:
+        case TIFF_IFD8:
             *value = (uint64_t *)origdata;
             if (tif->tif_flags & TIFF_SWAB)
                 TIFFSwabArrayOfLong8(*value, count);
@@ -2477,6 +2514,8 @@
             *value = (uint64_t *)origdata;
             return (TIFFReadDirEntryErrOk);
         }
+        default:
+            break;
     }
     data = (uint64_t *)_TIFFmallocExt(tif, count * 8);
     if (data == 0)
@@ -2547,6 +2586,7 @@
         }
         break;
         case TIFF_LONG:
+        case TIFF_IFD:
         {
             uint32_t *ma;
             uint64_t *mb;
@@ -2579,6 +2619,8 @@
             }
         }
         break;
+        default:
+            break;
     }
     _TIFFfreeExt(tif, origdata);
     if (err != TIFFReadDirEntryErrOk)
@@ -2651,6 +2693,8 @@
             if (tif->tif_flags & TIFF_SWAB)
                 TIFFSwabArrayOfLong8((uint64_t *)(*value), count);
             return (TIFFReadDirEntryErrOk);
+        default:
+            break;
     }
     data = (int64_t *)_TIFFmallocExt(tif, count * 8);
     if (data == 0)
@@ -2742,6 +2786,8 @@
             }
         }
         break;
+        default:
+            break;
     }
     _TIFFfreeExt(tif, origdata);
     *value = data;
@@ -2787,8 +2833,11 @@
             TIFFCvtIEEEFloatToNative(tif, count, (float *)origdata);
             *value = (float *)origdata;
             return (TIFFReadDirEntryErrOk);
+        default:
+            break;
     }
-    data = (float *)_TIFFmallocExt(tif, count * sizeof(float));
+    data =
+        (float *)_TIFFmallocExt(tif, (tmsize_t)((size_t)count * sizeof(float)));
     if (data == 0)
     {
         _TIFFfreeExt(tif, origdata);
@@ -2970,14 +3019,16 @@
             for (n = 0; n < count; n++)
             {
                 double val = *ma++;
-                if (val > FLT_MAX)
-                    val = FLT_MAX;
-                else if (val < -FLT_MAX)
-                    val = -FLT_MAX;
+                if (val > (double)FLT_MAX)
+                    val = (double)FLT_MAX;
+                else if (val < -(double)FLT_MAX)
+                    val = -(double)FLT_MAX;
                 *mb++ = (float)val;
             }
         }
         break;
+        default:
+            break;
     }
     _TIFFfreeExt(tif, origdata);
     *value = data;
@@ -3023,8 +3074,11 @@
             TIFFCvtIEEEDoubleToNative(tif, count, (double *)origdata);
             *value = (double *)origdata;
             return (TIFFReadDirEntryErrOk);
+        default:
+            break;
     }
-    data = (double *)_TIFFmallocExt(tif, count * sizeof(double));
+    data = (double *)_TIFFmallocExt(tif,
+                                    (tmsize_t)((size_t)count * sizeof(double)));
     if (data == 0)
     {
         _TIFFfreeExt(tif, origdata);
@@ -3207,6 +3261,8 @@
                 *mb++ = (double)(*ma++);
         }
         break;
+        default:
+            break;
     }
     _TIFFfreeExt(tif, origdata);
     *value = data;
@@ -3244,6 +3300,8 @@
             if (tif->tif_flags & TIFF_SWAB)
                 TIFFSwabArrayOfLong8(*value, count);
             return (TIFFReadDirEntryErrOk);
+        default:
+            break;
     }
     data = (uint64_t *)_TIFFmallocExt(tif, count * 8);
     if (data == 0)
@@ -3269,6 +3327,8 @@
             }
         }
         break;
+        default:
+            break;
     }
     _TIFFfreeExt(tif, origdata);
     *value = data;
@@ -3283,13 +3343,42 @@
     uint16_t *m;
     uint16_t *na;
     uint16_t nb;
-    if (direntry->tdir_count < (uint64_t)tif->tif_dir.td_samplesperpixel)
-        return (TIFFReadDirEntryErrCount);
+    if (direntry->tdir_count != (uint64_t)tif->tif_dir.td_samplesperpixel)
+    {
+        const TIFFField *fip = TIFFFieldWithTag(tif, direntry->tdir_tag);
+        if (direntry->tdir_count == 0)
+        {
+            return TIFFReadDirEntryErrCount;
+        }
+        else if (direntry->tdir_count <
+                 (uint64_t)tif->tif_dir.td_samplesperpixel)
+        {
+            TIFFWarningExtR(
+                tif, "TIFFReadDirEntryPersampleShort",
+                "Tag %s entry count is %" PRIu64
+                " , whereas it should be SamplesPerPixel=%d. Assuming that "
+                "missing entries are all at the value of the first one",
+                fip ? fip->field_name : "unknown tagname", direntry->tdir_count,
+                tif->tif_dir.td_samplesperpixel);
+        }
+        else
+        {
+            TIFFWarningExtR(tif, "TIFFReadDirEntryPersampleShort",
+                            "Tag %s entry count is %" PRIu64
+                            " , whereas it should be SamplesPerPixel=%d. "
+                            "Ignoring extra entries",
+                            fip ? fip->field_name : "unknown tagname",
+                            direntry->tdir_count,
+                            tif->tif_dir.td_samplesperpixel);
+        }
+    }
     err = TIFFReadDirEntryShortArray(tif, direntry, &m);
     if (err != TIFFReadDirEntryErrOk || m == NULL)
         return (err);
     na = m;
     nb = tif->tif_dir.td_samplesperpixel;
+    if (direntry->tdir_count < nb)
+        nb = (uint16_t)direntry->tdir_count;
     *value = *na++;
     nb--;
     while (nb > 0)
@@ -3908,7 +3997,7 @@
         {
             return TIFFReadDirEntryErrIo;
         }
-        mb = ma + size;
+        mb = (uint64_t)ma + (uint64_t)size;
         if (mb > (uint64_t)tif->tif_size)
             return (TIFFReadDirEntryErrIo);
         _TIFFmemcpy(dest, tif->tif_base + ma, size);
@@ -3955,6 +4044,7 @@
                 TIFFErrorExtR(tif, module, "Out of memory reading of \"%s\"",
                               tagname);
                 break;
+            case TIFFReadDirEntryErrOk:
             default:
                 assert(0); /* we should never get here */
                 break;
@@ -4001,6 +4091,7 @@
                                 "Out of memory reading of \"%s\"; tag ignored",
                                 tagname);
                 break;
+            case TIFFReadDirEntryErrOk:
             default:
                 assert(0); /* we should never get here */
                 break;
@@ -4086,7 +4177,8 @@
  */
 static bool EvaluateIFDdatasizeReading(TIFF *tif, TIFFDirEntry *dp)
 {
-    const uint64_t data_width = TIFFDataWidth(dp->tdir_type);
+    const uint64_t data_width =
+        (uint64_t)TIFFDataWidth((TIFFDataType)dp->tdir_type);
     if (data_width != 0 && dp->tdir_count > UINT64_MAX / data_width)
     {
         TIFFErrorExtR(tif, "EvaluateIFDdatasizeReading",
@@ -4173,9 +4265,9 @@
     /* Get offset of end of IFD entry space. */
     uint64_t IFDendoffset;
     if (!(tif->tif_flags & TIFF_BIGTIFF))
-        IFDendoffset = tif->tif_diroff + 2 + dircount * 12 + 4;
+        IFDendoffset = tif->tif_diroff + 2 + (uint64_t)dircount * 12 + 4;
     else
-        IFDendoffset = tif->tif_diroff + 8 + dircount * 20 + 8;
+        IFDendoffset = tif->tif_diroff + 8 + (uint64_t)dircount * 20 + 8;
 
     /* Check which offsets are right behind IFD entries. However, LibTIFF
      * increments the writing address for every external data to an even offset.
@@ -4224,9 +4316,9 @@
 
     /* Finally, add the size of the IFD tag entries themselves. */
     if (!(tif->tif_flags & TIFF_BIGTIFF))
-        tif->tif_dir.td_dirdatasize_read = 2 + dircount * 12 + 4 + size;
+        tif->tif_dir.td_dirdatasize_read = 2U + dircount * 12U + 4U + size;
     else
-        tif->tif_dir.td_dirdatasize_read = 8 + dircount * 20 + 8 + size;
+        tif->tif_dir.td_dirdatasize_read = 8U + dircount * 20U + 8U + size;
 } /*-- CalcFinalIFDdatasizeReading() --*/
 
 /*
@@ -4298,7 +4390,8 @@
         {
             TIFFDirEntry *na;
             uint16_t nb;
-            for (na = ma + 1, nb = mb + 1; nb < dircount; na++, nb++)
+            for (na = ma + 1, nb = (uint16_t)(mb + 1); nb < dircount;
+                 na++, nb++)
             {
                 if (ma->tdir_tag == na->tdir_tag)
                 {
@@ -4312,7 +4405,15 @@
     tif->tif_flags &= ~TIFF_BUF4WRITE;   /* reset before new dir */
     tif->tif_flags &= ~TIFF_CHOPPEDUPARRAYS;
 
-    /* free any old stuff and reinit */
+    /* When changing directory, in deferred strile loading mode, we must also
+     * unset the TIFF_LAZYSTRILELOAD_DONE bit if it was initially set,
+     * to make sure the strile offset/bytecount are read again (when they fit
+     * in the tag data area).
+     */
+    tif->tif_flags &= ~TIFF_LAZYSTRILELOAD_DONE;
+
+    /* Free any old stuff and reinit i/o and other parameters within
+     * TIFFDefaultDirectory() since we are starting on a new directory. */
     TIFFFreeDirectory(tif);
     TIFFDefaultDirectory(tif);
 
@@ -4325,7 +4426,8 @@
      * checking. Note: Counter are reset within TIFFFreeDirectory(). */
     tif->tif_dir.td_dirdatasize_offsets =
         (TIFFEntryOffsetAndLength *)_TIFFmallocExt(
-            tif, dircount * sizeof(TIFFEntryOffsetAndLength));
+            tif,
+            (tmsize_t)((size_t)dircount * sizeof(TIFFEntryOffsetAndLength)));
     if (tif->tif_dir.td_dirdatasize_offsets == NULL)
     {
         TIFFErrorExtR(
@@ -4788,8 +4890,8 @@
                     (void)TIFFFetchNormalTag(tif, dp, TRUE);
                     break;
             } /* -- switch (dp->tdir_tag) -- */
-        }     /* -- if (!dp->tdir_ignore) */
-    }         /* -- for-loop -- */
+        } /* -- if (!dp->tdir_ignore) */
+    } /* -- for-loop -- */
 
     /* Evaluate final IFD data size. */
     CalcFinalIFDdatasizeReading(tif, dircount);
@@ -5106,7 +5208,7 @@
             tif->tif_dir.td_maxsamplevalue = 0xFFFF;
         else
             tif->tif_dir.td_maxsamplevalue =
-                (uint16_t)((1L << tif->tif_dir.td_bitspersample) - 1);
+                (uint16_t)((1 << tif->tif_dir.td_bitspersample) - 1);
     }
 
 #ifdef STRIPBYTECOUNTSORTED_UNUSED
@@ -5172,16 +5274,10 @@
     tif->tif_flags &= ~TIFF_DIRTYSTRIP;
 
     /*
-     * Reinitialize i/o since we are starting on a new directory.
+     * Reinitialize some further i/o since we are starting on a new directory.
      */
-    tif->tif_row = (uint32_t)-1;
-    tif->tif_curstrip = (uint32_t)-1;
-    tif->tif_col = (uint32_t)-1;
-    tif->tif_curtile = (uint32_t)-1;
-    tif->tif_tilesize = (tmsize_t)-1;
-
-    tif->tif_scanlinesize = TIFFScanlineSize(tif);
-    if (!tif->tif_scanlinesize)
+    tif->tif_dir.td_scanlinesize = TIFFScanlineSize(tif);
+    if (!tif->tif_dir.td_scanlinesize)
     {
         TIFFErrorExtR(tif, module, "Cannot handle zero scanline size");
         return (0);
@@ -5189,8 +5285,8 @@
 
     if (isTiled(tif))
     {
-        tif->tif_tilesize = TIFFTileSize(tif);
-        if (!tif->tif_tilesize)
+        tif->tif_dir.td_tilesize = TIFFTileSize(tif);
+        if (!tif->tif_dir.td_tilesize)
         {
             TIFFErrorExtR(tif, module, "Cannot handle zero tile size");
             return (0);
@@ -5228,7 +5324,7 @@
                             "ascending order");
             break;
         }
-        m = o->tdir_tag + 1;
+        m = o->tdir_tag + 1U;
     }
 }
 
@@ -5276,7 +5372,7 @@
             break;
         mb--;
     }
-    *fii = mb;
+    *fii = (uint32_t)mb;
 }
 
 /*
@@ -5316,7 +5412,8 @@
         {
             TIFFDirEntry *na;
             uint16_t nb;
-            for (na = ma + 1, nb = mb + 1; nb < dircount; na++, nb++)
+            for (na = ma + 1, nb = (uint16_t)(mb + 1); nb < dircount;
+                 na++, nb++)
             {
                 if (ma->tdir_tag == na->tdir_tag)
                 {
@@ -5341,7 +5438,8 @@
      * checking. Note: Counter are reset within TIFFFreeDirectory(). */
     tif->tif_dir.td_dirdatasize_offsets =
         (TIFFEntryOffsetAndLength *)_TIFFmallocExt(
-            tif, dircount * sizeof(TIFFEntryOffsetAndLength));
+            tif,
+            (tmsize_t)((size_t)dircount * sizeof(TIFFEntryOffsetAndLength)));
     if (tif->tif_dir.td_dirdatasize_offsets == NULL)
     {
         TIFFErrorExtR(
@@ -5523,15 +5621,17 @@
         uint64_t space;
         uint16_t n;
         if (!(tif->tif_flags & TIFF_BIGTIFF))
-            space = sizeof(TIFFHeaderClassic) + 2 + dircount * 12 + 4;
+            space = sizeof(TIFFHeaderClassic) + 2 +
+                    (unsigned long)dircount * 12 + 4;
         else
-            space = sizeof(TIFFHeaderBig) + 8 + dircount * 20 + 8;
+            space =
+                sizeof(TIFFHeaderBig) + 8 + (unsigned long)dircount * 20 + 8;
         /* calculate amount of space used by indirect values */
         for (dp = dir, n = dircount; n > 0; n--, dp++)
         {
             uint32_t typewidth;
             uint64_t datasize;
-            typewidth = TIFFDataWidth((TIFFDataType)dp->tdir_type);
+            typewidth = (uint32_t)TIFFDataWidth((TIFFDataType)dp->tdir_type);
             if (typewidth == 0)
             {
                 TIFFErrorExtR(
@@ -5794,7 +5894,7 @@
     {
         TIFFErrorExtR(tif, "_TIFFCheckDirNumberAndOffset",
                       "Cannot handle more than %u TIFF directories",
-                      TIFF_MAX_DIR_COUNT);
+                      (unsigned)TIFF_MAX_DIR_COUNT);
         return 0;
     }
 
@@ -6056,7 +6156,7 @@
                                    "to read TIFF directory");
         if (origdir == NULL)
             return 0;
-        if (!ReadOK(tif, origdir, (tmsize_t)(dircount16 * dirsize)))
+        if (!ReadOK(tif, origdir, (tmsize_t)dircount16 * dirsize))
         {
             TIFFErrorExtR(tif, module, "%.100s: Can not read TIFF directory",
                           tif->tif_name);
@@ -6109,9 +6209,9 @@
          */
         if (!(tif->tif_flags & TIFF_BIGTIFF))
         {
-            m = off + sizeof(uint16_t);
-            if ((m < off) || (m < (tmsize_t)sizeof(uint16_t)) ||
-                (m > tif->tif_size))
+            m = (tmsize_t)((uint64_t)off + sizeof(uint16_t));
+            if ((m < off) || ((uint64_t)m < sizeof(uint16_t)) ||
+                ((uint64_t)m > (uint64_t)tif->tif_size))
             {
                 TIFFErrorExtR(tif, module, "Can not read TIFF directory count");
                 return 0;
@@ -6120,7 +6220,7 @@
             {
                 _TIFFmemcpy(&dircount16, tif->tif_base + off, sizeof(uint16_t));
             }
-            off += sizeof(uint16_t);
+            off = (tmsize_t)((uint64_t)off + sizeof(uint16_t));
             if (tif->tif_flags & TIFF_SWAB)
                 TIFFSwabShort(&dircount16);
             if (dircount16 > 4096)
@@ -6135,9 +6235,9 @@
         else
         {
             uint64_t dircount64;
-            m = off + sizeof(uint64_t);
-            if ((m < off) || (m < (tmsize_t)sizeof(uint64_t)) ||
-                (m > tif->tif_size))
+            m = (tmsize_t)((uint64_t)off + sizeof(uint64_t));
+            if ((m < off) || ((uint64_t)m < sizeof(uint64_t)) ||
+                ((uint64_t)m > (uint64_t)tif->tif_size))
             {
                 TIFFErrorExtR(tif, module, "Can not read TIFF directory count");
                 return 0;
@@ -6146,7 +6246,7 @@
             {
                 _TIFFmemcpy(&dircount64, tif->tif_base + off, sizeof(uint64_t));
             }
-            off += sizeof(uint64_t);
+            off = (tmsize_t)((uint64_t)off + sizeof(uint64_t));
             if (tif->tif_flags & TIFF_SWAB)
                 TIFFSwabLong8(&dircount64);
             if (dircount64 > 4096)
@@ -6185,7 +6285,7 @@
         if (origdir == NULL)
             return 0;
         m = off + dircount16 * dirsize;
-        if ((m < off) || (m < (tmsize_t)(dircount16 * dirsize)) ||
+        if ((m < off) || (m < (tmsize_t)dircount16 * (tmsize_t)dirsize) ||
             (m > tif->tif_size))
         {
             TIFFErrorExtR(tif, module, "Can not read TIFF directory");
@@ -6194,7 +6294,8 @@
         }
         else
         {
-            _TIFFmemcpy(origdir, tif->tif_base + off, dircount16 * dirsize);
+            _TIFFmemcpy(origdir, tif->tif_base + off,
+                        (tmsize_t)dircount16 * dirsize);
         }
         if (nextdiroff)
         {
@@ -6202,9 +6303,9 @@
             if (!(tif->tif_flags & TIFF_BIGTIFF))
             {
                 uint32_t nextdiroff32;
-                m = off + sizeof(uint32_t);
-                if ((m < off) || (m < (tmsize_t)sizeof(uint32_t)) ||
-                    (m > tif->tif_size))
+                m = (tmsize_t)((uint64_t)off + sizeof(uint32_t));
+                if ((m < off) || ((uint64_t)m < sizeof(uint32_t)) ||
+                    ((uint64_t)m > (uint64_t)tif->tif_size))
                     nextdiroff32 = 0;
                 else
                     _TIFFmemcpy(&nextdiroff32, tif->tif_base + off,
@@ -6215,9 +6316,9 @@
             }
             else
             {
-                m = off + sizeof(uint64_t);
-                if ((m < off) || (m < (tmsize_t)sizeof(uint64_t)) ||
-                    (m > tif->tif_size))
+                m = (tmsize_t)((uint64_t)off + sizeof(uint64_t));
+                if ((m < off) || ((uint64_t)m < sizeof(uint64_t)) ||
+                    ((uint64_t)m > (uint64_t)tif->tif_size))
                     *nextdiroff = 0;
                 else
                     _TIFFmemcpy(nextdiroff, tif->tif_base + off,
@@ -6363,8 +6464,8 @@
                     /* TIFFReadDirEntryArrayWithLimit() ensures this can't be
                      * larger than MAX_SIZE_TAG_DATA */
                     assert((uint32_t)dp->tdir_count + 1 == dp->tdir_count + 1);
-                    uint8_t *o =
-                        _TIFFmallocExt(tif, (uint32_t)dp->tdir_count + 1);
+                    uint8_t *o = (uint8_t *)_TIFFmallocExt(
+                        tif, (uint32_t)dp->tdir_count + 1);
                     if (o == NULL)
                     {
                         if (data != NULL)
@@ -6506,7 +6607,7 @@
             {
                 if (!EvaluateIFDdatasizeReading(tif, dp))
                     return 0;
-                if (!TIFFSetField(tif, dp->tdir_tag, data))
+                if (!TIFFSetField(tif, dp->tdir_tag, (double)data))
                     return (0);
             }
         }
@@ -6918,6 +7019,41 @@
             }
         }
         break;
+        case TIFF_SETGET_C0_IFD8:
+        {
+            uint64_t *data;
+            assert(fip->field_readcount >= 1);
+            assert(fip->field_passcount == 0);
+            if (dp->tdir_count != (uint64_t)fip->field_readcount)
+            {
+                TIFFWarningExtR(tif, module,
+                                "incorrect count for field \"%s\", expected "
+                                "%d, got %" PRIu64,
+                                fip->field_name, (int)fip->field_readcount,
+                                dp->tdir_count);
+                return (0);
+            }
+            else
+            {
+                err = TIFFReadDirEntryIfd8Array(tif, dp, &data);
+                if (err == TIFFReadDirEntryErrOk)
+                {
+                    if (!EvaluateIFDdatasizeReading(tif, dp))
+                    {
+                        if (data != 0)
+                            _TIFFfreeExt(tif, data);
+                        return 0;
+                    }
+                    int m;
+                    m = TIFFSetField(tif, dp->tdir_tag, data);
+                    if (data != 0)
+                        _TIFFfreeExt(tif, data);
+                    if (!m)
+                        return (0);
+                }
+            }
+        }
+        break;
         case TIFF_SETGET_C16_ASCII:
         {
             uint8_t *data;
@@ -6946,8 +7082,8 @@
                                         "byte. Forcing it to be null",
                                         fip->field_name);
                         /* Enlarge buffer and add terminating null. */
-                        uint8_t *o =
-                            _TIFFmallocExt(tif, (uint32_t)dp->tdir_count + 1);
+                        uint8_t *o = (uint8_t *)_TIFFmallocExt(
+                            tif, (uint32_t)dp->tdir_count + 1);
                         if (o == NULL)
                         {
                             if (data != NULL)
@@ -7317,8 +7453,8 @@
                         "in null byte. Forcing it to be null",
                         fip->field_name);
                     /* Enlarge buffer and add terminating null. */
-                    uint8_t *o =
-                        _TIFFmallocExt(tif, (uint32_t)dp->tdir_count + 1);
+                    uint8_t *o = (uint8_t *)_TIFFmallocExt(
+                        tif, (uint32_t)dp->tdir_count + 1);
                     if (o == NULL)
                     {
                         if (data != NULL)
@@ -7632,6 +7768,11 @@
             }
         }
         break;
+        case TIFF_SETGET_INT:
+        case TIFF_SETGET_C0_ASCII:
+        case TIFF_SETGET_OTHER:
+            assert(0); /* these should not arrive here */
+            break;
         default:
             assert(0); /* we should never get here */
             break;
@@ -7708,9 +7849,10 @@
         }
         if (dir->tdir_count)
             _TIFFmemcpy(resizeddata, data,
-                        (uint32_t)dir->tdir_count * sizeof(uint64_t));
+                        (tmsize_t)((size_t)dir->tdir_count * sizeof(uint64_t)));
         _TIFFmemset(resizeddata + (uint32_t)dir->tdir_count, 0,
-                    (nstrips - (uint32_t)dir->tdir_count) * sizeof(uint64_t));
+                    (tmsize_t)((size_t)(nstrips - (uint32_t)dir->tdir_count) *
+                               sizeof(uint64_t)));
         _TIFFfreeExt(tif, data);
         data = resizeddata;
     }
@@ -7874,7 +8016,7 @@
  */
 static void ChopUpSingleUncompressedStrip(TIFF *tif)
 {
-    register TIFFDirectory *td = &tif->tif_dir;
+    TIFFDirectory *td = &tif->tif_dir;
     uint64_t bytecount;
     uint64_t offset;
     uint32_t rowblock;
@@ -7889,7 +8031,7 @@
     /* later ( StripOffsets and StripByteCounts improperly filled) . */
     if (bytecount == 0 && tif->tif_mode != O_RDONLY)
         return;
-    offset = TIFFGetStrileByteCount(tif, 0);
+    offset = TIFFGetStrileOffset(tif, 0);
     assert(td->td_planarconfig == PLANARCONFIG_CONTIG);
     if ((td->td_photometric == PHOTOMETRIC_YCBCR) && (!isUpSampled(tif)))
         rowblock = td->td_ycbcrsubsampling[1];
@@ -8040,7 +8182,7 @@
 TIFF_NOSANITIZE_UNSIGNED_INT_OVERFLOW
 static uint64_t _TIFFUnsanitizedAddUInt64AndInt(uint64_t a, int b)
 {
-    return a + b;
+    return a + (uint64_t)b;
 }
 
 /* Read the value of [Strip|Tile]Offset or [Strip|Tile]ByteCount around
@@ -8119,7 +8261,7 @@
         panVals[strile] = 0;
         return 0;
     }
-    nOffset = nBaseOffset + sizeofval * strile;
+    nOffset = nBaseOffset + (uint64_t)sizeofval * (uint64_t)strile;
     nOffsetStartPage = (nOffset / IO_CACHE_PAGE_SIZE) * IO_CACHE_PAGE_SIZE;
     nOffsetEndPage = nOffsetStartPage + IO_CACHE_PAGE_SIZE;
 
@@ -8127,7 +8269,7 @@
         nOffsetEndPage += IO_CACHE_PAGE_SIZE;
 #undef IO_CACHE_PAGE_SIZE
 
-    nLastStripOffset = nBaseOffset + arraySize * sizeofval;
+    nLastStripOffset = nBaseOffset + (uint64_t)arraySize * sizeofval;
     if (nLastStripOffset < nOffsetEndPage)
         nOffsetEndPage = nLastStripOffset;
     if (nOffsetStartPage >= nOffsetEndPage)
@@ -8262,9 +8404,9 @@
         }
 #endif
         offsetArray = (uint64_t *)(_TIFFreallocExt(tif, td->td_stripoffset_p,
-                                                   nArraySize));
+                                                   (tmsize_t)nArraySize));
         bytecountArray = (uint64_t *)(_TIFFreallocExt(
-            tif, td->td_stripbytecount_p, nArraySize));
+            tif, td->td_stripbytecount_p, (tmsize_t)nArraySize));
         if (offsetArray)
             td->td_stripoffset_p = offsetArray;
         if (bytecountArray)
@@ -8298,7 +8440,7 @@
 
     if (~((*parray)[strile]) == 0)
     {
-        if (!_TIFFPartialReadStripArray(tif, dirent, strile, *parray))
+        if (!_TIFFPartialReadStripArray(tif, dirent, (int)strile, *parray))
         {
             (*parray)[strile] = 0;
             return 0;
@@ -8316,10 +8458,26 @@
     TIFFDirectory *td = &tif->tif_dir;
     if (pbErr)
         *pbErr = 0;
+
+    /* Avoid the "dirent->tdir_count <= 4" code path for one of
+     * StripOffsets/StripByteCounts, and the other code path for the other one,
+     * which will lead to inconsistencies and potential out-of-bounds reads.
+     */
+    if ((td->td_stripoffset_entry.tdir_count <= 4) !=
+        (td->td_stripbytecount_entry.tdir_count <= 4))
+    {
+        TIFFErrorExtR(tif, "_TIFFGetStrileOffsetOrByteCountValue",
+                      "Inconsistent directory count between StripOffsets and "
+                      "StripByteCounts");
+        if (pbErr)
+            *pbErr = 1;
+        return 0;
+    }
+
     if ((tif->tif_flags & TIFF_DEFERSTRILELOAD) &&
         !(tif->tif_flags & TIFF_CHOPPEDUPARRAYS))
     {
-        if (!(tif->tif_flags & TIFF_LAZYSTRILELOAD) ||
+        if (!(tif->tif_flags & TIFF_LAZYSTRILELOAD_ASKED) ||
             /* If the values may fit in the toff_long/toff_long8 member */
             /* then use _TIFFFillStriles to simplify _TIFFFetchStrileValue */
             dirent->tdir_count <= 4)
@@ -8390,7 +8548,7 @@
 
 static int _TIFFFillStrilesInternal(TIFF *tif, int loadStripByteCount)
 {
-    register TIFFDirectory *td = &tif->tif_dir;
+    TIFFDirectory *td = &tif->tif_dir;
     int return_value = 1;
 
     /* Do not do anything if TIFF_DEFERSTRILELOAD is not set */
@@ -8398,7 +8556,8 @@
         (tif->tif_flags & TIFF_CHOPPEDUPARRAYS) != 0)
         return 1;
 
-    if (tif->tif_flags & TIFF_LAZYSTRILELOAD)
+    if ((tif->tif_flags & TIFF_LAZYSTRILELOAD_ASKED) &&
+        !(tif->tif_flags & TIFF_LAZYSTRILELOAD_DONE))
     {
         /* In case of lazy loading, reload completely the arrays */
         _TIFFfreeExt(tif, td->td_stripoffset_p);
@@ -8406,7 +8565,7 @@
         td->td_stripoffset_p = NULL;
         td->td_stripbytecount_p = NULL;
         td->td_stripoffsetbyteallocsize = 0;
-        tif->tif_flags &= ~TIFF_LAZYSTRILELOAD;
+        tif->tif_flags |= TIFF_LAZYSTRILELOAD_DONE;
     }
 
     /* If stripoffset array is already loaded, exit with success */
diff --git a/third_party/libtiff/tif_dirwrite.c b/third_party/libtiff/tif_dirwrite.c
index bc5ada0..5da087e 100644
--- a/third_party/libtiff/tif_dirwrite.c
+++ b/third_party/libtiff/tif_dirwrite.c
@@ -365,7 +365,7 @@
                 }
                 if (tif->tif_flags & TIFF_SWAB)
                     TIFFSwabShort(&dircount);
-                (void)TIFFSeekFile(tif, nextdir + 2 + dircount * 12, SEEK_SET);
+                (void)TIFFSeekFile(tif, nextdir + 2 + dircount * 12U, SEEK_SET);
                 if (!ReadOK(tif, &nextnextdir, 4))
                 {
                     TIFFErrorExtR(tif, module, "Error fetching directory link");
@@ -377,7 +377,7 @@
                 {
                     uint32_t m;
                     m = 0;
-                    (void)TIFFSeekFile(tif, nextdir + 2 + dircount * 12,
+                    (void)TIFFSeekFile(tif, nextdir + 2 + dircount * 12U,
                                        SEEK_SET);
                     if (!WriteOK(tif, &m, 4))
                     {
@@ -417,7 +417,6 @@
             while (1)
             {
                 uint64_t dircount64;
-                uint16_t dircount;
                 uint64_t nextnextdir;
 
                 if (!SeekOK(tif, nextdir) || !ReadOK(tif, &dircount64, 8))
@@ -435,8 +434,8 @@
                                   "corrupt TIFF");
                     return (0);
                 }
-                dircount = (uint16_t)dircount64;
-                (void)TIFFSeekFile(tif, nextdir + 8 + dircount * 20, SEEK_SET);
+                (void)TIFFSeekFile(tif, nextdir + 8 + dircount64 * 20,
+                                   SEEK_SET);
                 if (!ReadOK(tif, &nextnextdir, 8))
                 {
                     TIFFErrorExtR(tif, module, "Error fetching directory link");
@@ -448,7 +447,7 @@
                 {
                     uint64_t m;
                     m = 0;
-                    (void)TIFFSeekFile(tif, nextdir + 8 + dircount * 20,
+                    (void)TIFFSeekFile(tif, nextdir + 8 + dircount64 * 20,
                                        SEEK_SET);
                     if (!WriteOK(tif, &m, 8))
                     {
@@ -592,24 +591,24 @@
             }
             if (TIFFFieldSet(tif, FIELD_RESOLUTION))
             {
-                if (!TIFFWriteDirectoryTagRational(tif, &ndir, dir,
-                                                   TIFFTAG_XRESOLUTION,
-                                                   tif->tif_dir.td_xresolution))
+                if (!TIFFWriteDirectoryTagRational(
+                        tif, &ndir, dir, TIFFTAG_XRESOLUTION,
+                        (double)tif->tif_dir.td_xresolution))
                     goto bad;
-                if (!TIFFWriteDirectoryTagRational(tif, &ndir, dir,
-                                                   TIFFTAG_YRESOLUTION,
-                                                   tif->tif_dir.td_yresolution))
+                if (!TIFFWriteDirectoryTagRational(
+                        tif, &ndir, dir, TIFFTAG_YRESOLUTION,
+                        (double)tif->tif_dir.td_yresolution))
                     goto bad;
             }
             if (TIFFFieldSet(tif, FIELD_POSITION))
             {
-                if (!TIFFWriteDirectoryTagRational(tif, &ndir, dir,
-                                                   TIFFTAG_XPOSITION,
-                                                   tif->tif_dir.td_xposition))
+                if (!TIFFWriteDirectoryTagRational(
+                        tif, &ndir, dir, TIFFTAG_XPOSITION,
+                        (double)tif->tif_dir.td_xposition))
                     goto bad;
-                if (!TIFFWriteDirectoryTagRational(tif, &ndir, dir,
-                                                   TIFFTAG_YPOSITION,
-                                                   tif->tif_dir.td_yposition))
+                if (!TIFFWriteDirectoryTagRational(
+                        tif, &ndir, dir, TIFFTAG_YPOSITION,
+                        (double)tif->tif_dir.td_yposition))
                     goto bad;
             }
             if (TIFFFieldSet(tif, FIELD_SUBFILETYPE))
@@ -712,6 +711,14 @@
             }
             if (TIFFFieldSet(tif, FIELD_STRIPBYTECOUNTS))
             {
+                /*  Check td_stripbytecount_p for NULL pointer (bug#749) */
+                if (tif->tif_dir.td_stripbytecount_p == NULL)
+                {
+                    TIFFErrorExtR(
+                        tif, module,
+                        "StripByteCount array is not set, pointer is NULL");
+                    goto bad;
+                }
                 if (!isTiled(tif))
                 {
                     if (!TIFFWriteDirectoryTagLongLong8Array(
@@ -731,6 +738,14 @@
             }
             if (TIFFFieldSet(tif, FIELD_STRIPOFFSETS))
             {
+                /*  Check td_stripoffset_p for NULL pointer (bug#749) */
+                if (tif->tif_dir.td_stripoffset_p == NULL)
+                {
+                    TIFFErrorExtR(
+                        tif, module,
+                        "StripByteOffset array is not set, pointer is NULL");
+                    goto bad;
+                }
                 if (!isTiled(tif))
                 {
                     /* td_stripoffset_p might be NULL in an odd OJPEG case. See
@@ -851,7 +866,8 @@
             {
                 if (!TIFFWriteDirectoryTagAscii(
                         tif, &ndir, dir, TIFFTAG_INKNAMES,
-                        tif->tif_dir.td_inknameslen, tif->tif_dir.td_inknames))
+                        (uint32_t)tif->tif_dir.td_inknameslen,
+                        tif->tif_dir.td_inknames))
                     goto bad;
             }
             if (TIFFFieldSet(tif, FIELD_NUMBEROFINKS))
@@ -932,10 +948,58 @@
                                 TIFFGetField(tif, o->field_tag, &pa, &pb);
                                 if (!TIFFWriteDirectoryTagUndefinedArray(
                                         tif, &ndir, dir, (uint16_t)o->field_tag,
-                                        pa, pb))
+                                        pa, (uint8_t *)pb))
                                     goto bad;
                             }
                             break;
+                            case TIFF_SETGET_UNDEFINED:
+                            case TIFF_SETGET_SINT8:
+                            case TIFF_SETGET_SINT16:
+                            case TIFF_SETGET_SINT32:
+                            case TIFF_SETGET_UINT64:
+                            case TIFF_SETGET_SINT64:
+                            case TIFF_SETGET_FLOAT:
+                            case TIFF_SETGET_DOUBLE:
+                            case TIFF_SETGET_IFD8:
+                            case TIFF_SETGET_INT:
+                            case TIFF_SETGET_UINT16_PAIR:
+                            case TIFF_SETGET_C0_ASCII:
+                            case TIFF_SETGET_C0_UINT8:
+                            case TIFF_SETGET_C0_SINT8:
+                            case TIFF_SETGET_C0_UINT16:
+                            case TIFF_SETGET_C0_SINT16:
+                            case TIFF_SETGET_C0_UINT32:
+                            case TIFF_SETGET_C0_SINT32:
+                            case TIFF_SETGET_C0_UINT64:
+                            case TIFF_SETGET_C0_SINT64:
+                            case TIFF_SETGET_C0_FLOAT:
+                            case TIFF_SETGET_C0_DOUBLE:
+                            case TIFF_SETGET_C0_IFD8:
+                            case TIFF_SETGET_C16_ASCII:
+                            case TIFF_SETGET_C16_UINT8:
+                            case TIFF_SETGET_C16_SINT8:
+                            case TIFF_SETGET_C16_UINT16:
+                            case TIFF_SETGET_C16_SINT16:
+                            case TIFF_SETGET_C16_UINT32:
+                            case TIFF_SETGET_C16_SINT32:
+                            case TIFF_SETGET_C16_UINT64:
+                            case TIFF_SETGET_C16_SINT64:
+                            case TIFF_SETGET_C16_FLOAT:
+                            case TIFF_SETGET_C16_DOUBLE:
+                            case TIFF_SETGET_C16_IFD8:
+                            case TIFF_SETGET_C32_ASCII:
+                            case TIFF_SETGET_C32_SINT8:
+                            case TIFF_SETGET_C32_UINT16:
+                            case TIFF_SETGET_C32_SINT16:
+                            case TIFF_SETGET_C32_UINT32:
+                            case TIFF_SETGET_C32_SINT32:
+                            case TIFF_SETGET_C32_UINT64:
+                            case TIFF_SETGET_C32_SINT64:
+                            case TIFF_SETGET_C32_FLOAT:
+                            case TIFF_SETGET_C32_DOUBLE:
+                            case TIFF_SETGET_C32_IFD8:
+                            case TIFF_SETGET_UINT8:
+                            case TIFF_SETGET_OTHER:
                             default:
                                 TIFFErrorExtR(
                                     tif, module,
@@ -954,67 +1018,67 @@
         {
             uint16_t tag =
                 (uint16_t)tif->tif_dir.td_customValues[m].info->field_tag;
-            uint32_t count = tif->tif_dir.td_customValues[m].count;
+            uint32_t count = (uint32_t)tif->tif_dir.td_customValues[m].count;
             switch (tif->tif_dir.td_customValues[m].info->field_type)
             {
                 case TIFF_ASCII:
                     if (!TIFFWriteDirectoryTagAscii(
                             tif, &ndir, dir, tag, count,
-                            tif->tif_dir.td_customValues[m].value))
+                            (char *)tif->tif_dir.td_customValues[m].value))
                         goto bad;
                     break;
                 case TIFF_UNDEFINED:
                     if (!TIFFWriteDirectoryTagUndefinedArray(
                             tif, &ndir, dir, tag, count,
-                            tif->tif_dir.td_customValues[m].value))
+                            (uint8_t *)tif->tif_dir.td_customValues[m].value))
                         goto bad;
                     break;
                 case TIFF_BYTE:
                     if (!TIFFWriteDirectoryTagByteArray(
                             tif, &ndir, dir, tag, count,
-                            tif->tif_dir.td_customValues[m].value))
+                            (uint8_t *)tif->tif_dir.td_customValues[m].value))
                         goto bad;
                     break;
                 case TIFF_SBYTE:
                     if (!TIFFWriteDirectoryTagSbyteArray(
                             tif, &ndir, dir, tag, count,
-                            tif->tif_dir.td_customValues[m].value))
+                            (int8_t *)tif->tif_dir.td_customValues[m].value))
                         goto bad;
                     break;
                 case TIFF_SHORT:
                     if (!TIFFWriteDirectoryTagShortArray(
                             tif, &ndir, dir, tag, count,
-                            tif->tif_dir.td_customValues[m].value))
+                            (uint16_t *)tif->tif_dir.td_customValues[m].value))
                         goto bad;
                     break;
                 case TIFF_SSHORT:
                     if (!TIFFWriteDirectoryTagSshortArray(
                             tif, &ndir, dir, tag, count,
-                            tif->tif_dir.td_customValues[m].value))
+                            (int16_t *)tif->tif_dir.td_customValues[m].value))
                         goto bad;
                     break;
                 case TIFF_LONG:
                     if (!TIFFWriteDirectoryTagLongArray(
                             tif, &ndir, dir, tag, count,
-                            tif->tif_dir.td_customValues[m].value))
+                            (uint32_t *)tif->tif_dir.td_customValues[m].value))
                         goto bad;
                     break;
                 case TIFF_SLONG:
                     if (!TIFFWriteDirectoryTagSlongArray(
                             tif, &ndir, dir, tag, count,
-                            tif->tif_dir.td_customValues[m].value))
+                            (int32_t *)tif->tif_dir.td_customValues[m].value))
                         goto bad;
                     break;
                 case TIFF_LONG8:
                     if (!TIFFWriteDirectoryTagLong8Array(
                             tif, &ndir, dir, tag, count,
-                            tif->tif_dir.td_customValues[m].value))
+                            (uint64_t *)tif->tif_dir.td_customValues[m].value))
                         goto bad;
                     break;
                 case TIFF_SLONG8:
                     if (!TIFFWriteDirectoryTagSlong8Array(
                             tif, &ndir, dir, tag, count,
-                            tif->tif_dir.td_customValues[m].value))
+                            (int64_t *)tif->tif_dir.td_customValues[m].value))
                         goto bad;
                     break;
                 case TIFF_RATIONAL:
@@ -1029,7 +1093,8 @@
                     {
                         if (!TIFFWriteDirectoryTagRationalDoubleArray(
                                 tif, &ndir, dir, tag, count,
-                                tif->tif_dir.td_customValues[m].value))
+                                (double *)tif->tif_dir.td_customValues[m]
+                                    .value))
                             goto bad;
                     }
                     else
@@ -1037,7 +1102,7 @@
                         /*-- default should be tv_size == 4 */
                         if (!TIFFWriteDirectoryTagRationalArray(
                                 tif, &ndir, dir, tag, count,
-                                tif->tif_dir.td_customValues[m].value))
+                                (float *)tif->tif_dir.td_customValues[m].value))
                             goto bad;
                         /*-- ToDo: After Testing, this should be removed and
                          * tv_size==4 should be set as default. */
@@ -1064,7 +1129,8 @@
                     {
                         if (!TIFFWriteDirectoryTagSrationalDoubleArray(
                                 tif, &ndir, dir, tag, count,
-                                tif->tif_dir.td_customValues[m].value))
+                                (double *)tif->tif_dir.td_customValues[m]
+                                    .value))
                             goto bad;
                     }
                     else
@@ -1072,7 +1138,7 @@
                         /*-- default should be tv_size == 4 */
                         if (!TIFFWriteDirectoryTagSrationalArray(
                                 tif, &ndir, dir, tag, count,
-                                tif->tif_dir.td_customValues[m].value))
+                                (float *)tif->tif_dir.td_customValues[m].value))
                             goto bad;
                         /*-- ToDo: After Testing, this should be removed and
                          * tv_size==4 should be set as default. */
@@ -1090,27 +1156,28 @@
                 case TIFF_FLOAT:
                     if (!TIFFWriteDirectoryTagFloatArray(
                             tif, &ndir, dir, tag, count,
-                            tif->tif_dir.td_customValues[m].value))
+                            (float *)tif->tif_dir.td_customValues[m].value))
                         goto bad;
                     break;
                 case TIFF_DOUBLE:
                     if (!TIFFWriteDirectoryTagDoubleArray(
                             tif, &ndir, dir, tag, count,
-                            tif->tif_dir.td_customValues[m].value))
+                            (double *)tif->tif_dir.td_customValues[m].value))
                         goto bad;
                     break;
                 case TIFF_IFD:
                     if (!TIFFWriteDirectoryTagIfdArray(
                             tif, &ndir, dir, tag, count,
-                            tif->tif_dir.td_customValues[m].value))
+                            (uint32_t *)tif->tif_dir.td_customValues[m].value))
                         goto bad;
                     break;
                 case TIFF_IFD8:
                     if (!TIFFWriteDirectoryTagIfdIfd8Array(
                             tif, &ndir, dir, tag, count,
-                            tif->tif_dir.td_customValues[m].value))
+                            (uint64_t *)tif->tif_dir.td_customValues[m].value))
                         goto bad;
                     break;
+                case TIFF_NOTYPE:
                 default:
                     assert(0); /* we should never get here */
                     break;
@@ -1128,7 +1195,8 @@
             tif->tif_dir.td_dirdatasize_write += 8 + ndir * 20 + 8;
 
         /* Setup a new directory within first pass. */
-        dir = _TIFFmallocExt(tif, ndir * sizeof(TIFFDirEntry));
+        dir = (TIFFDirEntry *)_TIFFmallocExt(
+            tif, (tmsize_t)((size_t)ndir * sizeof(TIFFDirEntry)));
         if (dir == NULL)
         {
             TIFFErrorExtR(tif, module, "Out of memory");
@@ -1238,7 +1306,7 @@
         uint8_t *n;
         uint32_t nTmp;
         TIFFDirEntry *o;
-        n = dirmem;
+        n = (uint8_t *)dirmem;
         *(uint16_t *)n = (uint16_t)ndir;
         if (tif->tif_flags & TIFF_SWAB)
             TIFFSwabShort((uint16_t *)n);
@@ -1274,7 +1342,7 @@
     {
         uint8_t *n;
         TIFFDirEntry *o;
-        n = dirmem;
+        n = (uint8_t *)dirmem;
         *(uint64_t *)n = ndir;
         if (tif->tif_flags & TIFF_SWAB)
             TIFFSwabLong8((uint64_t *)n);
@@ -1405,7 +1473,7 @@
 {
     if (val > 127)
         return 127;
-    if (val < -128 || val != val)
+    if (val < -128 || isnan(val))
         return -128;
     return (int8_t)val;
 }
@@ -1414,7 +1482,7 @@
 {
     if (val > 32767)
         return 32767;
-    if (val < -32768 || val != val)
+    if (val < -32768 || isnan(val))
         return -32768;
     return (int16_t)val;
 }
@@ -1423,7 +1491,7 @@
 {
     if (val > 0x7FFFFFFF)
         return 0x7FFFFFFF;
-    if (val < -0x7FFFFFFF - 1 || val != val)
+    if (val < -0x7FFFFFFF - 1 || isnan(val))
         return -0x7FFFFFFF - 1;
     return (int32_t)val;
 }
@@ -1432,7 +1500,7 @@
 {
     if (val < 0)
         return 0;
-    if (val > 255 || val != val)
+    if (val > 255 || isnan(val))
         return 255;
     return (uint8_t)val;
 }
@@ -1441,7 +1509,7 @@
 {
     if (val < 0)
         return 0;
-    if (val > 65535 || val != val)
+    if (val > 65535 || isnan(val))
         return 65535;
     return (uint16_t)val;
 }
@@ -1450,7 +1518,7 @@
 {
     if (val < 0)
         return 0;
-    if (val > 0xFFFFFFFFU || val != val)
+    if (val > 0xFFFFFFFFU || isnan(val))
         return 0xFFFFFFFFU;
     return (uint32_t)val;
 }
@@ -1464,7 +1532,7 @@
     void *conv;
     uint32_t i;
     int ok;
-    conv = _TIFFmallocExt(tif, count * sizeof(double));
+    conv = _TIFFmallocExt(tif, (tmsize_t)((size_t)count * sizeof(double)));
     if (conv == NULL)
     {
         TIFFErrorExtR(tif, module, "Out of memory");
@@ -1603,7 +1671,9 @@
         return (TIFFWriteDirectoryTagCheckedShortArray(
             tif, ndir, dir, tag, tif->tif_dir.td_samplesperpixel, NULL));
     }
-    m = _TIFFmallocExt(tif, tif->tif_dir.td_samplesperpixel * sizeof(uint16_t));
+    m = (uint16_t *)_TIFFmallocExt(
+        tif,
+        (tmsize_t)((size_t)tif->tif_dir.td_samplesperpixel * sizeof(uint16_t)));
     if (m == NULL)
     {
         TIFFErrorExtR(tif, module, "Out of memory");
@@ -1664,14 +1734,6 @@
     uint32_t *q;
     int o;
 
-    /* is this just a counting pass? */
-    if (dir == NULL)
-    {
-        /* only evaluate IFD data size and inc. ndir */
-        return (TIFFWriteDirectoryTagCheckedLong8Array(tif, ndir, dir, tag,
-                                                       count, value));
-    }
-
     /* We always write Long8 for BigTIFF, no checking needed. */
     if (tif->tif_flags & TIFF_BIGTIFF)
         return (TIFFWriteDirectoryTagCheckedLong8Array(tif, ndir, dir, tag,
@@ -1681,7 +1743,8 @@
     ** For classic tiff we want to verify everything is in range for long
     ** and convert to long format.
     */
-    p = _TIFFmallocExt(tif, count * sizeof(uint32_t));
+    p = (uint32_t *)_TIFFmallocExt(
+        tif, (tmsize_t)((size_t)count * sizeof(uint32_t)));
     if (p == NULL)
     {
         TIFFErrorExtR(tif, module, "Out of memory");
@@ -1725,13 +1788,6 @@
     int32_t *q;
     int o;
 
-    /* is this just a counting pass? */
-    if (dir == NULL)
-    {
-        /* only evaluate IFD data size and inc. ndir */
-        return (TIFFWriteDirectoryTagCheckedSlong8Array(tif, ndir, dir, tag,
-                                                        count, value));
-    }
     /* We always write SLong8 for BigTIFF, no checking needed. */
     if (tif->tif_flags & TIFF_BIGTIFF)
         return (TIFFWriteDirectoryTagCheckedSlong8Array(tif, ndir, dir, tag,
@@ -1741,7 +1797,8 @@
     ** For classic tiff we want to verify everything is in range for signed-long
     ** and convert to signed-long format.
     */
-    p = _TIFFmallocExt(tif, count * sizeof(uint32_t));
+    p = (int32_t *)_TIFFmallocExt(tif,
+                                  (tmsize_t)((size_t)count * sizeof(uint32_t)));
     if (p == NULL)
     {
         TIFFErrorExtR(tif, module, "Out of memory");
@@ -1960,7 +2017,8 @@
         ** and convert to long format.
         */
 
-        uint32_t *p = _TIFFmallocExt(tif, count * sizeof(uint32_t));
+        uint32_t *p = (uint32_t *)_TIFFmallocExt(
+            tif, (tmsize_t)((size_t)count * sizeof(uint32_t)));
         uint32_t *q;
         uint64_t *ma;
         uint32_t mb;
@@ -1990,7 +2048,8 @@
     }
     else
     {
-        uint16_t *p = _TIFFmallocExt(tif, count * sizeof(uint16_t));
+        uint16_t *p = (uint16_t *)_TIFFmallocExt(
+            tif, (tmsize_t)((size_t)count * sizeof(uint16_t)));
         uint16_t *q;
         uint64_t *ma;
         uint32_t mb;
@@ -2050,7 +2109,8 @@
     ** and convert to long format.
     */
 
-    p = _TIFFmallocExt(tif, count * sizeof(uint32_t));
+    p = (uint32_t *)_TIFFmallocExt(
+        tif, (tmsize_t)((size_t)count * sizeof(uint32_t)));
     if (p == NULL)
     {
         TIFFErrorExtR(tif, module, "Out of memory");
@@ -2101,26 +2161,45 @@
 {
     static const char module[] = "TIFFWriteDirectoryTagColormap";
     uint32_t m;
+    uint32_t count;
+    uint64_t count64;
+    tmsize_t total_values;
+    tmsize_t plane_bytes;
     uint16_t *n;
     int o;
-    m = (1 << tif->tif_dir.td_bitspersample);
+    if (tif->tif_dir.td_bitspersample >= 32)
+    {
+        TIFFErrorExtR(tif, module, "BitsPerSample too large for Colormap");
+        return (0);
+    }
+    m = 1U << tif->tif_dir.td_bitspersample;
+    count64 = _TIFFMultiply64(tif, 3U, m, module);
+    if (count64 == 0)
+        return (0);
+    count = _TIFFCastUInt64ToUInt32(tif, count64, module);
+    total_values = _TIFFCastUInt64ToSSize(tif, count64, module);
+    plane_bytes = _TIFFCastUInt64ToSSize(
+        tif, _TIFFMultiply64(tif, m, sizeof(uint16_t), module), module);
+    if (count == 0 || total_values == 0 || plane_bytes == 0)
+        return (0);
     if (dir == NULL) /* Just evaluate IFD data size and increment ndir. */
     {
-        EvaluateIFDdatasizeWrite(tif, 3 * m, sizeof(uint16_t), ndir);
+        EvaluateIFDdatasizeWrite(tif, count, sizeof(uint16_t), ndir);
         return 1;
     }
 
-    n = _TIFFmallocExt(tif, 3 * m * sizeof(uint16_t));
+    n = (uint16_t *)_TIFFCheckMalloc(tif, total_values, sizeof(uint16_t),
+                                     module);
     if (n == NULL)
     {
         TIFFErrorExtR(tif, module, "Out of memory");
         return (0);
     }
-    _TIFFmemcpy(&n[0], tif->tif_dir.td_colormap[0], m * sizeof(uint16_t));
-    _TIFFmemcpy(&n[m], tif->tif_dir.td_colormap[1], m * sizeof(uint16_t));
-    _TIFFmemcpy(&n[2 * m], tif->tif_dir.td_colormap[2], m * sizeof(uint16_t));
+    _TIFFmemcpy(&n[0], tif->tif_dir.td_colormap[0], plane_bytes);
+    _TIFFmemcpy(&n[m], tif->tif_dir.td_colormap[1], plane_bytes);
+    _TIFFmemcpy(&n[2 * m], tif->tif_dir.td_colormap[2], plane_bytes);
     o = TIFFWriteDirectoryTagCheckedShortArray(tif, ndir, dir, TIFFTAG_COLORMAP,
-                                               3 * m, n);
+                                               count, n);
     _TIFFfreeExt(tif, n);
     return (o);
 }
@@ -2130,13 +2209,27 @@
 {
     static const char module[] = "TIFFWriteDirectoryTagTransferfunction";
     uint32_t m;
+    uint32_t count;
+    uint64_t count64;
+    tmsize_t total_values;
+    tmsize_t plane_bytes;
     uint16_t n;
     uint16_t *o;
     int p;
     /* TIFFTAG_TRANSFERFUNCTION expects (1 or 3) pointer to arrays with
-     *  (1 << BitsPerSample) * uint16_t values.
+     * 2**BitsPerSample uint16_t values.
      */
-    m = (1 << tif->tif_dir.td_bitspersample);
+    if (tif->tif_dir.td_bitspersample >= 32)
+    {
+        TIFFErrorExtR(tif, module,
+                      "BitsPerSample too large for TransferFunction");
+        return (0);
+    }
+    m = 1U << tif->tif_dir.td_bitspersample;
+    plane_bytes = _TIFFCastUInt64ToSSize(
+        tif, _TIFFMultiply64(tif, m, sizeof(uint16_t), module), module);
+    if (plane_bytes == 0)
+        return (0);
     /* clang-format off */
     n = (tif->tif_dir.td_samplesperpixel - tif->tif_dir.td_extrasamples) > 1 ? 3 : 1;
     /* clang-format on */
@@ -2161,35 +2254,39 @@
     if (n == 3)
     {
         if (!_TIFFmemcmp(tif->tif_dir.td_transferfunction[0],
-                         tif->tif_dir.td_transferfunction[2],
-                         m * sizeof(uint16_t)) &&
+                         tif->tif_dir.td_transferfunction[2], plane_bytes) &&
             !_TIFFmemcmp(tif->tif_dir.td_transferfunction[0],
-                         tif->tif_dir.td_transferfunction[1],
-                         m * sizeof(uint16_t)))
+                         tif->tif_dir.td_transferfunction[1], plane_bytes))
             n = 1;
     }
+    count64 = _TIFFMultiply64(tif, n, m, module);
+    if (count64 == 0)
+        return (0);
+    count = _TIFFCastUInt64ToUInt32(tif, count64, module);
+    total_values = _TIFFCastUInt64ToSSize(tif, count64, module);
+    if (count == 0 || total_values == 0)
+        return (0);
     if (dir == NULL) /* Just evaluate IFD data size and increment ndir. */
     {
-        EvaluateIFDdatasizeWrite(tif, n * m, 2, ndir);
+        EvaluateIFDdatasizeWrite(tif, count, 2, ndir);
         return 1;
     }
 
-    o = _TIFFmallocExt(tif, n * m * sizeof(uint16_t));
+    o = (uint16_t *)_TIFFCheckMalloc(tif, total_values, sizeof(uint16_t),
+                                     module);
     if (o == NULL)
     {
         TIFFErrorExtR(tif, module, "Out of memory");
         return (0);
     }
-    _TIFFmemcpy(&o[0], tif->tif_dir.td_transferfunction[0],
-                m * sizeof(uint16_t));
+    _TIFFmemcpy(&o[0], tif->tif_dir.td_transferfunction[0], plane_bytes);
     if (n > 1)
-        _TIFFmemcpy(&o[m], tif->tif_dir.td_transferfunction[1],
-                    m * sizeof(uint16_t));
+        _TIFFmemcpy(&o[m], tif->tif_dir.td_transferfunction[1], plane_bytes);
     if (n > 2)
         _TIFFmemcpy(&o[2 * m], tif->tif_dir.td_transferfunction[2],
-                    m * sizeof(uint16_t));
+                    plane_bytes);
     p = TIFFWriteDirectoryTagCheckedShortArray(
-        tif, ndir, dir, TIFFTAG_TRANSFERFUNCTION, n * m, o);
+        tif, ndir, dir, TIFFTAG_TRANSFERFUNCTION, count, o);
     _TIFFfreeExt(tif, o);
     return (p);
 }
@@ -2209,7 +2306,9 @@
         uint64_t *pa;
         uint32_t *pb;
         uint16_t p;
-        o = _TIFFmallocExt(tif, tif->tif_dir.td_nsubifd * sizeof(uint32_t));
+        o = (uint32_t *)_TIFFmallocExt(
+            tif,
+            (tmsize_t)((size_t)tif->tif_dir.td_nsubifd * sizeof(uint32_t)));
         if (o == NULL)
         {
             TIFFErrorExtR(tif, module, "Out of memory");
@@ -2494,7 +2593,7 @@
         TIFFErrorExtR(tif, module, "Negative value is illegal");
         return 0;
     }
-    else if (value != value)
+    else if (isnan(value))
     {
         TIFFErrorExtR(tif, module, "Not-a-number value is illegal");
         return 0;
@@ -2537,7 +2636,8 @@
         EvaluateIFDdatasizeWrite(tif, count * 2, sizeof(uint32_t), ndir);
         return 1;
     }
-    m = _TIFFmallocExt(tif, count * 2 * sizeof(uint32_t));
+    m = (uint32_t *)_TIFFCheckMalloc(tif, count, 2 * sizeof(uint32_t),
+                                     "for rational array");
     if (m == NULL)
     {
         TIFFErrorExtR(tif, module, "Out of memory");
@@ -2545,7 +2645,7 @@
     }
     for (na = value, nb = m, nc = 0; nc < count; na++, nb += 2, nc++)
     {
-        DoubleToRational(*na, &nb[0], &nb[1]);
+        DoubleToRational((double)*na, &nb[0], &nb[1]);
     }
     if (tif->tif_flags & TIFF_SWAB)
         TIFFSwabArrayOfLong(m, count * 2);
@@ -2573,7 +2673,8 @@
         EvaluateIFDdatasizeWrite(tif, count * 2, sizeof(int32_t), ndir);
         return 1;
     }
-    m = _TIFFmallocExt(tif, count * 2 * sizeof(int32_t));
+    m = (int32_t *)_TIFFCheckMalloc(tif, count, 2 * sizeof(int32_t),
+                                    "for srational array");
     if (m == NULL)
     {
         TIFFErrorExtR(tif, module, "Out of memory");
@@ -2581,7 +2682,7 @@
     }
     for (na = value, nb = m, nc = 0; nc < count; na++, nb += 2, nc++)
     {
-        DoubleToSrational(*na, &nb[0], &nb[1]);
+        DoubleToSrational((double)*na, &nb[0], &nb[1]);
     }
     if (tif->tif_flags & TIFF_SWAB)
         TIFFSwabArrayOfLong((uint32_t *)m, count * 2);
@@ -2610,7 +2711,8 @@
         EvaluateIFDdatasizeWrite(tif, count * 2, sizeof(uint32_t), ndir);
         return 1;
     }
-    m = _TIFFmallocExt(tif, count * 2 * sizeof(uint32_t));
+    m = (uint32_t *)_TIFFCheckMalloc(tif, count, 2 * sizeof(uint32_t),
+                                     "for rational double array");
     if (m == NULL)
     {
         TIFFErrorExtR(tif, module, "Out of memory");
@@ -2618,7 +2720,7 @@
     }
     for (na = value, nb = m, nc = 0; nc < count; na++, nb += 2, nc++)
     {
-        DoubleToRational(*na, &nb[0], &nb[1]);
+        DoubleToRational((double)*na, &nb[0], &nb[1]);
     }
     if (tif->tif_flags & TIFF_SWAB)
         TIFFSwabArrayOfLong(m, count * 2);
@@ -2645,7 +2747,8 @@
         EvaluateIFDdatasizeWrite(tif, count * 2, sizeof(int32_t), ndir);
         return 1;
     }
-    m = _TIFFmallocExt(tif, count * 2 * sizeof(int32_t));
+    m = (int32_t *)_TIFFCheckMalloc(tif, count, 2 * sizeof(int32_t),
+                                    "for srational double array");
     if (m == NULL)
     {
         TIFFErrorExtR(tif, module, "Out of memory");
@@ -2653,7 +2756,7 @@
     }
     for (na = value, nb = m, nc = 0; nc < count; na++, nb += 2, nc++)
     {
-        DoubleToSrational(*na, &nb[0], &nb[1]);
+        DoubleToSrational((double)*na, &nb[0], &nb[1]);
     }
     if (tif->tif_flags & TIFF_SWAB)
         TIFFSwabArrayOfLong((uint32_t *)m, count * 2);
@@ -2744,7 +2847,8 @@
      *the double-value of it reaches an integer number without fractional part.
      */
     bigDenom = 1;
-    while ((value != floor(value)) && (value < fMax) && (bigDenom < nMax))
+    while ((!TIFF_DOUBLE_EQ(value, floor(value))) && (value < fMax) &&
+           (bigDenom < nMax))
     {
         bigDenom <<= 1;
         value *= 2;
@@ -2836,7 +2940,7 @@
         return;
     }
     /*-- Check for easy integer numbers -- */
-    if (value == (uint32_t)(value))
+    if (TIFF_DOUBLE_EQ(value, (double)(uint32_t)value))
     {
         *num = (uint32_t)value;
         *denom = 1;
@@ -2911,7 +3015,7 @@
         return;
     }
     /*-- Check for easy numbers -- */
-    if (value == (int32_t)(value))
+    if (TIFF_DOUBLE_EQ(value, (double)(int32_t)value))
     {
         *num = (int32_t)(neg * value);
         *denom = 1;
@@ -3231,6 +3335,14 @@
             uint16_t dircount;
             uint32_t nextnextdir;
 
+            /* Update IDF loop list and check for IFD loop.
+             * ndir is IFD ID plus one. */
+            if (!_TIFFCheckDirNumberAndOffset(tif, ndir - 1, nextdir))
+            {
+                TIFFErrorExtR(tif, module, "Error IFD loop detected");
+                return 0; /* bad offset (IFD looping or more than
+                             TIFF_MAX_DIR_COUNT IFDs) */
+            }
             if (!SeekOK(tif, nextdir) || !ReadOK(tif, &dircount, 2))
             {
                 TIFFErrorExtR(tif, module, "Error fetching directory count");
@@ -3238,7 +3350,7 @@
             }
             if (tif->tif_flags & TIFF_SWAB)
                 TIFFSwabShort(&dircount);
-            (void)TIFFSeekFile(tif, nextdir + 2 + dircount * 12, SEEK_SET);
+            (void)TIFFSeekFile(tif, nextdir + 2 + dircount * 12U, SEEK_SET);
             if (!ReadOK(tif, &nextnextdir, 4))
             {
                 TIFFErrorExtR(tif, module, "Error fetching directory link");
@@ -3248,7 +3360,7 @@
                 TIFFSwabLong(&nextnextdir);
             if (nextnextdir == 0)
             {
-                (void)TIFFSeekFile(tif, nextdir + 2 + dircount * 12, SEEK_SET);
+                (void)TIFFSeekFile(tif, nextdir + 2 + dircount * 12U, SEEK_SET);
                 if (!WriteOK(tif, &m, 4))
                 {
                     TIFFErrorExtR(tif, module, "Error writing directory link");
@@ -3306,9 +3418,15 @@
         while (1)
         {
             uint64_t dircount64;
-            uint16_t dircount;
             uint64_t nextnextdir;
 
+            /* Update IDF loop list and check for IFD loop. */
+            if (!_TIFFCheckDirNumberAndOffset(tif, ndir - 1, nextdir))
+            {
+                TIFFErrorExtR(tif, module, "Error IFD loop detected");
+                return 0; /* bad offset (IFD looping or more than
+                             TIFF_MAX_DIR_COUNT IFDs) */
+            }
             if (!SeekOK(tif, nextdir) || !ReadOK(tif, &dircount64, 8))
             {
                 TIFFErrorExtR(tif, module, "Error fetching directory count");
@@ -3323,8 +3441,7 @@
                               "likely corrupt TIFF");
                 return (0);
             }
-            dircount = (uint16_t)dircount64;
-            (void)TIFFSeekFile(tif, nextdir + 8 + dircount * 20, SEEK_SET);
+            (void)TIFFSeekFile(tif, nextdir + 8 + dircount64 * 20, SEEK_SET);
             if (!ReadOK(tif, &nextnextdir, 8))
             {
                 TIFFErrorExtR(tif, module, "Error fetching directory link");
@@ -3334,7 +3451,8 @@
                 TIFFSwabLong8(&nextnextdir);
             if (nextnextdir == 0)
             {
-                (void)TIFFSeekFile(tif, nextdir + 8 + dircount * 20, SEEK_SET);
+                (void)TIFFSeekFile(tif, nextdir + 8 + dircount64 * 20,
+                                   SEEK_SET);
                 if (!WriteOK(tif, &m, 8))
                 {
                     TIFFErrorExtR(tif, module, "Error writing directory link");
@@ -3475,7 +3593,7 @@
         if (entry_tag == tag)
             break;
 
-        read_offset += dirsize;
+        read_offset += (uint64_t)dirsize;
     }
 
     if (entry_tag != tag)
@@ -3584,13 +3702,13 @@
         if (in_datatype == TIFF_LONG8 &&
             (entry_type == TIFF_SHORT || entry_type == TIFF_LONG ||
              entry_type == TIFF_LONG8))
-            datatype = entry_type;
+            datatype = (TIFFDataType)entry_type;
         else if (in_datatype == TIFF_SLONG8 &&
                  (entry_type == TIFF_SLONG || entry_type == TIFF_SLONG8))
-            datatype = entry_type;
+            datatype = (TIFFDataType)entry_type;
         else if (in_datatype == TIFF_IFD8 &&
                  (entry_type == TIFF_IFD || entry_type == TIFF_IFD8))
-            datatype = entry_type;
+            datatype = (TIFFDataType)entry_type;
         else
             datatype = in_datatype;
     }
@@ -3605,7 +3723,8 @@
         return 0;
 
     if (datatype == in_datatype)
-        memcpy(buf_to_write, data, count * TIFFDataWidth(datatype));
+        memcpy(buf_to_write, data,
+               (size_t)count * (size_t)TIFFDataWidth(datatype));
     else if (datatype == TIFF_SLONG && in_datatype == TIFF_SLONG8)
     {
         tmsize_t i;
@@ -3698,8 +3817,8 @@
         tif->tif_dir.td_stripoffset_entry.tdir_type == 0 &&
         tif->tif_dir.td_stripoffset_entry.tdir_offset.toff_long8 == 0)
     {
-        tif->tif_dir.td_stripoffset_entry.tdir_type = datatype;
-        tif->tif_dir.td_stripoffset_entry.tdir_count = count;
+        tif->tif_dir.td_stripoffset_entry.tdir_type = (uint16_t)datatype;
+        tif->tif_dir.td_stripoffset_entry.tdir_count = (uint64_t)count;
     }
     else if ((tag == TIFFTAG_TILEBYTECOUNTS ||
               tag == TIFFTAG_STRIPBYTECOUNTS) &&
@@ -3707,8 +3826,8 @@
              tif->tif_dir.td_stripbytecount_entry.tdir_type == 0 &&
              tif->tif_dir.td_stripbytecount_entry.tdir_offset.toff_long8 == 0)
     {
-        tif->tif_dir.td_stripbytecount_entry.tdir_type = datatype;
-        tif->tif_dir.td_stripbytecount_entry.tdir_count = count;
+        tif->tif_dir.td_stripbytecount_entry.tdir_type = (uint16_t)datatype;
+        tif->tif_dir.td_stripbytecount_entry.tdir_count = (uint64_t)count;
     }
 
     /* -------------------------------------------------------------------- */
@@ -3756,13 +3875,14 @@
         if (count * TIFFDataWidth(datatype) == 4)
         {
             uint32_t value;
-            memcpy(&value, buf_to_write, count * TIFFDataWidth(datatype));
+            memcpy(&value, buf_to_write,
+                   (size_t)count * (size_t)TIFFDataWidth(datatype));
             entry_offset = value;
         }
         else
         {
             memcpy(&entry_offset, buf_to_write,
-                   count * TIFFDataWidth(datatype));
+                   (size_t)count * (size_t)TIFFDataWidth(datatype));
         }
     }
 
@@ -3772,7 +3892,7 @@
     /* -------------------------------------------------------------------- */
     /*      Adjust the directory entry.                                     */
     /* -------------------------------------------------------------------- */
-    entry_type = datatype;
+    entry_type = (uint16_t)datatype;
     entry_count = (uint64_t)count;
     memcpy(direntry_raw + 2, &entry_type, sizeof(uint16_t));
     if (tif->tif_flags & TIFF_SWAB)
diff --git a/third_party/libtiff/tif_dumpmode.c b/third_party/libtiff/tif_dumpmode.c
index 267d5d2..4e3133f 100644
--- a/third_party/libtiff/tif_dumpmode.c
+++ b/third_party/libtiff/tif_dumpmode.c
@@ -80,7 +80,7 @@
                       "Not enough data for scanline %" PRIu32
                       ", expected a request for at most %" TIFF_SSIZE_FORMAT
                       " bytes, got a request for %" TIFF_SSIZE_FORMAT " bytes",
-                      tif->tif_row, tif->tif_rawcc, cc);
+                      tif->tif_dir.td_row, tif->tif_rawcc, cc);
         return (0);
     }
     /*
@@ -99,8 +99,23 @@
  */
 static int DumpModeSeek(TIFF *tif, uint32_t nrows)
 {
-    tif->tif_rawcp += nrows * tif->tif_scanlinesize;
-    tif->tif_rawcc -= nrows * tif->tif_scanlinesize;
+    tmsize_t seek_size;
+    if (nrows > 0 &&
+        tif->tif_dir.td_scanlinesize > (tmsize_t)(TIFF_TMSIZE_T_MAX / nrows))
+    {
+        TIFFErrorExtR(tif, "DumpModeSeek",
+                      "Integer overflow computing seek size");
+        return (0);
+    }
+    seek_size = (tmsize_t)nrows * tif->tif_dir.td_scanlinesize;
+    if (seek_size > tif->tif_rawcc)
+    {
+        TIFFErrorExtR(tif, "DumpModeSeek",
+                      "Seek beyond end of raw data buffer");
+        return (0);
+    }
+    tif->tif_rawcp += seek_size;
+    tif->tif_rawcc -= seek_size;
     return (1);
 }
 
diff --git a/third_party/libtiff/tif_fax3.c b/third_party/libtiff/tif_fax3.c
index 34e1c78..06b9508 100644
--- a/third_party/libtiff/tif_fax3.c
+++ b/third_party/libtiff/tif_fax3.c
@@ -123,7 +123,7 @@
     static const char module[] = mod;                                          \
     Fax3CodecState *sp = DecoderState(tif);                                    \
     int a0;                                   /* reference element */          \
-    int lastx = sp->b.rowpixels;              /* last element in row */        \
+    int lastx = (int)sp->b.rowpixels;         /* last element in row */        \
     uint32_t BitAcc;                          /* bit accumulator */            \
     int BitsAvail;                            /* # valid bits in BitAcc */     \
     int RunLength;                            /* length of current run */      \
@@ -209,61 +209,68 @@
 static void Fax3Unexpected(const char *module, TIFF *tif, uint32_t line,
                            uint32_t a0)
 {
-    TIFFErrorExtR(tif, module,
-                  "Bad code word at line %" PRIu32 " of %s %" PRIu32
-                  " (x %" PRIu32 ")",
-                  line, isTiled(tif) ? "tile" : "strip",
-                  (isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip), a0);
+    TIFFErrorExtR(
+        tif, module,
+        "Bad code word at line %" PRIu32 " of %s %" PRIu32 " (x %" PRIu32 ")",
+        line, isTiled(tif) ? "tile" : "strip",
+        (isTiled(tif) ? tif->tif_dir.td_curtile : tif->tif_dir.td_curstrip),
+        a0);
 }
 #define unexpected(table, a0)                                                  \
     do                                                                         \
     {                                                                          \
-        Fax3Unexpected(module, tif, sp->line, a0);                             \
+        Fax3Unexpected(module, tif, (uint32_t)sp->line, (uint32_t)(a0));       \
         ++sp->unexpectedReachedCount;                                          \
     } while (0)
 
 static void Fax3Extension(const char *module, TIFF *tif, uint32_t line,
                           uint32_t a0)
 {
-    TIFFErrorExtR(tif, module,
-                  "Uncompressed data (not supported) at line %" PRIu32
-                  " of %s %" PRIu32 " (x %" PRIu32 ")",
-                  line, isTiled(tif) ? "tile" : "strip",
-                  (isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip), a0);
+    TIFFErrorExtR(
+        tif, module,
+        "Uncompressed data (not supported) at line %" PRIu32 " of %s %" PRIu32
+        " (x %" PRIu32 ")",
+        line, isTiled(tif) ? "tile" : "strip",
+        (isTiled(tif) ? tif->tif_dir.td_curtile : tif->tif_dir.td_curstrip),
+        a0);
 }
-#define extension(a0) Fax3Extension(module, tif, sp->line, a0)
+#define extension(a0)                                                          \
+    Fax3Extension(module, tif, (uint32_t)sp->line, (uint32_t)(a0))
 
 static void Fax3BadLength(const char *module, TIFF *tif, uint32_t line,
                           uint32_t a0, uint32_t lastx)
 {
-    TIFFWarningExtR(tif, module,
-                    "%s at line %" PRIu32 " of %s %" PRIu32 " (got %" PRIu32
-                    ", expected %" PRIu32 ")",
-                    a0 < lastx ? "Premature EOL" : "Line length mismatch", line,
-                    isTiled(tif) ? "tile" : "strip",
-                    (isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip), a0,
-                    lastx);
+    TIFFWarningExtR(
+        tif, module,
+        "%s at line %" PRIu32 " of %s %" PRIu32 " (got %" PRIu32
+        ", expected %" PRIu32 ")",
+        a0 < lastx ? "Premature EOL" : "Line length mismatch", line,
+        isTiled(tif) ? "tile" : "strip",
+        (isTiled(tif) ? tif->tif_dir.td_curtile : tif->tif_dir.td_curstrip), a0,
+        lastx);
 }
 #define badlength(a0, lastx)                                                   \
     do                                                                         \
     {                                                                          \
-        Fax3BadLength(module, tif, sp->line, a0, lastx);                       \
+        Fax3BadLength(module, tif, (uint32_t)sp->line, (uint32_t)(a0),         \
+                      (uint32_t)(lastx));                                      \
         ++sp->eolReachedCount;                                                 \
     } while (0)
 
 static void Fax3PrematureEOF(const char *module, TIFF *tif, uint32_t line,
                              uint32_t a0)
 {
-    TIFFWarningExtR(tif, module,
-                    "Premature EOF at line %" PRIu32 " of %s %" PRIu32
-                    " (x %" PRIu32 ")",
-                    line, isTiled(tif) ? "tile" : "strip",
-                    (isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip), a0);
+    TIFFWarningExtR(
+        tif, module,
+        "Premature EOF at line %" PRIu32 " of %s %" PRIu32 " (x %" PRIu32 ")",
+        line, isTiled(tif) ? "tile" : "strip",
+        (isTiled(tif) ? tif->tif_dir.td_curtile : tif->tif_dir.td_curstrip),
+        a0);
 }
 #define prematureEOF(a0)                                                       \
     do                                                                         \
     {                                                                          \
-        Fax3PrematureEOF(module, tif, sp->line, a0);                           \
+        Fax3PrematureEOF(module, tif, (uint32_t)sp->line, (uint32_t)(a0));     \
         ++sp->eofReachedCount;                                                 \
     } while (0)
 
@@ -275,16 +282,15 @@
         "Try to decode (read) fax Group 3 data without EOL at line %" PRIu32
         " of %s %" PRIu32 " (x %" PRIu32 "). Please check result",
         line, isTiled(tif) ? "tile" : "strip",
-        (isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip), a0);
+        (isTiled(tif) ? tif->tif_dir.td_curtile : tif->tif_dir.td_curstrip),
+        a0);
 }
 #define tryG3WithoutEOL(a0)                                                    \
     do                                                                         \
     {                                                                          \
-        Fax3TryG3WithoutEOL(module, tif, sp->line, a0);                        \
+        Fax3TryG3WithoutEOL(module, tif, (uint32_t)sp->line, (uint32_t)(a0));  \
     } while (0)
 
-#define Nop
-
 static int CheckReachedCounters(TIFF *tif, const char *module,
                                 Fax3CodecState *sp)
 {
@@ -344,12 +350,12 @@
         pa = thisrun;
 #ifdef FAX3_DEBUG
         printf("\nBitAcc=%08" PRIX32 ", BitsAvail = %d\n", BitAcc, BitsAvail);
-        printf("-------------------- %" PRIu32 "\n", tif->tif_row);
+        printf("-------------------- %" PRIu32 "\n", tif->tif_dir.td_row);
         fflush(stdout);
 #endif
         SYNC_EOL(EOF1D, RETRY_WITHOUT_EOL_1D);
         EXPAND1D(EOF1Da);
-        (*sp->fill)(buf, thisrun, pa, lastx);
+        (*sp->fill)(buf, thisrun, pa, (uint32_t)lastx);
         buf += sp->b.rowbytes;
         occ -= sp->b.rowbytes;
         sp->line++;
@@ -357,7 +363,7 @@
     EOF1D: /* premature EOF */
         CLEANUP_RUNS();
     EOF1Da: /* premature EOF */
-        (*sp->fill)(buf, thisrun, pa, lastx);
+        (*sp->fill)(buf, thisrun, pa, (uint32_t)lastx);
         UNCACHE_STATE(tif, sp);
         return (-1);
     }
@@ -404,16 +410,16 @@
         ClrBits(1);
 #ifdef FAX3_DEBUG
         printf(" %s\n-------------------- %" PRIu32 "\n", is1D ? "1D" : "2D",
-               tif->tif_row);
+               tif->tif_dir.td_row);
         fflush(stdout);
 #endif
         pb = sp->refruns;
-        b1 = *pb++;
+        b1 = (int)*pb++;
         if (is1D)
             EXPAND1D(EOF2Da);
         else
             EXPAND2D(EOF2Da);
-        (*sp->fill)(buf, thisrun, pa, lastx);
+        (*sp->fill)(buf, thisrun, pa, (uint32_t)lastx);
         if (pa < thisrun + sp->nruns)
         {
             SETVALUE(0); /* imaginary change for reference */
@@ -426,7 +432,7 @@
     EOF2D: /* premature EOF */
         CLEANUP_RUNS();
     EOF2Da: /* premature EOF */
-        (*sp->fill)(buf, thisrun, pa, lastx);
+        (*sp->fill)(buf, thisrun, pa, (uint32_t)lastx);
         UNCACHE_STATE(tif, sp);
         return (-1);
     }
@@ -479,12 +485,12 @@
             {
                 if (bx)
                 { /* align to byte boundary */
-                    *cp++ &= 0xff << (8 - bx);
+                    *cp++ &= (unsigned char)(0xff << (8 - bx));
                     run -= 8 - bx;
                 }
-                if ((n = run >> 3) != 0)
+                if ((n = (int32_t)(run >> 3)) != 0)
                 { /* multiple bytes to fill */
-                    if ((n / sizeof(int64_t)) > 1)
+                    if (((size_t)n / sizeof(int64_t)) > 1)
                     {
                         /*
                          * Align to int64_tword boundary and fill.
@@ -492,8 +498,8 @@
                         for (; n && !isAligned(cp, int64_t); n--)
                             *cp++ = 0x00;
                         lp = (int64_t *)cp;
-                        nw = (int32_t)(n / sizeof(int64_t));
-                        n -= nw * sizeof(int64_t);
+                        nw = (int32_t)((size_t)n / sizeof(int64_t));
+                        n -= (int32_t)((size_t)nw * sizeof(int64_t));
                         do
                         {
                             *lp++ = 0L;
@@ -504,10 +510,10 @@
                     run &= 7;
                 }
                 if (run)
-                    cp[0] &= 0xff >> run;
+                    cp[0] &= (unsigned char)(0xff >> run);
             }
             else
-                cp[0] &= ~(_fillmasks[run] >> bx);
+                cp[0] &= (unsigned char)~(_fillmasks[run] >> bx);
             x += runs[0];
         }
         run = runs[1];
@@ -521,12 +527,12 @@
             {
                 if (bx)
                 { /* align to byte boundary */
-                    *cp++ |= 0xff >> bx;
+                    *cp++ |= (unsigned char)(0xff >> bx);
                     run -= 8 - bx;
                 }
-                if ((n = run >> 3) != 0)
+                if ((n = (int32_t)(run >> 3)) != 0)
                 { /* multiple bytes to fill */
-                    if ((n / sizeof(int64_t)) > 1)
+                    if (((size_t)n / sizeof(int64_t)) > 1)
                     {
                         /*
                          * Align to int64_t boundary and fill.
@@ -534,8 +540,8 @@
                         for (; n && !isAligned(cp, int64_t); n--)
                             *cp++ = 0xff;
                         lp = (int64_t *)cp;
-                        nw = (int32_t)(n / sizeof(int64_t));
-                        n -= nw * sizeof(int64_t);
+                        nw = (int32_t)((size_t)n / sizeof(int64_t));
+                        n -= (int32_t)((size_t)nw * sizeof(int64_t));
                         do
                         {
                             *lp++ = -1L;
@@ -550,7 +556,7 @@
                     cp[0] = (unsigned char)((cp[0] | (0xff00 >> run)) & 0xff);
             }
             else
-                cp[0] |= _fillmasks[run] >> bx;
+                cp[0] |= (unsigned char)(_fillmasks[run] >> bx);
             x += runs[1];
         }
     }
@@ -726,12 +732,13 @@
     {                                                                          \
         while (length > bit)                                                   \
         {                                                                      \
-            data |= bits >> (length - bit);                                    \
+            data |= (int)((unsigned int)bits >> (length - bit));               \
             length -= bit;                                                     \
             _FlushBits(tif);                                                   \
         }                                                                      \
         assert(length < 9);                                                    \
-        data |= (bits & _msbmask[length]) << (bit - length);                   \
+        data |= (int)(((unsigned int)bits & (unsigned int)_msbmask[length])    \
+                      << (unsigned int)(bit - length));                        \
         bit -= length;                                                         \
         if (bit == 0)                                                          \
             _FlushBits(tif);                                                   \
@@ -745,13 +752,13 @@
 static int Fax3PutBits(TIFF *tif, unsigned int bits, unsigned int length)
 {
     Fax3CodecState *sp = EncoderState(tif);
-    unsigned int bit = sp->bit;
-    int data = sp->data;
+    unsigned int bit = (unsigned int)sp->bit;
+    int data = (int)sp->data;
 
     _PutBits(tif, bits, length);
 
-    sp->data = data;
-    sp->bit = bit;
+    sp->data = (uint32_t)data;
+    sp->bit = (int)bit;
     return 1;
 }
 
@@ -782,8 +789,8 @@
 static int putspan(TIFF *tif, int32_t span, const tableentry *tab)
 {
     Fax3CodecState *sp = EncoderState(tif);
-    unsigned int bit = sp->bit;
-    int data = sp->data;
+    unsigned int bit = (unsigned int)sp->bit;
+    int data = (int)sp->data;
     unsigned int code, length;
 
     while (span >= 2624)
@@ -816,8 +823,8 @@
 #endif
     _PutBits(tif, code, length);
 
-    sp->data = data;
-    sp->bit = bit;
+    sp->data = (uint32_t)data;
+    sp->bit = (int)bit;
 
     return 1;
 }
@@ -831,8 +838,8 @@
 static int Fax3PutEOL(TIFF *tif)
 {
     Fax3CodecState *sp = EncoderState(tif);
-    unsigned int bit = sp->bit;
-    int data = sp->data;
+    unsigned int bit = (unsigned int)sp->bit;
+    int data = (int)sp->data;
     unsigned int code, length, tparm;
 
     if (sp->b.groupoptions & GROUP3OPT_FILLBITS)
@@ -849,7 +856,7 @@
                 align = sp->bit + (8 - align);
             else
                 align = sp->bit - align;
-            tparm = align;
+            tparm = (unsigned int)align;
             _PutBits(tif, 0, tparm);
         }
     }
@@ -862,8 +869,8 @@
     }
     _PutBits(tif, code, length);
 
-    sp->data = data;
-    sp->bit = bit;
+    sp->data = (uint32_t)data;
+    sp->bit = (int)bit;
 
     return 1;
 }
@@ -991,10 +998,10 @@
             bp++;
         }
         lp = (int64_t *)bp;
-        while ((bits >= (int32_t)(8 * sizeof(int64_t))) && (0 == *lp))
+        while ((bits >= (int32_t)(size_t)(8 * sizeof(int64_t))) && (0 == *lp))
         {
-            span += 8 * sizeof(int64_t);
-            bits -= 8 * sizeof(int64_t);
+            span += (int32_t)(size_t)(8 * sizeof(int64_t));
+            bits -= (int32_t)(size_t)(8 * sizeof(int64_t));
             lp++;
         }
         bp = (unsigned char *)lp;
@@ -1059,11 +1066,11 @@
             bp++;
         }
         lp = (int64_t *)bp;
-        while ((bits >= (int32_t)(8 * sizeof(int64_t))) &&
+        while ((bits >= (int32_t)(size_t)(8 * sizeof(int64_t))) &&
                (~((uint64_t)0) == (uint64_t)*lp))
         {
-            span += 8 * sizeof(int64_t);
-            bits -= 8 * sizeof(int64_t);
+            span += (int32_t)(size_t)(8 * sizeof(int64_t));
+            bits -= (int32_t)(size_t)(8 * sizeof(int64_t));
             lp++;
         }
         bp = (unsigned char *)lp;
@@ -1118,16 +1125,16 @@
 
     for (;;)
     {
-        span = find0span(bp, bs, bits); /* white span */
+        span = find0span(bp, (int32_t)bs, (int32_t)bits); /* white span */
         if (!putspan(tif, span, TIFFFaxWhiteCodes))
             return 0;
-        bs += span;
+        bs += (uint32_t)span;
         if (bs >= bits)
             break;
-        span = find1span(bp, bs, bits); /* black span */
+        span = find1span(bp, (int32_t)bs, (int32_t)bits); /* black span */
         if (!putspan(tif, span, TIFFFaxBlackCodes))
             return 0;
-        bs += span;
+        bs += (uint32_t)span;
         if (bs >= bits)
             break;
     }
@@ -1161,15 +1168,20 @@
 static int Fax3Encode2DRow(TIFF *tif, unsigned char *bp, unsigned char *rp,
                            uint32_t bits)
 {
-#define PIXEL(buf, ix) ((((buf)[(ix) >> 3]) >> (7 - ((ix)&7))) & 1)
+#define PIXEL(buf, ix) ((((buf)[(ix) >> 3]) >> (7 - ((ix) & 7))) & 1)
     uint32_t a0 = 0;
-    uint32_t a1 = (PIXEL(bp, 0) != 0 ? 0 : finddiff(bp, 0, bits, 0));
-    uint32_t b1 = (PIXEL(rp, 0) != 0 ? 0 : finddiff(rp, 0, bits, 0));
+    uint32_t a1 = (PIXEL(bp, 0) != 0
+                       ? 0
+                       : (uint32_t)finddiff(bp, (int32_t)0, (int32_t)bits, 0));
+    uint32_t b1 = (PIXEL(rp, 0) != 0
+                       ? 0
+                       : (uint32_t)finddiff(rp, (int32_t)0, (int32_t)bits, 0));
     uint32_t a2, b2;
 
     for (;;)
     {
-        b2 = finddiff2(rp, b1, bits, PIXEL(rp, b1));
+        b2 = (uint32_t)finddiff2(rp, (int32_t)b1, (int32_t)bits,
+                                 (int32_t)PIXEL(rp, b1));
         if (b2 >= a1)
         {
             /* Naive computation triggers
@@ -1182,21 +1194,22 @@
                                                      : 0x7FFFFFFF;
             if (!(-3 <= d && d <= 3))
             { /* horizontal mode */
-                a2 = finddiff2(bp, a1, bits, PIXEL(bp, a1));
+                a2 = (uint32_t)finddiff2(bp, (int32_t)a1, (int32_t)bits,
+                                         (int32_t)PIXEL(bp, a1));
                 if (!putcode(tif, &horizcode))
                     return 0;
                 if (a0 + a1 == 0 || PIXEL(bp, a0) == 0)
                 {
-                    if (!putspan(tif, a1 - a0, TIFFFaxWhiteCodes))
+                    if (!putspan(tif, (int32_t)(a1 - a0), TIFFFaxWhiteCodes))
                         return 0;
-                    if (!putspan(tif, a2 - a1, TIFFFaxBlackCodes))
+                    if (!putspan(tif, (int32_t)(a2 - a1), TIFFFaxBlackCodes))
                         return 0;
                 }
                 else
                 {
-                    if (!putspan(tif, a1 - a0, TIFFFaxBlackCodes))
+                    if (!putspan(tif, (int32_t)(a1 - a0), TIFFFaxBlackCodes))
                         return 0;
-                    if (!putspan(tif, a2 - a1, TIFFFaxWhiteCodes))
+                    if (!putspan(tif, (int32_t)(a2 - a1), TIFFFaxWhiteCodes))
                         return 0;
                 }
                 a0 = a2;
@@ -1216,9 +1229,12 @@
         }
         if (a0 >= bits)
             break;
-        a1 = finddiff(bp, a0, bits, PIXEL(bp, a0));
-        b1 = finddiff(rp, a0, bits, !PIXEL(bp, a0));
-        b1 = finddiff(rp, b1, bits, PIXEL(bp, a0));
+        a1 = (uint32_t)finddiff(bp, (int32_t)a0, (int32_t)bits,
+                                (int32_t)PIXEL(bp, a0));
+        b1 = (uint32_t)finddiff(rp, (int32_t)a0, (int32_t)bits,
+                                (int32_t)!PIXEL(bp, a0));
+        b1 = (uint32_t)finddiff(rp, (int32_t)b1, (int32_t)bits,
+                                (int32_t)PIXEL(bp, a0));
     }
     return (1);
 #undef PIXEL
@@ -1487,6 +1503,8 @@
             case CLEANFAXDATA_UNCLEAN:
                 fprintf(fd, " uncorrected errors");
                 break;
+            default:
+                break;
         }
         fprintf(fd, " (%" PRIu16 " = 0x%" PRIx16 ")\n", sp->cleanfaxdata,
                 sp->cleanfaxdata);
@@ -1500,6 +1518,22 @@
         (*sp->printdir)(tif, fd, flags);
 }
 
+static uint64_t Fax3GetMaxCompressionRatio(TIFF *tif)
+{
+    (void)tif;
+
+    /* See README_for_libtiff_developpers.md for raw data used to estimate
+     * the maximum compression rate. */
+
+    /* 1024x1024: 36 */
+    /* 4096x4096: 100 */
+    /* 16383x16383: 163 */
+    /* 65536x65536: 200 */
+    /* 200000x200000: 208 */
+
+    return 250;
+}
+
 static int InitCCITTFax3(TIFF *tif)
 {
     static const char module[] = "InitCCITTFax3";
@@ -1564,6 +1598,7 @@
     tif->tif_encodetile = Fax3Encode;
     tif->tif_close = Fax3Close;
     tif->tif_cleanup = Fax3Cleanup;
+    tif->tif_getmaxcompressionratio = Fax3GetMaxCompressionRatio;
 
     return (1);
 }
@@ -1626,10 +1661,10 @@
         RunLength = 0;
         pa = thisrun = sp->curruns;
         pb = sp->refruns;
-        b1 = *pb++;
+        b1 = (int)*pb++;
 #ifdef FAX3_DEBUG
         printf("\nBitAcc=%08" PRIX32 ", BitsAvail = %d\n", BitAcc, BitsAvail);
-        printf("-------------------- %d\n", tif->tif_row);
+        printf("-------------------- %d\n", tif->tif_dir.td_row);
         fflush(stdout);
 #endif
         EXPAND2D(EOFG4);
@@ -1643,7 +1678,7 @@
                           occ, lastx);
             return -1;
         }
-        (*sp->fill)(buf, thisrun, pa, lastx);
+        (*sp->fill)(buf, thisrun, pa, (uint32_t)lastx);
         SETVALUE(0); /* imaginary change for reference */
         SWAP(uint32_t *, sp->curruns, sp->refruns);
         buf += sp->b.rowbytes;
@@ -1666,7 +1701,7 @@
                           occ, lastx);
             return -1;
         }
-        (*sp->fill)(buf, thisrun, pa, lastx);
+        (*sp->fill)(buf, thisrun, pa, (uint32_t)lastx);
         UNCACHE_STATE(tif, sp);
         return (sp->line != start
                     ? 1
@@ -1713,6 +1748,16 @@
     return (1);
 }
 
+static uint64_t Fax4GetMaxCompressionRatio(TIFF *tif)
+{
+    /* FAX4 can compress up to almost one byte per line, so the compression
+     * ratio can be up to the tile/strip width.
+     * See README_for_libtiff_developpers.md for raw data
+     */
+    return isTiled(tif) ? tif->tif_dir.td_tilewidth
+                        : tif->tif_dir.td_imagewidth;
+}
+
 int TIFFInitCCITTFax4(TIFF *tif, int scheme)
 {
     (void)scheme;
@@ -1735,6 +1780,7 @@
         tif->tif_encodestrip = Fax4Encode;
         tif->tif_encodetile = Fax4Encode;
         tif->tif_postencode = Fax4PostEncode;
+        tif->tif_getmaxcompressionratio = Fax4GetMaxCompressionRatio;
         /*
          * Suppress RTC at the end of each strip.
          */
@@ -1773,11 +1819,11 @@
         pa = thisrun;
 #ifdef FAX3_DEBUG
         printf("\nBitAcc=%08" PRIX32 ", BitsAvail = %d\n", BitAcc, BitsAvail);
-        printf("-------------------- %" PRIu32 "\n", tif->tif_row);
+        printf("-------------------- %" PRIu32 "\n", tif->tif_dir.td_row);
         fflush(stdout);
 #endif
         EXPAND1D(EOFRLE);
-        (*sp->fill)(buf, thisrun, pa, lastx);
+        (*sp->fill)(buf, thisrun, pa, (uint32_t)lastx);
         /*
          * Cleanup at the end of the row.
          */
@@ -1798,7 +1844,7 @@
         sp->line++;
         continue;
     EOFRLE: /* premature EOF */
-        (*sp->fill)(buf, thisrun, pa, lastx);
+        (*sp->fill)(buf, thisrun, pa, (uint32_t)lastx);
         UNCACHE_STATE(tif, sp);
         return (-1);
     }
@@ -1806,6 +1852,21 @@
     return (1);
 }
 
+static uint64_t Fax3RLEGetMaxCompressionRatio(TIFF *tif)
+{
+    (void)tif;
+    /* See README_for_libtiff_developpers.md for raw data used to estimate
+     * the maximum compression rate. */
+
+    /* 1024x1024: 43 */
+    /* 4096x4096: 128 */
+    /* 16383x16383: 171 */
+    /* 65536x65536: 205 */
+    /* 200000x200000: 211 */
+
+    return 250;
+}
+
 int TIFFInitCCITTRLE(TIFF *tif, int scheme)
 {
     (void)scheme;
@@ -1814,6 +1875,7 @@
         tif->tif_decoderow = Fax3DecodeRLE;
         tif->tif_decodestrip = Fax3DecodeRLE;
         tif->tif_decodetile = Fax3DecodeRLE;
+        tif->tif_getmaxcompressionratio = Fax3RLEGetMaxCompressionRatio;
         /*
          * Suppress RTC+EOLs when encoding and byte-align data.
          */
@@ -1832,6 +1894,7 @@
         tif->tif_decoderow = Fax3DecodeRLE;
         tif->tif_decodestrip = Fax3DecodeRLE;
         tif->tif_decodetile = Fax3DecodeRLE;
+        tif->tif_getmaxcompressionratio = Fax3RLEGetMaxCompressionRatio;
         /*
          * Suppress RTC+EOLs when encoding and word-align data.
          */
diff --git a/third_party/libtiff/tif_fax3.h b/third_party/libtiff/tif_fax3.h
index c3100ce..60d709c 100644
--- a/third_party/libtiff/tif_fax3.h
+++ b/third_party/libtiff/tif_fax3.h
@@ -267,14 +267,14 @@
     {                                                                          \
         if (pa >= thisrun + sp->nruns)                                         \
         {                                                                      \
-            TIFFErrorExtR(tif, module, "Buffer overflow at line %u of %s %u",  \
+            TIFFErrorExtR(tif, module, "Buffer overflow at line %d of %s %u",  \
                           sp->line, isTiled(tif) ? "tile" : "strip",           \
-                          isTiled(tif) ? tif->tif_curtile                      \
-                                       : tif->tif_curstrip);                   \
+                          isTiled(tif) ? tif->tif_dir.td_curtile               \
+                                       : tif->tif_dir.td_curstrip);            \
             return (-1);                                                       \
         }                                                                      \
-        *pa++ = RunLength + (x);                                               \
-        a0 += (x);                                                             \
+        *pa++ = (uint32_t)((uint32_t)RunLength + (uint32_t)(x));               \
+        a0 += (int)(uint32_t)(x);                                              \
         RunLength = 0;                                                         \
     } while (0)
 #endif
@@ -334,20 +334,20 @@
     {                                                                          \
         if (RunLength)                                                         \
             SETVALUE(0);                                                       \
-        if (a0 != lastx)                                                       \
+        if (a0 != (int)lastx)                                                  \
         {                                                                      \
             badlength(a0, lastx);                                              \
-            while (a0 > lastx && pa > thisrun)                                 \
-                a0 -= *--pa;                                                   \
-            if (a0 < lastx)                                                    \
+            while (a0 > (int)lastx && pa > thisrun)                            \
+                a0 -= (int)*--pa;                                              \
+            if (a0 < (int)lastx)                                               \
             {                                                                  \
                 if (a0 < 0)                                                    \
                     a0 = 0;                                                    \
                 if ((pa - thisrun) & 1)                                        \
                     SETVALUE(0);                                               \
-                SETVALUE(lastx - a0);                                          \
+                SETVALUE((uint32_t)((int)lastx - a0));                         \
             }                                                                  \
-            else if (a0 > lastx)                                               \
+            else if (a0 > (int)lastx)                                          \
             {                                                                  \
                 SETVALUE(lastx);                                               \
                 SETVALUE(0);                                                   \
@@ -385,8 +385,9 @@
                         goto doneWhite1d;                                      \
                     case S_MakeUpW:                                            \
                     case S_MakeUp:                                             \
-                        a0 += TabEnt->Param;                                   \
-                        RunLength += TabEnt->Param;                            \
+                        a0 = (int)((uint32_t)a0 + TabEnt->Param);              \
+                        RunLength =                                            \
+                            (int)((uint32_t)RunLength + TabEnt->Param);        \
                         break;                                                 \
                     default:                                                   \
                         unexpected("WhiteTable", a0);                          \
@@ -394,7 +395,7 @@
                 }                                                              \
             }                                                                  \
         doneWhite1d:                                                           \
-            if (a0 >= lastx)                                                   \
+            if (a0 >= (int)lastx)                                              \
                 goto done1d;                                                   \
             for (;;)                                                           \
             {                                                                  \
@@ -409,8 +410,8 @@
                         goto doneBlack1d;                                      \
                     case S_MakeUpB:                                            \
                     case S_MakeUp:                                             \
-                        a0 += TabEnt->Param;                                   \
-                        RunLength += TabEnt->Param;                            \
+                        a0 += (int)TabEnt->Param;                              \
+                        RunLength += (int)TabEnt->Param;                       \
                         break;                                                 \
                     default:                                                   \
                         unexpected("BlackTable", a0);                          \
@@ -418,7 +419,7 @@
                 }                                                              \
             }                                                                  \
         doneBlack1d:                                                           \
-            if (a0 >= lastx)                                                   \
+            if (a0 >= (int)lastx)                                              \
                 goto done1d;                                                   \
             if (*(pa - 1) == 0 && *(pa - 2) == 0)                              \
                 pa -= 2;                                                       \
@@ -439,17 +440,18 @@
     do                                                                         \
     {                                                                          \
         if (pa != thisrun)                                                     \
-            while (b1 <= a0 && b1 < lastx)                                     \
+            while (b1 <= a0 && b1 < (int)lastx)                                \
             {                                                                  \
                 if (pb + 1 >= sp->refruns + sp->nruns)                         \
                 {                                                              \
-                    TIFFErrorExtR(                                             \
-                        tif, module, "Buffer overflow at line %u of %s %u",    \
-                        sp->line, isTiled(tif) ? "tile" : "strip",             \
-                        isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip);  \
+                    TIFFErrorExtR(tif, module,                                 \
+                                  "Buffer overflow at line %d of %s %u",       \
+                                  sp->line, isTiled(tif) ? "tile" : "strip",   \
+                                  isTiled(tif) ? tif->tif_dir.td_curtile       \
+                                               : tif->tif_dir.td_curstrip);    \
                     return (-1);                                               \
                 }                                                              \
-                b1 += pb[0] + pb[1];                                           \
+                b1 += (int)(pb[0] + pb[1]);                                    \
                 pb += 2;                                                       \
             }                                                                  \
     } while (0)
@@ -460,14 +462,15 @@
 #define EXPAND2D(eoflab)                                                       \
     do                                                                         \
     {                                                                          \
-        while (a0 < lastx)                                                     \
+        while (a0 < (int)lastx)                                                \
         {                                                                      \
             if (pa >= thisrun + sp->nruns)                                     \
             {                                                                  \
-                TIFFErrorExtR(                                                 \
-                    tif, module, "Buffer overflow at line %u of %s %u",        \
-                    sp->line, isTiled(tif) ? "tile" : "strip",                 \
-                    isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip);      \
+                TIFFErrorExtR(tif, module,                                     \
+                              "Buffer overflow at line %d of %s %u", sp->line, \
+                              isTiled(tif) ? "tile" : "strip",                 \
+                              isTiled(tif) ? tif->tif_dir.td_curtile           \
+                                           : tif->tif_dir.td_curstrip);        \
                 return (-1);                                                   \
             }                                                                  \
             LOOKUP8(7, TIFFFaxMainTable, eof2d);                               \
@@ -477,18 +480,19 @@
                     CHECK_b1;                                                  \
                     if (pb + 1 >= sp->refruns + sp->nruns)                     \
                     {                                                          \
-                        TIFFErrorExtR(tif, module,                             \
-                                      "Buffer overflow at line %u of %s %u",   \
-                                      sp->line,                                \
-                                      isTiled(tif) ? "tile" : "strip",         \
-                                      isTiled(tif) ? tif->tif_curtile          \
-                                                   : tif->tif_curstrip);       \
+                        TIFFErrorExtR(                                         \
+                            tif, module,                                       \
+                            "Buffer overflow at line %d of %s %u", sp->line,   \
+                            isTiled(tif) ? "tile" : "strip",                   \
+                            isTiled(tif) ? tif->tif_dir.td_curtile             \
+                                         : tif->tif_dir.td_curstrip);          \
                         return (-1);                                           \
                     }                                                          \
-                    b1 += *pb++;                                               \
-                    RunLength += b1 - a0;                                      \
+                    b1 = b1 + (int)*pb++;                                      \
+                    RunLength =                                                \
+                        (int)((uint32_t)RunLength + (uint32_t)(b1 - a0));      \
                     a0 = b1;                                                   \
-                    b1 += *pb++;                                               \
+                    b1 = b1 + (int)*pb++;                                      \
                     break;                                                     \
                 case S_Horiz:                                                  \
                     if ((pa - thisrun) & 1)                                    \
@@ -503,8 +507,9 @@
                                     goto doneWhite2da;                         \
                                 case S_MakeUpB:                                \
                                 case S_MakeUp:                                 \
-                                    a0 += TabEnt->Param;                       \
-                                    RunLength += TabEnt->Param;                \
+                                    a0 = (int)((uint32_t)a0 + TabEnt->Param);  \
+                                    RunLength = (int)((uint32_t)RunLength +    \
+                                                      TabEnt->Param);          \
                                     break;                                     \
                                 default:                                       \
                                     goto badBlack2d;                           \
@@ -521,8 +526,9 @@
                                     goto doneBlack2da;                         \
                                 case S_MakeUpW:                                \
                                 case S_MakeUp:                                 \
-                                    a0 += TabEnt->Param;                       \
-                                    RunLength += TabEnt->Param;                \
+                                    a0 = (int)((uint32_t)a0 + TabEnt->Param);  \
+                                    RunLength = (int)((uint32_t)RunLength +    \
+                                                      TabEnt->Param);          \
                                     break;                                     \
                                 default:                                       \
                                     goto badWhite2d;                           \
@@ -542,8 +548,9 @@
                                     goto doneWhite2db;                         \
                                 case S_MakeUpW:                                \
                                 case S_MakeUp:                                 \
-                                    a0 += TabEnt->Param;                       \
-                                    RunLength += TabEnt->Param;                \
+                                    a0 = (int)((uint32_t)a0 + TabEnt->Param);  \
+                                    RunLength = (int)((uint32_t)RunLength +    \
+                                                      TabEnt->Param);          \
                                     break;                                     \
                                 default:                                       \
                                     goto badWhite2d;                           \
@@ -560,8 +567,9 @@
                                     goto doneBlack2db;                         \
                                 case S_MakeUpB:                                \
                                 case S_MakeUp:                                 \
-                                    a0 += TabEnt->Param;                       \
-                                    RunLength += TabEnt->Param;                \
+                                    a0 = (int)((uint32_t)a0 + TabEnt->Param);  \
+                                    RunLength = (int)((uint32_t)RunLength +    \
+                                                      TabEnt->Param);          \
                                     break;                                     \
                                 default:                                       \
                                     goto badBlack2d;                           \
@@ -576,47 +584,47 @@
                     SETVALUE(b1 - a0);                                         \
                     if (pb >= sp->refruns + sp->nruns)                         \
                     {                                                          \
-                        TIFFErrorExtR(tif, module,                             \
-                                      "Buffer overflow at line %u of %s %u",   \
-                                      sp->line,                                \
-                                      isTiled(tif) ? "tile" : "strip",         \
-                                      isTiled(tif) ? tif->tif_curtile          \
-                                                   : tif->tif_curstrip);       \
+                        TIFFErrorExtR(                                         \
+                            tif, module,                                       \
+                            "Buffer overflow at line %d of %s %u", sp->line,   \
+                            isTiled(tif) ? "tile" : "strip",                   \
+                            isTiled(tif) ? tif->tif_dir.td_curtile             \
+                                         : tif->tif_dir.td_curstrip);          \
                         return (-1);                                           \
                     }                                                          \
-                    b1 += *pb++;                                               \
+                    b1 = b1 + (int)*pb++;                                      \
                     break;                                                     \
                 case S_VR:                                                     \
                     CHECK_b1;                                                  \
-                    SETVALUE(b1 - a0 + TabEnt->Param);                         \
+                    SETVALUE((int)((uint32_t)(b1 - a0) + TabEnt->Param));      \
                     if (pb >= sp->refruns + sp->nruns)                         \
                     {                                                          \
-                        TIFFErrorExtR(tif, module,                             \
-                                      "Buffer overflow at line %u of %s %u",   \
-                                      sp->line,                                \
-                                      isTiled(tif) ? "tile" : "strip",         \
-                                      isTiled(tif) ? tif->tif_curtile          \
-                                                   : tif->tif_curstrip);       \
+                        TIFFErrorExtR(                                         \
+                            tif, module,                                       \
+                            "Buffer overflow at line %d of %s %u", sp->line,   \
+                            isTiled(tif) ? "tile" : "strip",                   \
+                            isTiled(tif) ? tif->tif_dir.td_curtile             \
+                                         : tif->tif_dir.td_curstrip);          \
                         return (-1);                                           \
                     }                                                          \
-                    b1 += *pb++;                                               \
+                    b1 = b1 + (int)*pb++;                                      \
                     break;                                                     \
                 case S_VL:                                                     \
                     CHECK_b1;                                                  \
-                    if (b1 < (int)(a0 + TabEnt->Param))                        \
+                    if (b1 < (int)((uint32_t)a0 + TabEnt->Param))              \
                     {                                                          \
                         unexpected("VL", a0);                                  \
                         goto eol2d;                                            \
                     }                                                          \
-                    SETVALUE(b1 - a0 - TabEnt->Param);                         \
-                    b1 -= *--pb;                                               \
+                    SETVALUE((int)((uint32_t)(b1 - a0) - TabEnt->Param));      \
+                    b1 = b1 - (int)*--pb;                                      \
                     break;                                                     \
                 case S_Ext:                                                    \
-                    *pa++ = lastx - a0;                                        \
+                    *pa++ = (uint32_t)((int)lastx - a0);                       \
                     extension(a0);                                             \
                     goto eol2d;                                                \
                 case S_EOL:                                                    \
-                    *pa++ = lastx - a0;                                        \
+                    *pa++ = (uint32_t)((int)lastx - a0);                       \
                     NeedBits8(4, eof2d);                                       \
                     if (GetBits(4))                                            \
                         unexpected("EOL", a0);                                 \
diff --git a/third_party/libtiff/tif_getimage.c b/third_party/libtiff/tif_getimage.c
index ee128c0..316284d 100644
--- a/third_party/libtiff/tif_getimage.c
+++ b/third_party/libtiff/tif_getimage.c
@@ -29,6 +29,7 @@
  */
 #include "tiffiop.h"
 #include <limits.h>
+#include <math.h>
 #include <stdio.h>
 
 static int gtTileContig(TIFFRGBAImage *, uint32_t *, uint32_t, uint32_t);
@@ -57,21 +58,21 @@
 
 static const TIFFDisplay display_sRGB = {
     {/* XYZ -> luminance matrix */
-     {3.2410F, -1.5374F, -0.4986F},
-     {-0.9692F, 1.8760F, 0.0416F},
-     {0.0556F, -0.2040F, 1.0570F}},
-    100.0F,
-    100.0F,
-    100.0F, /* Light o/p for reference white */
+     {3.2410f, -1.5374f, -0.4986f},
+     {-0.9692f, 1.8760f, 0.0416f},
+     {0.0556f, -0.2040f, 1.0570f}},
+    100.0f,
+    100.0f,
+    100.0f, /* Light o/p for reference white */
     255,
     255,
     255, /* Pixel values for ref. white */
-    1.0F,
-    1.0F,
-    1.0F, /* Residual light o/p for black pixel */
-    2.4F,
-    2.4F,
-    2.4F, /* Gamma values for the three guns */
+    1.0f,
+    1.0f,
+    1.0f, /* Residual light o/p for black pixel */
+    2.4f,
+    2.4f,
+    2.4f, /* Gamma values for the three guns */
 };
 
 /*
@@ -316,7 +317,7 @@
     uint16_t compress;
     int colorchannels;
     uint16_t *red_orig, *green_orig, *blue_orig;
-    int n_color;
+    uint32_t n_color;
 
     if (!TIFFRGBAImageOK(tif, emsg))
         return 0;
@@ -372,6 +373,8 @@
             case EXTRASAMPLE_UNASSALPHA: /* data is not pre-multiplied */
                 img->alpha = sampleinfo[0];
                 break;
+            default:
+                break;
         }
     }
 
@@ -421,13 +424,13 @@
             }
 
             /* copy the colormaps so we can modify them */
-            n_color = (1U << img->bitspersample);
-            img->redcmap =
-                (uint16_t *)_TIFFmallocExt(tif, sizeof(uint16_t) * n_color);
-            img->greencmap =
-                (uint16_t *)_TIFFmallocExt(tif, sizeof(uint16_t) * n_color);
-            img->bluecmap =
-                (uint16_t *)_TIFFmallocExt(tif, sizeof(uint16_t) * n_color);
+            n_color = (uint32_t)(1U << img->bitspersample);
+            img->redcmap = (uint16_t *)_TIFFmallocExt(
+                tif, (tmsize_t)(sizeof(uint16_t) * (size_t)n_color));
+            img->greencmap = (uint16_t *)_TIFFmallocExt(
+                tif, (tmsize_t)(sizeof(uint16_t) * (size_t)n_color));
+            img->bluecmap = (uint16_t *)_TIFFmallocExt(
+                tif, (tmsize_t)(sizeof(uint16_t) * (size_t)n_color));
             if (!img->redcmap || !img->greencmap || !img->bluecmap)
             {
                 snprintf(emsg, EMSG_BUF_SIZE,
@@ -604,7 +607,7 @@
      * Width is checked in img->get() function individually. */
     if (0 <= img->row_offset && (uint32_t)img->row_offset < img->height)
     {
-        uint32_t hx = img->height - img->row_offset;
+        uint32_t hx = img->height - (uint32_t)img->row_offset;
         if (h > hx)
         {
             /* Adapt parameters to read only available lines and put image
@@ -617,7 +620,7 @@
     {
         TIFFErrorExtR(img->tif, TIFFFileName(img->tif),
                       "Error in TIFFRGBAImageGet: row offset %d exceeds "
-                      "image height %d",
+                      "image height %u",
                       img->row_offset, img->height);
         return 0;
     }
@@ -751,13 +754,13 @@
 
     if (0 <= img->col_offset && (uint32_t)img->col_offset < img->width)
     {
-        wmin = TIFFmin(w, img->width - img->col_offset);
+        wmin = TIFFmin(w, img->width - (uint32_t)img->col_offset);
     }
     else
     {
         TIFFErrorExtR(tif, TIFFFileName(tif),
                       "Error in gtTileContig: column offset %d exceeds "
-                      "image width %d",
+                      "image width %u",
                       img->col_offset, img->width);
         return 0;
     }
@@ -785,7 +788,7 @@
     }
     else
     {
-        if (tw > ((int64_t)INT_MAX + w))
+        if (tw > ((int64_t)INT_MAX + w) || w > ((int64_t)INT_MAX + tw))
         {
             TIFFErrorExtR(tif, TIFFFileName(tif), "%s",
                           "unsupported tile size (too wide)");
@@ -804,9 +807,9 @@
     /*
      *	Leftmost tile is clipped on left side if col_offset > 0.
      */
-    leftmost_fromskew = img->col_offset % tw;
-    leftmost_tw = tw - leftmost_fromskew;
-    int64_t skew_i64 = (int64_t)toskew + leftmost_fromskew;
+    leftmost_fromskew = (int32_t)((uint32_t)img->col_offset % tw);
+    leftmost_tw = (uint32_t)((int32_t)tw - leftmost_fromskew);
+    int64_t skew_i64 = (int64_t)toskew + (int64_t)(int32_t)leftmost_fromskew;
     if (skew_i64 > INT_MAX || skew_i64 < INT_MIN)
     {
         TIFFErrorExtR(tif, TIFFFileName(tif), "%s %" PRId64, "Invalid skew",
@@ -816,34 +819,36 @@
     leftmost_toskew = (int32_t)skew_i64;
     for (row = 0; ret != 0 && row < h; row += nrow)
     {
-        rowstoread = th - (row + img->row_offset) % th;
+        rowstoread = th - ((uint32_t)row + (uint32_t)img->row_offset) % th;
         nrow = (row + rowstoread > h ? h - row : rowstoread);
         fromskew = leftmost_fromskew;
         this_tw = leftmost_tw;
         this_toskew = leftmost_toskew;
         tocol = 0;
-        col = img->col_offset;
+        col = (uint32_t)img->col_offset;
         /* wmin: only write imagewidth if raster is bigger. */
         while (tocol < wmin)
         {
             if (_TIFFReadTileAndAllocBuffer(tif, (void **)&buf, bufsize, col,
-                                            row + img->row_offset, 0,
-                                            0) == (tmsize_t)(-1) &&
+                                            (uint32_t)row +
+                                                (uint32_t)img->row_offset,
+                                            0, 0) == (tmsize_t)(-1) &&
                 (buf == NULL || img->stoponerr))
             {
                 ret = 0;
                 break;
             }
-            pos = ((row + img->row_offset) % th) * TIFFTileRowSize(tif) +
+            pos = (((uint32_t)row + (uint32_t)img->row_offset) % th) *
+                      TIFFTileRowSize(tif) +
                   ((tmsize_t)fromskew * img->samplesperpixel);
             if (tocol + this_tw > wmin)
             {
                 /*
                  * Rightmost tile is clipped on right side.
                  */
-                fromskew = tw - (wmin - tocol);
-                this_tw = tw - fromskew;
-                this_toskew = toskew + fromskew;
+                fromskew = (int32_t)(tw - (wmin - tocol));
+                this_tw = (uint32_t)((int32_t)tw - fromskew);
+                this_toskew = (int32_t)(toskew + (int32_t)(uint32_t)fromskew);
             }
             tmsize_t roffset = (tmsize_t)y * w + tocol;
             (*put)(img, raster + roffset, tocol, y, this_tw, nrow, fromskew,
@@ -859,7 +864,8 @@
             this_toskew = toskew;
         }
 
-        y += ((flip & FLIP_VERTICALLY) ? -(int32_t)nrow : (int32_t)nrow);
+        y += (uint32_t)((flip & FLIP_VERTICALLY) ? -(int32_t)nrow
+                                                 : (int32_t)nrow);
     }
     _TIFFfreeExt(img->tif, buf);
 
@@ -869,7 +875,7 @@
 
         for (line = 0; line < h; line++)
         {
-            uint32_t *left = raster + (line * w);
+            uint32_t *left = raster + (size_t)line * w;
             /* Use wmin to only flip horizontally data in place and not complete
              * raster-row. */
             uint32_t *right = left + wmin - 1;
@@ -924,13 +930,13 @@
     uint32_t wmin;
     if (0 <= img->col_offset && (uint32_t)img->col_offset < img->width)
     {
-        wmin = TIFFmin(w, img->width - img->col_offset);
+        wmin = TIFFmin(w, img->width - (uint32_t)img->col_offset);
     }
     else
     {
         TIFFErrorExtR(tif, TIFFFileName(tif),
                       "Error in gtTileSeparate: column offset %d exceeds "
-                      "image width %d",
+                      "image width %u",
                       img->col_offset, img->width);
         return 0;
     }
@@ -960,7 +966,7 @@
     }
     else
     {
-        if (tw > ((int64_t)INT_MAX + w))
+        if (tw > ((int64_t)INT_MAX + w) || w > ((int64_t)INT_MAX + tw))
         {
             TIFFErrorExtR(tif, TIFFFileName(tif), "%s",
                           "unsupported tile size (too wide)");
@@ -992,9 +998,9 @@
     /*
      *	Leftmost tile is clipped on left side if col_offset > 0.
      */
-    leftmost_fromskew = img->col_offset % tw;
-    leftmost_tw = tw - leftmost_fromskew;
-    int64_t skew_i64 = (int64_t)toskew + leftmost_fromskew;
+    leftmost_fromskew = (int32_t)((uint32_t)img->col_offset % tw);
+    leftmost_tw = (uint32_t)((int32_t)tw - leftmost_fromskew);
+    int64_t skew_i64 = (int64_t)toskew + (int64_t)(int32_t)leftmost_fromskew;
     if (skew_i64 > INT_MAX || skew_i64 < INT_MIN)
     {
         TIFFErrorExtR(tif, TIFFFileName(tif), "%s %" PRId64, "Invalid skew",
@@ -1004,21 +1010,22 @@
     leftmost_toskew = (int32_t)skew_i64;
     for (row = 0; ret != 0 && row < h; row += nrow)
     {
-        rowstoread = th - (row + img->row_offset) % th;
+        rowstoread = th - ((uint32_t)row + (uint32_t)img->row_offset) % th;
         nrow = (row + rowstoread > h ? h - row : rowstoread);
         fromskew = leftmost_fromskew;
         this_tw = leftmost_tw;
         this_toskew = leftmost_toskew;
         tocol = 0;
-        col = img->col_offset;
+        col = (uint32_t)img->col_offset;
         /* wmin: only write imagewidth if raster is bigger. */
         while (tocol < wmin)
         {
             if (buf == NULL)
             {
-                if (_TIFFReadTileAndAllocBuffer(tif, (void **)&buf, bufsize,
-                                                col, row + img->row_offset, 0,
-                                                0) == (tmsize_t)(-1) &&
+                if (_TIFFReadTileAndAllocBuffer(
+                        tif, (void **)&buf, bufsize, col,
+                        (uint32_t)((int32_t)row + img->row_offset), 0,
+                        0) == (tmsize_t)(-1) &&
                     (buf == NULL || img->stoponerr))
                 {
                     ret = 0;
@@ -1037,32 +1044,36 @@
                     pa = (alpha ? (p2 + tilesize) : NULL);
                 }
             }
-            else if (TIFFReadTile(tif, p0, col, row + img->row_offset, 0, 0) ==
-                         (tmsize_t)(-1) &&
+            else if (TIFFReadTile(tif, p0, col,
+                                  (uint32_t)((int32_t)row + img->row_offset), 0,
+                                  0) == (tmsize_t)(-1) &&
                      img->stoponerr)
             {
                 ret = 0;
                 break;
             }
             if (colorchannels > 1 &&
-                TIFFReadTile(tif, p1, col, row + img->row_offset, 0, 1) ==
-                    (tmsize_t)(-1) &&
+                TIFFReadTile(tif, p1, col,
+                             (uint32_t)((int32_t)row + img->row_offset), 0,
+                             (uint16_t)1) == (tmsize_t)(-1) &&
                 img->stoponerr)
             {
                 ret = 0;
                 break;
             }
             if (colorchannels > 1 &&
-                TIFFReadTile(tif, p2, col, row + img->row_offset, 0, 2) ==
-                    (tmsize_t)(-1) &&
+                TIFFReadTile(tif, p2, col,
+                             (uint32_t)((int32_t)row + img->row_offset), 0,
+                             (uint16_t)2) == (tmsize_t)(-1) &&
                 img->stoponerr)
             {
                 ret = 0;
                 break;
             }
             if (alpha &&
-                TIFFReadTile(tif, pa, col, row + img->row_offset, 0,
-                             colorchannels) == (tmsize_t)(-1) &&
+                TIFFReadTile(tif, pa, col,
+                             (uint32_t)((int32_t)row + img->row_offset), 0,
+                             (uint16_t)colorchannels) == (tmsize_t)(-1) &&
                 img->stoponerr)
             {
                 ret = 0;
@@ -1071,16 +1082,17 @@
 
             /* For SEPARATE the pos-offset is per sample and should not be
              * multiplied by img->samplesperpixel. */
-            pos = ((row + img->row_offset) % th) * TIFFTileRowSize(tif) +
+            pos = (tmsize_t)((uint32_t)((int32_t)row + img->row_offset) % th) *
+                      TIFFTileRowSize(tif) +
                   (tmsize_t)fromskew;
             if (tocol + this_tw > wmin)
             {
                 /*
                  * Rightmost tile is clipped on right side.
                  */
-                fromskew = tw - (wmin - tocol);
-                this_tw = tw - fromskew;
-                this_toskew = toskew + fromskew;
+                fromskew = (int32_t)(tw - (wmin - tocol));
+                this_tw = (uint32_t)((int32_t)tw - fromskew);
+                this_toskew = (int32_t)(toskew + (int32_t)(uint32_t)fromskew);
             }
             tmsize_t roffset = (tmsize_t)y * w + tocol;
             (*put)(img, raster + roffset, tocol, y, this_tw, nrow, fromskew,
@@ -1097,7 +1109,8 @@
             this_toskew = toskew;
         }
 
-        y += ((flip & FLIP_VERTICALLY) ? -(int32_t)nrow : (int32_t)nrow);
+        y += (uint32_t)((flip & FLIP_VERTICALLY) ? -(int32_t)nrow
+                                                 : (int32_t)nrow);
     }
 
     if (flip & FLIP_HORIZONTALLY)
@@ -1106,7 +1119,7 @@
 
         for (line = 0; line < h; line++)
         {
-            uint32_t *left = raster + (line * w);
+            uint32_t *left = raster + (size_t)line * w;
             /* Use wmin to only flip horizontally data in place and not complete
              * raster-row. */
             uint32_t *right = left + wmin - 1;
@@ -1155,13 +1168,13 @@
     uint32_t wmin;
     if (0 <= img->col_offset && (uint32_t)img->col_offset < imagewidth)
     {
-        wmin = TIFFmin(w, imagewidth - img->col_offset);
+        wmin = TIFFmin(w, imagewidth - (uint32_t)img->col_offset);
     }
     else
     {
         TIFFErrorExtR(tif, TIFFFileName(tif),
                       "Error in gtStripContig: column offset %d exceeds "
-                      "image width %d",
+                      "image width %u",
                       img->col_offset, imagewidth);
         return 0;
     }
@@ -1201,7 +1214,7 @@
         y = 0;
         /* Skew forward to the end of the raster width of the row currently
          * copied. */
-        toskew = w - wmin;
+        toskew = (int32_t)(w - wmin);
     }
 
     TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
@@ -1212,16 +1225,18 @@
     }
 
     scanline = TIFFScanlineSize(tif);
-    fromskew = (w < imagewidth ? imagewidth - w : 0);
+    fromskew = (int32_t)(w < imagewidth ? imagewidth - w : 0);
     for (row = 0; row < h; row += nrow)
     {
         uint32_t temp;
-        rowstoread = rowsperstrip - (row + img->row_offset) % rowsperstrip;
+        rowstoread = rowsperstrip -
+                     (uint32_t)((int32_t)row + img->row_offset) % rowsperstrip;
         nrow = (row + rowstoread > h ? h - row : rowstoread);
         nrowsub = nrow;
         if ((nrowsub % subsamplingver) != 0)
             nrowsub += subsamplingver - nrowsub % subsamplingver;
-        temp = (row + img->row_offset) % rowsperstrip + nrowsub;
+        temp =
+            (uint32_t)((int32_t)row + img->row_offset) % rowsperstrip + nrowsub;
         if (scanline > 0 && temp > (size_t)(TIFF_TMSIZE_T_MAX / scanline))
         {
             TIFFErrorExtR(tif, TIFFFileName(tif),
@@ -1229,21 +1244,27 @@
             return 0;
         }
         if (_TIFFReadEncodedStripAndAllocBuffer(
-                tif, TIFFComputeStrip(tif, row + img->row_offset, 0),
+                tif,
+                TIFFComputeStrip(tif,
+                                 (uint32_t)((int32_t)row + img->row_offset), 0),
                 (void **)(&buf), maxstripsize,
-                temp * scanline) == (tmsize_t)(-1) &&
+                (tmsize_t)((size_t)temp * (size_t)scanline)) ==
+                (tmsize_t)(-1) &&
             (buf == NULL || img->stoponerr))
         {
             ret = 0;
             break;
         }
 
-        pos = ((row + img->row_offset) % rowsperstrip) * scanline +
+        pos = (tmsize_t)((uint32_t)((int32_t)row + img->row_offset) %
+                         rowsperstrip) *
+                  scanline +
               ((tmsize_t)img->col_offset * img->samplesperpixel);
         tmsize_t roffset = (tmsize_t)y * w;
         (*put)(img, raster + roffset, 0, y, wmin, nrow, fromskew, toskew,
                buf + pos);
-        y += ((flip & FLIP_VERTICALLY) ? -(int32_t)nrow : (int32_t)nrow);
+        y += (uint32_t)((flip & FLIP_VERTICALLY) ? -(int32_t)nrow
+                                                 : (int32_t)nrow);
     }
 
     if (flip & FLIP_HORIZONTALLY)
@@ -1256,7 +1277,7 @@
 
         for (line = 0; line < h; line++)
         {
-            uint32_t *left = raster + (line * w);
+            uint32_t *left = raster + (size_t)line * w;
             /* Use wmin to only flip horizontally data in place and not complete
              * raster-row. */
             uint32_t *right = left + wmin - 1;
@@ -1306,13 +1327,13 @@
     uint32_t wmin;
     if (0 <= img->col_offset && (uint32_t)img->col_offset < imagewidth)
     {
-        wmin = TIFFmin(w, imagewidth - img->col_offset);
+        wmin = TIFFmin(w, imagewidth - (uint32_t)img->col_offset);
     }
     else
     {
         TIFFErrorExtR(tif, TIFFFileName(tif),
                       "Error in gtStripSeparate: column offset %d exceeds "
-                      "image width %d",
+                      "image width %u",
                       img->col_offset, imagewidth);
         return 0;
     }
@@ -1343,7 +1364,7 @@
         y = 0;
         /* Skew forward to the end of the raster width of the row currently
          * written. */
-        toskew = w - wmin;
+        toskew = (int32_t)(w - wmin);
     }
 
     switch (img->photometric)
@@ -1367,14 +1388,16 @@
     }
 
     scanline = TIFFScanlineSize(tif);
-    fromskew = (w < imagewidth ? imagewidth - w : 0);
+    fromskew = (int32_t)(w < imagewidth ? imagewidth - w : 0);
     for (row = 0; row < h; row += nrow)
     {
         uint32_t temp;
-        rowstoread = rowsperstrip - (row + img->row_offset) % rowsperstrip;
+        rowstoread =
+            rowsperstrip -
+            ((uint32_t)((int32_t)row + img->row_offset) % rowsperstrip);
         nrow = (row + rowstoread > h ? h - row : rowstoread);
-        offset_row = row + img->row_offset;
-        temp = (row + img->row_offset) % rowsperstrip + nrow;
+        offset_row = (uint32_t)((int32_t)row + img->row_offset);
+        temp = (uint32_t)((int32_t)row + img->row_offset) % rowsperstrip + nrow;
         if (scanline > 0 && temp > (size_t)(TIFF_TMSIZE_T_MAX / scanline))
         {
             TIFFErrorExtR(tif, TIFFFileName(tif),
@@ -1441,12 +1464,15 @@
 
         /* For SEPARATE the pos-offset is per sample and should not be
          * multiplied by img->samplesperpixel. */
-        pos = ((row + img->row_offset) % rowsperstrip) * scanline +
+        pos = (tmsize_t)((uint32_t)((int32_t)row + img->row_offset) %
+                         rowsperstrip) *
+                  scanline +
               (tmsize_t)img->col_offset;
         tmsize_t roffset = (tmsize_t)y * w;
         (*put)(img, raster + roffset, 0, y, wmin, nrow, fromskew, toskew,
                p0 + pos, p1 + pos, p2 + pos, (alpha ? (pa + pos) : NULL));
-        y += ((flip & FLIP_VERTICALLY) ? -(int32_t)nrow : (int32_t)nrow);
+        y += (uint32_t)((flip & FLIP_VERTICALLY) ? -(int32_t)nrow
+                                                 : (int32_t)nrow);
     }
 
     if (flip & FLIP_HORIZONTALLY)
@@ -1455,7 +1481,7 @@
 
         for (line = 0; line < h; line++)
         {
-            uint32_t *left = raster + (line * w);
+            uint32_t *left = raster + (size_t)line * w;
             /* Use wmin to only flip horizontally data in place and not complete
              * raster-row. */
             uint32_t *right = left + wmin - 1;
@@ -1511,6 +1537,9 @@
             op; /*-fallthrough*/                                               \
         case 1:                                                                \
             op;                                                                \
+            break;                                                             \
+        default:                                                               \
+            break;                                                             \
     }
 #define CASE4(x, op)                                                           \
     switch (x)                                                                 \
@@ -1521,6 +1550,9 @@
             op; /*-fallthrough*/                                               \
         case 1:                                                                \
             op;                                                                \
+            break;                                                             \
+        default:                                                               \
+            break;                                                             \
     }
 #define NOP
 
@@ -1587,13 +1619,6 @@
 #define PACK4(r, g, b, a)                                                      \
     ((uint32_t)(r) | ((uint32_t)(g) << 8) | ((uint32_t)(b) << 16) |            \
      ((uint32_t)(a) << 24))
-#define W2B(v) (((v) >> 8) & 0xff)
-/* TODO: PACKW should have be made redundant in favor of Bitdepth16To8 LUT */
-#define PACKW(r, g, b)                                                         \
-    ((uint32_t)W2B(r) | ((uint32_t)W2B(g) << 8) | ((uint32_t)W2B(b) << 16) | A1)
-#define PACKW4(r, g, b, a)                                                     \
-    ((uint32_t)W2B(r) | ((uint32_t)W2B(g) << 8) | ((uint32_t)W2B(b) << 16) |   \
-     ((uint32_t)W2B(a) << 24))
 
 #define DECLAREContigPutFunc(name)                                             \
     static void name(TIFFRGBAImage *img, uint32_t *cp, uint32_t x, uint32_t y, \
@@ -1712,7 +1737,7 @@
     {
         for (x = w; x > 0; --x)
         {
-            *cp++ = BWmap[*pp][0] & ((uint32_t) * (pp + 1) << 24 | ~A1);
+            *cp++ = BWmap[*pp][0] & ((uint32_t)*(pp + 1) << 24 | ~A1);
             pp += samplesperpixel;
         }
         cp += toskew;
@@ -1727,6 +1752,9 @@
 {
     int samplesperpixel = img->samplesperpixel;
     uint32_t **BWmap = img->BWmap;
+    /* Convert pixel skew to byte skew (16-bit samples) */
+    const tmsize_t fromskewLocal =
+        (tmsize_t)fromskew * (tmsize_t)(2 * samplesperpixel);
 
     (void)y;
     for (; h > 0; --h)
@@ -1742,7 +1770,7 @@
             wp += samplesperpixel;
         }
         cp += toskew;
-        pp += fromskew;
+        pp += fromskewLocal;
     }
 }
 
@@ -1812,13 +1840,14 @@
 
     (void)x;
     (void)y;
-    fromskew *= samplesperpixel;
+    const tmsize_t fromskewLocal =
+        (tmsize_t)fromskew * (tmsize_t)samplesperpixel;
     for (; h > 0; --h)
     {
         UNROLL8(w, NOP, *cp++ = PACK(pp[0], pp[1], pp[2]);
                 pp += samplesperpixel);
         cp += toskew;
-        pp += fromskew;
+        pp += fromskewLocal;
     }
 }
 
@@ -1832,13 +1861,14 @@
 
     (void)x;
     (void)y;
-    fromskew *= samplesperpixel;
+    const tmsize_t fromskewLocal =
+        (tmsize_t)fromskew * (tmsize_t)samplesperpixel;
     for (; h > 0; --h)
     {
         UNROLL8(w, NOP, *cp++ = PACK4(pp[0], pp[1], pp[2], pp[3]);
                 pp += samplesperpixel);
         cp += toskew;
-        pp += fromskew;
+        pp += fromskewLocal;
     }
 }
 
@@ -1850,7 +1880,8 @@
 {
     int samplesperpixel = img->samplesperpixel;
     (void)y;
-    fromskew *= samplesperpixel;
+    const tmsize_t fromskewLocal =
+        (tmsize_t)fromskew * (tmsize_t)samplesperpixel;
     for (; h > 0; --h)
     {
         uint32_t r, g, b, a;
@@ -1866,7 +1897,7 @@
             pp += samplesperpixel;
         }
         cp += toskew;
-        pp += fromskew;
+        pp += fromskewLocal;
     }
 }
 
@@ -1878,7 +1909,8 @@
     int samplesperpixel = img->samplesperpixel;
     uint16_t *wp = (uint16_t *)pp;
     (void)y;
-    fromskew *= samplesperpixel;
+    const tmsize_t fromskewLocal =
+        (tmsize_t)fromskew * (tmsize_t)samplesperpixel;
     for (; h > 0; --h)
     {
         for (x = w; x > 0; --x)
@@ -1888,7 +1920,7 @@
             wp += samplesperpixel;
         }
         cp += toskew;
-        wp += fromskew;
+        wp += fromskewLocal;
     }
 }
 
@@ -1901,7 +1933,8 @@
     int samplesperpixel = img->samplesperpixel;
     uint16_t *wp = (uint16_t *)pp;
     (void)y;
-    fromskew *= samplesperpixel;
+    const tmsize_t fromskewLocal =
+        (tmsize_t)fromskew * (tmsize_t)samplesperpixel;
     for (; h > 0; --h)
     {
         for (x = w; x > 0; --x)
@@ -1911,7 +1944,7 @@
             wp += samplesperpixel;
         }
         cp += toskew;
-        wp += fromskew;
+        wp += fromskewLocal;
     }
 }
 
@@ -1924,7 +1957,8 @@
     int samplesperpixel = img->samplesperpixel;
     uint16_t *wp = (uint16_t *)pp;
     (void)y;
-    fromskew *= samplesperpixel;
+    const tmsize_t fromskewLocal =
+        (tmsize_t)fromskew * (tmsize_t)samplesperpixel;
     for (; h > 0; --h)
     {
         uint32_t r, g, b, a;
@@ -1940,7 +1974,7 @@
             wp += samplesperpixel;
         }
         cp += toskew;
-        wp += fromskew;
+        wp += fromskewLocal;
     }
 }
 
@@ -1956,14 +1990,17 @@
 
     (void)x;
     (void)y;
-    fromskew *= samplesperpixel;
+    const tmsize_t fromskewLocal =
+        (tmsize_t)fromskew * (tmsize_t)samplesperpixel;
     for (; h > 0; --h)
     {
-        UNROLL8(w, NOP, k = 255 - pp[3]; r = (k * (255 - pp[0])) / 255;
-                g = (k * (255 - pp[1])) / 255; b = (k * (255 - pp[2])) / 255;
+        UNROLL8(w, NOP, k = (uint16_t)(255 - pp[3]);
+                r = (uint16_t)((k * (uint16_t)(255 - pp[0])) / 255);
+                g = (uint16_t)((k * (uint16_t)(255 - pp[1])) / 255);
+                b = (uint16_t)((k * (uint16_t)(255 - pp[2])) / 255);
                 *cp++ = PACK(r, g, b); pp += samplesperpixel);
         cp += toskew;
-        pp += fromskew;
+        pp += fromskewLocal;
     }
 }
 
@@ -1976,22 +2013,23 @@
 {
     int samplesperpixel = img->samplesperpixel;
     TIFFRGBValue *Map = img->Map;
-    uint16_t r, g, b, k;
+    unsigned int r, g, b, k;
 
     (void)y;
-    fromskew *= samplesperpixel;
+    const tmsize_t fromskewLocal =
+        (tmsize_t)fromskew * (tmsize_t)samplesperpixel;
     for (; h > 0; --h)
     {
         for (x = w; x > 0; --x)
         {
-            k = 255 - pp[3];
-            r = (k * (255 - pp[0])) / 255;
-            g = (k * (255 - pp[1])) / 255;
-            b = (k * (255 - pp[2])) / 255;
+            k = 255U - pp[3];
+            r = (k * (255U - pp[0])) / 255U;
+            g = (k * (255U - pp[1])) / 255U;
+            b = (k * (255U - pp[2])) / 255U;
             *cp++ = PACK(Map[r], Map[g], Map[b]);
             pp += samplesperpixel;
         }
-        pp += fromskew;
+        pp += fromskewLocal;
         cp += toskew;
     }
 }
@@ -2044,13 +2082,13 @@
     (void)y;
     for (; h > 0; --h)
     {
-        uint32_t rv, gv, bv, kv;
+        unsigned int rv, gv, bv, kv;
         for (x = w; x > 0; --x)
         {
-            kv = 255 - *a++;
-            rv = (kv * (255 - *r++)) / 255;
-            gv = (kv * (255 - *g++)) / 255;
-            bv = (kv * (255 - *b++)) / 255;
+            kv = 255U - *a++;
+            rv = (kv * (255U - *r++)) / 255U;
+            gv = (kv * (255U - *g++)) / 255U;
+            bv = (kv * (255U - *b++)) / 255U;
             *cp++ = PACK4(rv, gv, bv, 255);
         }
         SKEW4(r, g, b, a, fromskew);
@@ -2162,7 +2200,7 @@
     float X, Y, Z;
     uint32_t r, g, b;
     (void)y;
-    fromskew *= 3;
+    const tmsize_t fromskewLocal = (tmsize_t)fromskew * (tmsize_t)3;
     for (; h > 0; --h)
     {
         for (x = w; x > 0; --x)
@@ -2174,7 +2212,7 @@
             pp += 3;
         }
         cp += toskew;
-        pp += fromskew;
+        pp += fromskewLocal;
     }
 }
 
@@ -2187,7 +2225,7 @@
     uint32_t r, g, b;
     uint16_t *wp = (uint16_t *)pp;
     (void)y;
-    fromskew *= 3;
+    const tmsize_t fromskewLocal = (tmsize_t)fromskew * (tmsize_t)3;
     for (; h > 0; --h)
     {
         for (x = w; x > 0; --x)
@@ -2199,7 +2237,7 @@
             wp += 3;
         }
         cp += toskew;
-        wp += fromskew;
+        wp += fromskewLocal;
     }
 }
 
@@ -2210,7 +2248,7 @@
 #define YCbCrtoRGB(dst, Y)                                                     \
     {                                                                          \
         uint32_t r, g, b;                                                      \
-        TIFFYCbCrtoRGB(img->ycbcr, (Y), Cb, Cr, &r, &g, &b);                   \
+        TIFFYCbCrtoRGB(img->ycbcr, (Y), (int32_t)Cb, (int32_t)Cr, &r, &g, &b); \
         dst = PACK(r, g, b);                                                   \
     }
 
@@ -2226,7 +2264,8 @@
 
     (void)y;
     /* adjust fromskew */
-    fromskew = (fromskew / 4) * (4 * 2 + 2);
+    const tmsize_t fromskewLocal =
+        (tmsize_t)(fromskew / 4) * (tmsize_t)(4 * 4 + 2);
     if ((h & 3) == 0 && (w & 3) == 0)
     {
         for (; h >= 4; h -= 4)
@@ -2264,7 +2303,7 @@
             cp1 += incr;
             cp2 += incr;
             cp3 += incr;
-            pp += fromskew;
+            pp += fromskewLocal;
         }
     }
     else
@@ -2288,7 +2327,7 @@
                                 YCbCrtoRGB(cp1[3], pp[7]); /* FALLTHROUGH */
                             case 1:
                                 YCbCrtoRGB(cp[3], pp[3]); /* FALLTHROUGH */
-                        }                                 /* FALLTHROUGH */
+                        } /* FALLTHROUGH */
                     case 3:
                         switch (h)
                         {
@@ -2300,7 +2339,7 @@
                                 YCbCrtoRGB(cp1[2], pp[6]); /* FALLTHROUGH */
                             case 1:
                                 YCbCrtoRGB(cp[2], pp[2]); /* FALLTHROUGH */
-                        }                                 /* FALLTHROUGH */
+                        } /* FALLTHROUGH */
                     case 2:
                         switch (h)
                         {
@@ -2312,7 +2351,7 @@
                                 YCbCrtoRGB(cp1[1], pp[5]); /* FALLTHROUGH */
                             case 1:
                                 YCbCrtoRGB(cp[1], pp[1]); /* FALLTHROUGH */
-                        }                                 /* FALLTHROUGH */
+                        } /* FALLTHROUGH */
                     case 1:
                         switch (h)
                         {
@@ -2324,7 +2363,7 @@
                                 YCbCrtoRGB(cp1[0], pp[4]); /* FALLTHROUGH */
                             case 1:
                                 YCbCrtoRGB(cp[0], pp[0]); /* FALLTHROUGH */
-                        }                                 /* FALLTHROUGH */
+                        } /* FALLTHROUGH */
                 }
                 if (x < 4)
                 {
@@ -2351,7 +2390,7 @@
             cp1 += incr;
             cp2 += incr;
             cp3 += incr;
-            pp += fromskew;
+            pp += fromskewLocal;
         }
     }
 }
@@ -2362,10 +2401,11 @@
 DECLAREContigPutFunc(putcontig8bitYCbCr42tile)
 {
     uint32_t *cp1 = cp + w + toskew;
-    const tmsize_t incr = 2 * (tmsize_t)toskew + w;
+    const tmsize_t incr = 2 * (tmsize_t)toskew + (tmsize_t)w;
 
     (void)y;
-    fromskew = (fromskew / 4) * (4 * 2 + 2);
+    const tmsize_t fromskewLocal =
+        (tmsize_t)(fromskew / 4) * (tmsize_t)(4 * 2 + 2);
     if ((w & 3) == 0 && (h & 1) == 0)
     {
         for (; h >= 2; h -= 2)
@@ -2391,7 +2431,7 @@
             } while (--x);
             cp += incr;
             cp1 += incr;
-            pp += fromskew;
+            pp += fromskewLocal;
         }
     }
     else
@@ -2411,7 +2451,7 @@
                                 YCbCrtoRGB(cp1[3], pp[7]); /* FALLTHROUGH */
                             case 1:
                                 YCbCrtoRGB(cp[3], pp[3]); /* FALLTHROUGH */
-                        }                                 /* FALLTHROUGH */
+                        } /* FALLTHROUGH */
                     case 3:
                         switch (h)
                         {
@@ -2419,7 +2459,7 @@
                                 YCbCrtoRGB(cp1[2], pp[6]); /* FALLTHROUGH */
                             case 1:
                                 YCbCrtoRGB(cp[2], pp[2]); /* FALLTHROUGH */
-                        }                                 /* FALLTHROUGH */
+                        } /* FALLTHROUGH */
                     case 2:
                         switch (h)
                         {
@@ -2427,7 +2467,7 @@
                                 YCbCrtoRGB(cp1[1], pp[5]); /* FALLTHROUGH */
                             case 1:
                                 YCbCrtoRGB(cp[1], pp[1]); /* FALLTHROUGH */
-                        }                                 /* FALLTHROUGH */
+                        } /* FALLTHROUGH */
                     case 1:
                         switch (h)
                         {
@@ -2435,7 +2475,7 @@
                                 YCbCrtoRGB(cp1[0], pp[4]); /* FALLTHROUGH */
                             case 1:
                                 YCbCrtoRGB(cp[0], pp[0]); /* FALLTHROUGH */
-                        }                                 /* FALLTHROUGH */
+                        } /* FALLTHROUGH */
                 }
                 if (x < 4)
                 {
@@ -2456,7 +2496,7 @@
             h -= 2;
             cp += incr;
             cp1 += incr;
-            pp += fromskew;
+            pp += fromskewLocal;
         }
     }
 }
@@ -2467,7 +2507,8 @@
 DECLAREContigPutFunc(putcontig8bitYCbCr41tile)
 {
     (void)y;
-    fromskew = (fromskew / 4) * (4 * 1 + 2);
+    const tmsize_t fromskewLocal =
+        (tmsize_t)(fromskew / 4) * (tmsize_t)(4 * 1 + 2);
     do
     {
         x = w >> 2;
@@ -2501,6 +2542,8 @@
                     YCbCrtoRGB(cp[0], pp[0]); /*-fallthrough*/
                 case 0:
                     break;
+                default:
+                    break;
             }
 
             cp += (w & 3);
@@ -2508,7 +2551,7 @@
         }
 
         cp += toskew;
-        pp += fromskew;
+        pp += fromskewLocal;
     } while (--h);
 }
 
@@ -2518,9 +2561,10 @@
 DECLAREContigPutFunc(putcontig8bitYCbCr22tile)
 {
     uint32_t *cp2;
-    const tmsize_t incr = 2 * (tmsize_t)toskew + w;
+    const tmsize_t incr = 2 * (tmsize_t)toskew + (tmsize_t)w;
     (void)y;
-    fromskew = (fromskew / 2) * (2 * 2 + 2);
+    const tmsize_t fromskewLocal =
+        (tmsize_t)(fromskew / 2) * (tmsize_t)(2 * 2 + 2);
     cp2 = cp + w + toskew;
     while (h >= 2)
     {
@@ -2550,7 +2594,7 @@
         }
         cp += incr;
         cp2 += incr;
-        pp += fromskew;
+        pp += fromskewLocal;
         h -= 2;
     }
     if (h == 1)
@@ -2582,7 +2626,8 @@
 DECLAREContigPutFunc(putcontig8bitYCbCr21tile)
 {
     (void)y;
-    fromskew = (fromskew / 2) * (2 * 1 + 2);
+    const tmsize_t fromskewLocal =
+        (tmsize_t)(fromskew / 2) * (tmsize_t)(2 * 1 + 2);
     do
     {
         x = w >> 1;
@@ -2611,7 +2656,7 @@
         }
 
         cp += toskew;
-        pp += fromskew;
+        pp += fromskewLocal;
     } while (--h);
 }
 
@@ -2621,9 +2666,10 @@
 DECLAREContigPutFunc(putcontig8bitYCbCr12tile)
 {
     uint32_t *cp2;
-    const tmsize_t incr = 2 * (tmsize_t)toskew + w;
+    const tmsize_t incr = 2 * (tmsize_t)toskew + (tmsize_t)w;
     (void)y;
-    fromskew = (fromskew / 1) * (1 * 2 + 2);
+    const tmsize_t fromskewLocal =
+        (tmsize_t)(fromskew / 1) * (tmsize_t)(1 * 2 + 2);
     cp2 = cp + w + toskew;
     while (h >= 2)
     {
@@ -2640,7 +2686,7 @@
         } while (--x);
         cp += incr;
         cp2 += incr;
-        pp += fromskew;
+        pp += fromskewLocal;
         h -= 2;
     }
     if (h == 1)
@@ -2663,7 +2709,8 @@
 DECLAREContigPutFunc(putcontig8bitYCbCr11tile)
 {
     (void)y;
-    fromskew = (fromskew / 1) * (1 * 1 + 2);
+    const tmsize_t fromskewLocal =
+        (tmsize_t)(fromskew / 1) * (tmsize_t)(1 * 1 + 2);
     do
     {
         x = w; /* was x = w>>1; patched 2000/09/25 warmerda@home.com */
@@ -2677,7 +2724,7 @@
             pp += 3;
         } while (--x);
         cp += toskew;
-        pp += fromskew;
+        pp += fromskewLocal;
     } while (--h);
 }
 
@@ -2736,8 +2783,8 @@
 
     /* Do some validation to avoid later issues. Detect NaN for now */
     /* and also if lumaGreen is zero since we divide by it later */
-    if (luma[0] != luma[0] || luma[1] != luma[1] || luma[1] == 0.0 ||
-        luma[2] != luma[2])
+    if (isnan(luma[0]) || isnan(luma[1]) || TIFF_FLOAT_EQ(luma[1], 0.0f) ||
+        isnan(luma[2]))
     {
         TIFFErrorExtR(img->tif, module,
                       "Invalid values for YCbCrCoefficients tag");
@@ -2769,7 +2816,7 @@
     float refWhite[3];
 
     TIFFGetFieldDefaulted(img->tif, TIFFTAG_WHITEPOINT, &whitePoint);
-    if (whitePoint[1] == 0.0f)
+    if (TIFF_FLOAT_EQ(whitePoint[1], 0.0f))
     {
         TIFFErrorExtR(img->tif, module, "Invalid value for WhitePoint tag.");
         return NULL;
@@ -2787,10 +2834,10 @@
         }
     }
 
-    refWhite[1] = 100.0F;
+    refWhite[1] = 100.0f;
     refWhite[0] = whitePoint[0] / whitePoint[1] * refWhite[1];
     refWhite[2] =
-        (1.0F - whitePoint[0] - whitePoint[1]) / whitePoint[1] * refWhite[1];
+        (1.0f - whitePoint[0] - whitePoint[1]) / whitePoint[1] * refWhite[1];
     if (TIFFCIELabToRGBInit(img->cielab, &display_sRGB, refWhite) < 0)
     {
         TIFFErrorExtR(img->tif, module,
@@ -2826,7 +2873,8 @@
 
     img->BWmap = (uint32_t **)_TIFFmallocExt(
         img->tif,
-        256 * sizeof(uint32_t *) + (256 * nsamples * sizeof(uint32_t)));
+        (tmsize_t)((size_t)256 * sizeof(uint32_t *) +
+                   ((size_t)256 * (size_t)nsamples * sizeof(uint32_t))));
     if (img->BWmap == NULL)
     {
         TIFFErrorExtR(img->tif, TIFFFileName(img->tif),
@@ -2867,6 +2915,8 @@
             case 16:
                 GREY(i);
                 break;
+            default:
+                break;
         }
 #undef GREY
     }
@@ -2882,14 +2932,14 @@
 {
     int32_t x, range;
 
-    range = (int32_t)((1L << img->bitspersample) - 1);
+    range = (int32_t)((1U << img->bitspersample) - 1U);
 
     /* treat 16 bit the same as eight bit */
     if (img->bitspersample == 16)
-        range = (int32_t)255;
+        range = 255;
 
     img->Map = (TIFFRGBValue *)_TIFFmallocExt(
-        img->tif, (range + 1) * sizeof(TIFFRGBValue));
+        img->tif, (tmsize_t)((size_t)(range + 1) * sizeof(TIFFRGBValue)));
     if (img->Map == NULL)
     {
         TIFFErrorExtR(img->tif, TIFFFileName(img->tif),
@@ -2972,7 +3022,8 @@
 
     img->PALmap = (uint32_t **)_TIFFmallocExt(
         img->tif,
-        256 * sizeof(uint32_t *) + (256 * nsamples * sizeof(uint32_t)));
+        (tmsize_t)((size_t)256 * sizeof(uint32_t *) +
+                   ((size_t)256 * (size_t)nsamples * sizeof(uint32_t))));
     if (img->PALmap == NULL)
     {
         TIFFErrorExtR(img->tif, TIFFFileName(img->tif),
@@ -3012,6 +3063,8 @@
             case 8:
                 CMAP(i);
                 break;
+            default:
+                break;
         }
 #undef CMAP
     }
@@ -3054,6 +3107,8 @@
             if (img->bitspersample <= 8 && !makecmap(img))
                 return (0);
             break;
+        default:
+            break;
     }
     return (1);
 }
@@ -3102,6 +3157,8 @@
                             img->put.contig = putRGBcontig16bittile;
                     }
                     break;
+                default:
+                    break;
             }
             break;
         case PHOTOMETRIC_SEPARATED:
@@ -3133,6 +3190,8 @@
                     case 1:
                         img->put.contig = put1bitcmaptile;
                         break;
+                    default:
+                        break;
                 }
             }
             break;
@@ -3160,6 +3219,8 @@
                     case 1:
                         img->put.contig = put1bitbwtile;
                         break;
+                    default:
+                        break;
                 }
             }
             break;
@@ -3181,6 +3242,19 @@
                     uint16_t SubsamplingVer;
                     TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRSUBSAMPLING,
                                           &SubsamplingHor, &SubsamplingVer);
+                    /* Validate that the image dimensions are compatible with
+                    the subsampling block. All putcontig8bitYCbCrXYtile routines
+                    assume width >= X and height >= Y. */
+                    if (img->width < SubsamplingHor ||
+                        img->height < SubsamplingVer)
+                    {
+                        TIFFErrorExtR(img->tif, TIFFFileName(img->tif),
+                                      "YCbCr subsampling (%u,%u) incompatible "
+                                      "with image size %ux%u",
+                                      SubsamplingHor, SubsamplingVer,
+                                      img->width, img->height);
+                        return (0);
+                    }
                     switch ((SubsamplingHor << 4) | SubsamplingVer)
                     {
                         case 0x44:
@@ -3204,6 +3278,8 @@
                         case 0x11:
                             img->put.contig = putcontig8bitYCbCr11tile;
                             break;
+                        default:
+                            break;
                     }
                 }
             }
@@ -3215,6 +3291,9 @@
                     img->put.contig = initCIELabConversion(img);
                 break;
             }
+            break;
+        default:
+            break;
     }
     return ((img->get != NULL) && (img->put.contig != NULL));
 }
@@ -3266,6 +3345,8 @@
                             img->put.separate = putRGBseparate16bittile;
                     }
                     break;
+                default:
+                    break;
             }
             break;
         case PHOTOMETRIC_SEPARATED:
@@ -3290,10 +3371,14 @@
                             img->put.separate = putseparate8bitYCbCr11tile;
                             break;
                             /* TODO: add other cases here */
+                        default:
+                            break;
                     }
                 }
             }
             break;
+        default:
+            break;
     }
     return ((img->get != NULL) && (img->put.separate != NULL));
 }
@@ -3304,7 +3389,7 @@
     uint8_t *m;
     uint16_t na, nv;
     assert(img->UaToAa == NULL);
-    img->UaToAa = _TIFFmallocExt(img->tif, 65536);
+    img->UaToAa = (uint8_t *)_TIFFmallocExt(img->tif, 65536);
     if (img->UaToAa == NULL)
     {
         TIFFErrorExtR(img->tif, module, "Out of memory");
@@ -3325,7 +3410,7 @@
     uint8_t *m;
     uint32_t n;
     assert(img->Bitdepth16To8 == NULL);
-    img->Bitdepth16To8 = _TIFFmallocExt(img->tif, 65536);
+    img->Bitdepth16To8 = (uint8_t *)_TIFFmallocExt(img->tif, 65536);
     if (img->Bitdepth16To8 == NULL)
     {
         TIFFErrorExtR(img->tif, module, "Out of memory");
@@ -3392,7 +3477,7 @@
             return (0);
         }
 
-        img.row_offset = row;
+        img.row_offset = (int)row;
         img.col_offset = 0;
 
         if (row + rowsperstrip > img.height)
@@ -3503,8 +3588,8 @@
      * Read the chunk of imagery.
      */
 
-    img.row_offset = row;
-    img.col_offset = col;
+    img.row_offset = (int)row;
+    img.col_offset = (int)col;
 
     ok = TIFFRGBAImageGet(&img, raster, read_xsize, read_ysize);
 
@@ -3526,15 +3611,16 @@
         memmove(raster + (size_t)(tile_ysize - i_row - 1) * tile_xsize,
                 raster + (size_t)(read_ysize - i_row - 1) * read_xsize,
                 read_xsize * sizeof(uint32_t));
-        _TIFFmemset(raster + (size_t)(tile_ysize - i_row - 1) * tile_xsize +
-                        read_xsize,
-                    0, sizeof(uint32_t) * (tile_xsize - read_xsize));
+        _TIFFmemset(
+            raster + (size_t)(tile_ysize - i_row - 1) * tile_xsize + read_xsize,
+            0,
+            (tmsize_t)(sizeof(uint32_t) * (size_t)(tile_xsize - read_xsize)));
     }
 
     for (i_row = read_ysize; i_row < tile_ysize; i_row++)
     {
         _TIFFmemset(raster + (size_t)(tile_ysize - i_row - 1) * tile_xsize, 0,
-                    sizeof(uint32_t) * tile_xsize);
+                    (tmsize_t)(sizeof(uint32_t) * (size_t)tile_xsize));
     }
 
     return (ok);
diff --git a/third_party/libtiff/tif_hash_set.c b/third_party/libtiff/tif_hash_set.c
index 9be488e..aefcaad 100644
--- a/third_party/libtiff/tif_hash_set.c
+++ b/third_party/libtiff/tif_hash_set.c
@@ -76,7 +76,7 @@
     100663319, 201326611, 402653189, 805306457, 1610612741};
 
 /************************************************************************/
-/*                    TIFFHashSetHashPointer()                          */
+/*                       TIFFHashSetHashPointer()                       */
 /************************************************************************/
 
 /**
@@ -93,7 +93,7 @@
 }
 
 /************************************************************************/
-/*                   TIFFHashSetEqualPointer()                          */
+/*                      TIFFHashSetEqualPointer()                       */
 /************************************************************************/
 
 /**
@@ -111,7 +111,7 @@
 }
 
 /************************************************************************/
-/*                          TIFFHashSetNew()                             */
+/*                           TIFFHashSetNew()                           */
 /************************************************************************/
 
 /**
@@ -164,7 +164,7 @@
 }
 
 /************************************************************************/
-/*                          TIFFHashSetSize()                            */
+/*                          TIFFHashSetSize()                           */
 /************************************************************************/
 
 /**
@@ -184,7 +184,7 @@
 }
 
 /************************************************************************/
-/*                       TIFFHashSetGetNewListElt()                      */
+/*                      TIFFHashSetGetNewListElt()                      */
 /************************************************************************/
 
 static TIFFList *TIFFHashSetGetNewListElt(TIFFHashSet *set)
@@ -202,7 +202,7 @@
 }
 
 /************************************************************************/
-/*                       TIFFHashSetReturnListElt()                      */
+/*                      TIFFHashSetReturnListElt()                      */
 /************************************************************************/
 
 static void TIFFHashSetReturnListElt(TIFFHashSet *set, TIFFList *psList)
@@ -220,7 +220,7 @@
 }
 
 /************************************************************************/
-/*                   TIFFHashSetClearInternal()                          */
+/*                      TIFFHashSetClearInternal()                      */
 /************************************************************************/
 
 static void TIFFHashSetClearInternal(TIFFHashSet *set, bool bFinalize)
@@ -246,7 +246,7 @@
 }
 
 /************************************************************************/
-/*                         TIFFListDestroy()                            */
+/*                          TIFFListDestroy()                           */
 /************************************************************************/
 
 /**
@@ -270,7 +270,7 @@
 }
 
 /************************************************************************/
-/*                        TIFFHashSetDestroy()                          */
+/*                         TIFFHashSetDestroy()                         */
 /************************************************************************/
 
 /**
@@ -295,7 +295,7 @@
 
 #ifdef notused
 /************************************************************************/
-/*                        TIFFHashSetClear()                             */
+/*                          TIFFHashSetClear()                          */
 /************************************************************************/
 
 /**
@@ -319,7 +319,7 @@
 }
 
 /************************************************************************/
-/*                       TIFFHashSetForeach()                           */
+/*                         TIFFHashSetForeach()                         */
 /************************************************************************/
 
 /**
@@ -360,14 +360,14 @@
 #endif
 
 /************************************************************************/
-/*                        TIFFHashSetRehash()                           */
+/*                         TIFFHashSetRehash()                          */
 /************************************************************************/
 
 static bool TIFFHashSetRehash(TIFFHashSet *set)
 {
     int nNewAllocatedSize = anPrimes[set->nIndiceAllocatedSize];
     TIFFList **newTabList =
-        (TIFFList **)(calloc(nNewAllocatedSize, sizeof(TIFFList *)));
+        (TIFFList **)(calloc((size_t)nNewAllocatedSize, sizeof(TIFFList *)));
     if (newTabList == NULL)
         return false;
 #ifdef HASH_DEBUG
@@ -384,7 +384,7 @@
         while (cur)
         {
             const unsigned long nNewHashVal =
-                set->fnHashFunc(cur->pData) % nNewAllocatedSize;
+                set->fnHashFunc(cur->pData) % (unsigned long)nNewAllocatedSize;
 #ifdef HASH_DEBUG
             if (newTabList[nNewHashVal])
                 set->nCollisions++;
@@ -403,12 +403,13 @@
 }
 
 /************************************************************************/
-/*                        TIFFHashSetFindPtr()                          */
+/*                         TIFFHashSetFindPtr()                         */
 /************************************************************************/
 
 static void **TIFFHashSetFindPtr(TIFFHashSet *set, const void *elt)
 {
-    const unsigned long nHashVal = set->fnHashFunc(elt) % set->nAllocatedSize;
+    const unsigned long nHashVal =
+        set->fnHashFunc(elt) % (unsigned long)set->nAllocatedSize;
     TIFFList *cur = set->tabList[nHashVal];
     while (cur)
     {
@@ -464,7 +465,8 @@
         }
     }
 
-    const unsigned long nHashVal = set->fnHashFunc(elt) % set->nAllocatedSize;
+    const unsigned long nHashVal =
+        set->fnHashFunc(elt) % (unsigned long)set->nAllocatedSize;
 #ifdef HASH_DEBUG
     if (set->tabList[nHashVal])
         set->nCollisions++;
@@ -486,7 +488,7 @@
 }
 
 /************************************************************************/
-/*                        TIFFHashSetLookup()                           */
+/*                         TIFFHashSetLookup()                          */
 /************************************************************************/
 
 /**
@@ -532,7 +534,8 @@
         }
     }
 
-    int nHashVal = (int)(set->fnHashFunc(elt) % set->nAllocatedSize);
+    int nHashVal =
+        (int)(set->fnHashFunc(elt) % (unsigned long)set->nAllocatedSize);
     TIFFList *cur = set->tabList[nHashVal];
     TIFFList *prev = NULL;
     while (cur)
@@ -581,7 +584,7 @@
 
 #ifdef notused
 /************************************************************************/
-/*                     TIFFHashSetRemoveDeferRehash()                   */
+/*                    TIFFHashSetRemoveDeferRehash()                    */
 /************************************************************************/
 
 /**
diff --git a/third_party/libtiff/tif_jpeg.c b/third_party/libtiff/tif_jpeg.c
index a9764f0..1f17d0c 100644
--- a/third_party/libtiff/tif_jpeg.c
+++ b/third_party/libtiff/tif_jpeg.c
@@ -22,9 +22,6 @@
  * OF THIS SOFTWARE.
  */
 
-#define WIN32_LEAN_AND_MEAN
-#define VC_EXTRALEAN
-
 #include "tiffiop.h"
 #include <stdlib.h>
 
@@ -151,20 +148,9 @@
 #define LONGJMP(jbuf, code) longjmp(jbuf, code)
 #define JMP_BUF jmp_buf
 
-#ifndef TIFF_jpeg_destination_mgr_defined
-#define TIFF_jpeg_destination_mgr_defined
-typedef struct jpeg_destination_mgr jpeg_destination_mgr;
-#endif
-
-#ifndef TIFF_jpeg_source_mgr_defined
-#define TIFF_jpeg_source_mgr_defined
-typedef struct jpeg_source_mgr jpeg_source_mgr;
-#endif
-
-#ifndef TIFF_jpeg_error_mgr_defined
-#define TIFF_jpeg_error_mgr_defined
-typedef struct jpeg_error_mgr jpeg_error_mgr;
-#endif
+typedef struct jpeg_destination_mgr tiff_jpeg_destination_mgr;
+typedef struct jpeg_source_mgr tiff_jpeg_source_mgr;
+typedef struct jpeg_error_mgr tiff_jpeg_error_mgr;
 
 /*
  * State block for each open TIFF file using
@@ -179,6 +165,10 @@
  *     so we can safely cast JPEGState* -> jpeg_xxx_struct*
  *     and vice versa!
  */
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable : 4324) /* structure padding due to alignment */
+#endif
 typedef struct
 {
     union
@@ -189,22 +179,24 @@
     } cinfo; /* NB: must be first */
     int cinfo_initialized;
 
-    jpeg_error_mgr err;  /* libjpeg error manager */
-    JMP_BUF exit_jmpbuf; /* for catching libjpeg failures */
+    tiff_jpeg_error_mgr err; /* libjpeg error manager */
+    JMP_BUF exit_jmpbuf;     /* for catching libjpeg failures */
 
     struct jpeg_progress_mgr progress;
     /*
      * The following two members could be a union, but
      * they're small enough that it's not worth the effort.
      */
-    jpeg_destination_mgr dest; /* data dest for compression */
-    jpeg_source_mgr src;       /* data source for decompression */
-                               /* private state */
-    TIFF *tif;                 /* back link needed by some code */
-    uint16_t photometric;      /* copy of PhotometricInterpretation */
-    uint16_t h_sampling;       /* luminance sampling factors */
+    tiff_jpeg_destination_mgr dest; /* data dest for compression */
+    tiff_jpeg_source_mgr src;       /* data source for decompression */
+                                    /* private state */
+    TIFF *tif;                      /* back link needed by some code */
+    uint16_t photometric;           /* copy of PhotometricInterpretation */
+    uint16_t h_sampling;            /* luminance sampling factors */
     uint16_t v_sampling;
     tmsize_t bytesperline; /* decompressed bytes per scanline */
+    uint32_t strile_width;
+    uint32_t strile_height;
     /* pointers to intermediate buffers when processing downsampled data */
     TIFF_JSAMPARRAY ds_buffer[MAX_COMPONENTS];
     int scancount; /* number of "scanlines" accumulated */
@@ -214,6 +206,9 @@
 
     int encode_raw_error;
 } JPEGState;
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
 
 #define JState(tif) ((JPEGState *)(tif)->tif_data)
 
@@ -564,7 +559,7 @@
     /* the entire buffer has been filled; enlarge it by 1000 bytes */
     newbuf =
         _TIFFreallocExt(sp->tif, (void *)sp->otherSettings.jpegtables,
-                        (tmsize_t)(sp->otherSettings.jpegtables_length + 1000));
+                        (tmsize_t)sp->otherSettings.jpegtables_length + 1000);
     if (newbuf == NULL)
         ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 100);
     sp->dest.next_output_byte =
@@ -917,7 +912,7 @@
                         return (0);
                     if (n < 2)
                         return (0);
-                    n -= 2;
+                    n = (uint16_t)(n - 2);
                     if (n > 0)
                         JPEGFixupTagsSubsamplingSkip(data, n);
                 }
@@ -1021,7 +1016,7 @@
         assert(m < 0x80000000UL);
         if (TIFFReadFile(data->tif, data->buffer, (tmsize_t)m) != (tmsize_t)m)
             return (0);
-        data->buffercurrentbyte = data->buffer;
+        data->buffercurrentbyte = (uint8_t *)data->buffer;
         data->bufferbytesleft = m;
         data->fileoffset += m;
         data->filebytesleft -= m;
@@ -1042,7 +1037,7 @@
         return (0);
     if (!JPEGFixupTagsSubsamplingReadByte(data, &mb))
         return (0);
-    *result = (ma << 8) | mb;
+    *result = (uint16_t)((ma << 8) | mb);
     return (1);
 }
 
@@ -1164,6 +1159,47 @@
     return ret;
 }
 
+static int JPEGComputeStrileWidthHeightBytesPerLine(TIFF *tif, uint16_t s)
+{
+    JPEGState *sp = JState(tif);
+    TIFFDirectory *td = &tif->tif_dir;
+
+    /*
+     * Check image parameters and set decompression parameters.
+     */
+    if (isTiled(tif))
+    {
+        sp->strile_width = td->td_tilewidth;
+        sp->strile_height = td->td_tilelength;
+        sp->bytesperline = TIFFTileRowSize(tif);
+    }
+    else
+    {
+        sp->strile_width = td->td_imagewidth;
+        sp->strile_height = td->td_imagelength - tif->tif_dir.td_row;
+        if (sp->strile_height > td->td_rowsperstrip)
+            sp->strile_height = td->td_rowsperstrip;
+        sp->bytesperline = TIFFScanlineSize(tif);
+    }
+    if (td->td_planarconfig == PLANARCONFIG_SEPARATE && s > 0)
+    {
+        /*
+         * For PC 2, scale down the expected strip/tile size
+         * to match a downsampled component
+         */
+        if (sp->h_sampling == 0 || sp->v_sampling == 0)
+        {
+            TIFFErrorExtR(tif, "JPEGComputeStrileWidthHeightBytesPerLine",
+                          "JPEG horizontal or vertical sampling is zero");
+            return (0);
+        }
+        sp->strile_width = TIFFhowmany_32(sp->strile_width, sp->h_sampling);
+        sp->strile_height = TIFFhowmany_32(sp->strile_height, sp->v_sampling);
+    }
+
+    return 1;
+}
+
 /*
  * Set up for decoding a strip or tile.
  */
@@ -1172,7 +1208,6 @@
     JPEGState *sp = JState(tif);
     TIFFDirectory *td = &tif->tif_dir;
     static const char module[] = "JPEGPreDecode";
-    uint32_t segment_width, segment_height;
     int downsampled_output;
     int ci;
 
@@ -1198,52 +1233,24 @@
         return (0);
 
     tif->tif_rawcp = (uint8_t *)sp->src.next_input_byte;
-    tif->tif_rawcc = sp->src.bytes_in_buffer;
+    tif->tif_rawcc = (tmsize_t)sp->src.bytes_in_buffer;
 
-    /*
-     * Check image parameters and set decompression parameters.
-     */
-    if (isTiled(tif))
-    {
-        segment_width = td->td_tilewidth;
-        segment_height = td->td_tilelength;
-        sp->bytesperline = TIFFTileRowSize(tif);
-    }
-    else
-    {
-        segment_width = td->td_imagewidth;
-        segment_height = td->td_imagelength - tif->tif_row;
-        if (segment_height > td->td_rowsperstrip)
-            segment_height = td->td_rowsperstrip;
-        sp->bytesperline = TIFFScanlineSize(tif);
-    }
-    if (td->td_planarconfig == PLANARCONFIG_SEPARATE && s > 0)
-    {
-        /*
-         * For PC 2, scale down the expected strip/tile size
-         * to match a downsampled component
-         */
-        if (sp->h_sampling == 0 || sp->v_sampling == 0)
-        {
-            TIFFErrorExtR(tif, module,
-                          "JPEG horizontal or vertical sampling is zero");
-            return (0);
-        }
-        segment_width = TIFFhowmany_32(segment_width, sp->h_sampling);
-        segment_height = TIFFhowmany_32(segment_height, sp->v_sampling);
-    }
-    if (sp->cinfo.d.image_width < segment_width ||
-        sp->cinfo.d.image_height < segment_height)
+    if (!JPEGComputeStrileWidthHeightBytesPerLine(tif, s))
+        return 0;
+
+    if (sp->cinfo.d.image_width < sp->strile_width ||
+        sp->cinfo.d.image_height < sp->strile_height)
     {
         TIFFWarningExtR(tif, module,
                         "Improper JPEG strip/tile size, "
                         "expected %" PRIu32 "x%" PRIu32 ", got %ux%u",
-                        segment_width, segment_height, sp->cinfo.d.image_width,
-                        sp->cinfo.d.image_height);
+                        sp->strile_width, sp->strile_height,
+                        sp->cinfo.d.image_width, sp->cinfo.d.image_height);
     }
-    if (sp->cinfo.d.image_width == segment_width &&
-        sp->cinfo.d.image_height > segment_height &&
-        tif->tif_row + segment_height == td->td_imagelength && !isTiled(tif))
+    if (sp->cinfo.d.image_width == sp->strile_width &&
+        sp->cinfo.d.image_height > sp->strile_height &&
+        tif->tif_dir.td_row + sp->strile_height == td->td_imagelength &&
+        !isTiled(tif))
     {
         /* Some files have a last strip, that should be truncated, */
         /* but their JPEG codestream has still the maximum strip */
@@ -1252,11 +1259,11 @@
         TIFFWarningExtR(tif, module,
                         "JPEG strip size exceeds expected dimensions,"
                         " expected %" PRIu32 "x%" PRIu32 ", got %ux%u",
-                        segment_width, segment_height, sp->cinfo.d.image_width,
-                        sp->cinfo.d.image_height);
+                        sp->strile_width, sp->strile_height,
+                        sp->cinfo.d.image_width, sp->cinfo.d.image_height);
     }
-    else if (sp->cinfo.d.image_width > segment_width ||
-             sp->cinfo.d.image_height > segment_height)
+    else if (sp->cinfo.d.image_width > sp->strile_width ||
+             sp->cinfo.d.image_height > sp->strile_height)
     {
         /*
          * This case could be dangerous, if the strip or tile size has
@@ -1267,8 +1274,8 @@
         TIFFErrorExtR(tif, module,
                       "JPEG strip/tile size exceeds expected dimensions,"
                       " expected %" PRIu32 "x%" PRIu32 ", got %ux%u",
-                      segment_width, segment_height, sp->cinfo.d.image_width,
-                      sp->cinfo.d.image_height);
+                      sp->strile_width, sp->strile_height,
+                      sp->cinfo.d.image_width, sp->cinfo.d.image_height);
         return (0);
     }
     if (sp->cinfo.d.num_components !=
@@ -1325,11 +1332,12 @@
             if (compptr->h_samp_factor > 0 && compptr->v_samp_factor > 0)
             {
                 nRequiredMemory +=
-                    (toff_t)(((compptr->width_in_blocks +
-                               compptr->h_samp_factor - 1) /
-                              compptr->h_samp_factor)) *
-                    ((compptr->height_in_blocks + compptr->v_samp_factor - 1) /
-                     compptr->v_samp_factor) *
+                    (toff_t)((JDIMENSION)(((int)compptr->width_in_blocks +
+                                           compptr->h_samp_factor - 1) /
+                                          compptr->h_samp_factor)) *
+                    (JDIMENSION)(((int)compptr->height_in_blocks +
+                                  compptr->v_samp_factor - 1) /
+                                 compptr->v_samp_factor) *
                     sizeof(JBLOCK);
             }
         }
@@ -1445,7 +1453,7 @@
  * Decode a chunk of pixels.
  * "Standard" case: returned data is not downsampled.
  */
-#if !JPEG_LIB_MK1_OR_12BIT
+#if !defined(JPEG_LIB_MK1_OR_12BIT)
 static int JPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s)
 {
     JPEGState *sp = JState(tif);
@@ -1470,7 +1478,18 @@
         TIFFWarningExtR(tif, tif->tif_name, "fractional scanline not read");
 
     if (nrows > (tmsize_t)sp->cinfo.d.image_height)
+    {
+        /* Initialize the output buffer if the JPEG image is smaller than the
+         * strile height. */
+        memset(buf, 0, (size_t)cc);
         nrows = sp->cinfo.d.image_height;
+    }
+    else if (sp->strile_width > sp->cinfo.d.image_width)
+    {
+        /* Initialize the output buffer if the JPEG image is smaller than the
+         * strile width. */
+        memset(buf, 0, (size_t)cc);
+    }
 
     /* data is expected to be read in multiples of a scanline */
     if (nrows)
@@ -1489,7 +1508,7 @@
                 return (0);
             }
 
-            ++tif->tif_row;
+            ++tif->tif_dir.td_row;
             buf += sp->bytesperline;
             cc -= sp->bytesperline;
         } while (--nrows > 0);
@@ -1497,15 +1516,15 @@
 
     /* Update information on consumed data */
     tif->tif_rawcp = (uint8_t *)sp->src.next_input_byte;
-    tif->tif_rawcc = sp->src.bytes_in_buffer;
+    tif->tif_rawcc = (tmsize_t)sp->src.bytes_in_buffer;
 
     /* Close down the decompressor if we've finished the strip or tile. */
     return sp->cinfo.d.output_scanline < sp->cinfo.d.output_height ||
            TIFFjpeg_finish_decompress(sp);
 }
-#endif /* !JPEG_LIB_MK1_OR_12BIT */
+#endif /* !defined(JPEG_LIB_MK1_OR_12BIT) */
 
-#if JPEG_LIB_MK1_OR_12BIT
+#if defined(JPEG_LIB_MK1_OR_12BIT)
 /*ARGSUSED*/ static int JPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc,
                                    uint16_t s)
 {
@@ -1531,7 +1550,18 @@
         TIFFWarningExtR(tif, tif->tif_name, "fractional scanline not read");
 
     if (nrows > (tmsize_t)sp->cinfo.d.image_height)
+    {
+        /* Initialize the output buffer if the JPEG image is smaller than the
+         * strile height. */
+        memset(buf, 0, (size_t)cc);
         nrows = sp->cinfo.d.image_height;
+    }
+    else if (sp->strile_width > sp->cinfo.d.image_width)
+    {
+        /* Initialize the output buffer if the JPEG image is smaller than the
+         * strile width. */
+        memset(buf, 0, (size_t)cc);
+    }
 
     /* data is expected to be read in multiples of a scanline */
     if (nrows)
@@ -1545,8 +1575,9 @@
         if (sp->cinfo.d.data_precision == 12)
         {
             line_work_buf = (TIFF_JSAMPROW)_TIFFmallocExt(
-                tif, sizeof(short) * sp->cinfo.d.output_width *
-                         sp->cinfo.d.num_components);
+                tif, (tmsize_t)((size_t)sizeof(short) *
+                                (size_t)sp->cinfo.d.output_width *
+                                (size_t)sp->cinfo.d.num_components));
         }
 
         do
@@ -1562,14 +1593,16 @@
                 if (TIFFjpeg_read_scanlines(sp, &line_work_buf, 1) != 1)
                 {
                     memset(buf, 0, (size_t)cc);
+                    _TIFFfreeExt(tif, line_work_buf);
                     return (0);
                 }
 
                 if (sp->cinfo.d.data_precision == 12)
                 {
-                    int value_pairs = (sp->cinfo.d.output_width *
-                                       sp->cinfo.d.num_components) /
-                                      2;
+                    int value_pairs =
+                        (int)((JDIMENSION)sp->cinfo.d.output_width *
+                              (JDIMENSION)sp->cinfo.d.num_components) /
+                        2;
                     int iPair;
 
                     for (iPair = 0; iPair < value_pairs; iPair++)
@@ -1588,18 +1621,19 @@
                 else if (sp->cinfo.d.data_precision == 8)
                 {
                     int value_count =
-                        (sp->cinfo.d.output_width * sp->cinfo.d.num_components);
+                        (int)((JDIMENSION)sp->cinfo.d.output_width *
+                              (JDIMENSION)sp->cinfo.d.num_components);
                     int iValue;
 
                     for (iValue = 0; iValue < value_count; iValue++)
                     {
                         ((unsigned char *)buf)[iValue] =
-                            line_work_buf[iValue] & 0xff;
+                            (unsigned char)(line_work_buf[iValue] & 0xff);
                     }
                 }
             }
 
-            ++tif->tif_row;
+            ++tif->tif_dir.td_row;
             buf += sp->bytesperline;
             cc -= sp->bytesperline;
         } while (--nrows > 0);
@@ -1610,13 +1644,13 @@
 
     /* Update information on consumed data */
     tif->tif_rawcp = (uint8_t *)sp->src.next_input_byte;
-    tif->tif_rawcc = sp->src.bytes_in_buffer;
+    tif->tif_rawcc = (tmsize_t)sp->src.bytes_in_buffer;
 
     /* Close down the decompressor if we've finished the strip or tile. */
     return sp->cinfo.d.output_scanline < sp->cinfo.d.output_height ||
            TIFFjpeg_finish_decompress(sp);
 }
-#endif /* JPEG_LIB_MK1_OR_12BIT */
+#endif /* defined(JPEG_LIB_MK1_OR_12BIT) */
 
 /*ARGSUSED*/ static int DecodeRowError(TIFF *tif, uint8_t *buf, tmsize_t cc,
                                        uint16_t s)
@@ -1650,8 +1684,16 @@
     /* For last strip, limit number of rows to its truncated height */
     /* even if the codestream height is larger (which is not compliant, */
     /* but that we tolerate) */
-    if ((uint32_t)nrows > td->td_imagelength - tif->tif_row && !isTiled(tif))
-        nrows = td->td_imagelength - tif->tif_row;
+    if ((uint32_t)nrows > td->td_imagelength - tif->tif_dir.td_row &&
+        !isTiled(tif))
+        nrows = td->td_imagelength - tif->tif_dir.td_row;
+
+    /* The downsampled-data decode loop below only writes up to the JPEG
+     * codestream dimensions (and, due to the clump stride, may not cover the
+     * full caller buffer even for compliant files). Zero the whole buffer so
+     * no uninitialised heap is ever returned, mirroring the guard JPEGDecode
+     * received in 65759931ab6e (#826). */
+    memset(buf, 0, (size_t)cc);
 
 #if defined(JPEG_LIB_MK1_OR_12BIT)
     unsigned short *tmpbuf = NULL;
@@ -1666,9 +1708,10 @@
         int samples_per_clump = sp->samplesperclump;
 
 #if defined(JPEG_LIB_MK1_OR_12BIT)
-        tmpbuf = _TIFFmallocExt(tif, sizeof(unsigned short) *
-                                         sp->cinfo.d.output_width *
-                                         sp->cinfo.d.num_components);
+        tmpbuf = (unsigned short *)_TIFFmallocExt(
+            tif, (tmsize_t)((size_t)sizeof(unsigned short) *
+                            (size_t)sp->cinfo.d.output_width *
+                            (size_t)sp->cinfo.d.num_components));
         if (tmpbuf == NULL)
         {
             TIFFErrorExtR(tif, "JPEGDecodeRaw", "Out of memory");
@@ -1761,18 +1804,20 @@
                 if (sp->cinfo.d.data_precision == 8)
                 {
                     int i = 0;
-                    int len =
-                        sp->cinfo.d.output_width * sp->cinfo.d.num_components;
+                    int len = (int)((JDIMENSION)sp->cinfo.d.output_width *
+                                    (JDIMENSION)sp->cinfo.d.num_components);
                     for (i = 0; i < len; i++)
                     {
-                        ((unsigned char *)buf)[i] = tmpbuf[i] & 0xff;
+                        ((unsigned char *)buf)[i] =
+                            (unsigned char)(tmpbuf[i] & 0xff);
                     }
                 }
                 else
                 { /* 12-bit */
-                    int value_pairs = (sp->cinfo.d.output_width *
-                                       sp->cinfo.d.num_components) /
-                                      2;
+                    int value_pairs =
+                        (int)((JDIMENSION)sp->cinfo.d.output_width *
+                              (JDIMENSION)sp->cinfo.d.num_components) /
+                        2;
                     int iPair;
                     for (iPair = 0; iPair < value_pairs; iPair++)
                     {
@@ -1791,7 +1836,7 @@
 #endif
 
             sp->scancount++;
-            tif->tif_row += sp->v_sampling;
+            tif->tif_dir.td_row += sp->v_sampling;
 
             buf += sp->bytesperline;
             cc -= sp->bytesperline;
@@ -2030,9 +2075,9 @@
                 if (!TIFFGetField(tif, TIFFTAG_REFERENCEBLACKWHITE, &ref))
                 {
                     float refbw[6];
-                    long top = 1L << td->td_bitspersample;
+                    uint32_t top = 1U << td->td_bitspersample;
                     refbw[0] = 0;
-                    refbw[1] = (float)(top - 1L);
+                    refbw[1] = (float)(top - 1);
                     refbw[2] = (float)(top >> 1);
                     refbw[3] = refbw[1];
                     refbw[4] = refbw[2];
@@ -2080,30 +2125,30 @@
 #endif
     if (isTiled(tif))
     {
-        if ((td->td_tilelength % (sp->v_sampling * DCTSIZE)) != 0)
+        if ((td->td_tilelength % ((uint32_t)sp->v_sampling * DCTSIZE)) != 0)
         {
             TIFFErrorExtR(tif, module,
                           "JPEG tile height must be multiple of %" PRIu32,
-                          (uint32_t)(sp->v_sampling * DCTSIZE));
+                          (uint32_t)sp->v_sampling * DCTSIZE);
             return (0);
         }
-        if ((td->td_tilewidth % (sp->h_sampling * DCTSIZE)) != 0)
+        if ((td->td_tilewidth % ((uint32_t)sp->h_sampling * DCTSIZE)) != 0)
         {
             TIFFErrorExtR(tif, module,
                           "JPEG tile width must be multiple of %" PRIu32,
-                          (uint32_t)(sp->h_sampling * DCTSIZE));
+                          (uint32_t)sp->h_sampling * DCTSIZE);
             return (0);
         }
     }
     else
     {
         if (td->td_rowsperstrip < td->td_imagelength &&
-            (td->td_rowsperstrip % (sp->v_sampling * DCTSIZE)) != 0)
+            (td->td_rowsperstrip % ((uint32_t)sp->v_sampling * DCTSIZE)) != 0)
         {
             TIFFErrorExtR(tif, module,
                           "RowsPerStrip must be multiple of %" PRIu32
                           " for JPEG",
-                          (uint32_t)(sp->v_sampling * DCTSIZE));
+                          (uint32_t)sp->v_sampling * DCTSIZE);
             return (0);
         }
     }
@@ -2159,7 +2204,6 @@
     JPEGState *sp = JState(tif);
     TIFFDirectory *td = &tif->tif_dir;
     static const char module[] = "JPEGPreEncode";
-    uint32_t segment_width, segment_height;
     int downsampled_input;
 
     assert(sp != NULL);
@@ -2170,47 +2214,20 @@
     }
 
     assert(!sp->cinfo.comm.is_decompressor);
-    /*
-     * Set encoding parameters for this strip/tile.
-     */
-    if (isTiled(tif))
-    {
-        segment_width = td->td_tilewidth;
-        segment_height = td->td_tilelength;
-        sp->bytesperline = TIFFTileRowSize(tif);
-    }
-    else
-    {
-        segment_width = td->td_imagewidth;
-        segment_height = td->td_imagelength - tif->tif_row;
-        if (segment_height > td->td_rowsperstrip)
-            segment_height = td->td_rowsperstrip;
-        sp->bytesperline = TIFFScanlineSize(tif);
-    }
-    if (td->td_planarconfig == PLANARCONFIG_SEPARATE && s > 0)
-    {
-        /* for PC 2, scale down the strip/tile size
-         * to match a downsampled component
-         */
-        if (sp->h_sampling == 0 || sp->v_sampling == 0)
-        {
-            TIFFErrorExtR(tif, module,
-                          "JPEG horizontal or vertical sampling is zero");
-            return (0);
-        }
-        segment_width = TIFFhowmany_32(segment_width, sp->h_sampling);
-        segment_height = TIFFhowmany_32(segment_height, sp->v_sampling);
-    }
-    if (segment_width > (uint32_t)JPEG_MAX_DIMENSION ||
-        segment_height > (uint32_t)JPEG_MAX_DIMENSION)
+
+    if (!JPEGComputeStrileWidthHeightBytesPerLine(tif, s))
+        return 0;
+
+    if (sp->strile_width > (uint32_t)JPEG_MAX_DIMENSION ||
+        sp->strile_height > (uint32_t)JPEG_MAX_DIMENSION)
     {
         TIFFErrorExtR(tif, module,
                       "Strip/tile too large for JPEG. Maximum dimension is %d",
                       (int)JPEG_MAX_DIMENSION);
         return (0);
     }
-    sp->cinfo.c.image_width = segment_width;
-    sp->cinfo.c.image_height = segment_height;
+    sp->cinfo.c.image_width = sp->strile_width;
+    sp->cinfo.c.image_height = sp->strile_height;
     downsampled_input = FALSE;
     if (td->td_planarconfig == PLANARCONFIG_CONTIG)
     {
@@ -2282,7 +2299,13 @@
         /* an existing file */
         suppress_huff_table(sp, 0);
         suppress_huff_table(sp, 1);
-        sp->cinfo.c.optimize_coding = FALSE;
+
+        /* We want to keep optimize_coding = TRUE for 12-bit JPEG */
+        /* See lengthy explanation at
+         * https://gitlab.com/libtiff/libtiff/-/work_items/773#note_3009836854
+         */
+        if (sp->cinfo.c.data_precision == 8)
+            sp->cinfo.c.optimize_coding = FALSE;
     }
     else
         sp->cinfo.c.optimize_coding = TRUE;
@@ -2338,13 +2361,15 @@
         TIFFWarningExtR(tif, tif->tif_name, "fractional scanline discarded");
 
     /* The last strip will be limited to image size */
-    if (!isTiled(tif) && tif->tif_row + nrows > tif->tif_dir.td_imagelength)
-        nrows = tif->tif_dir.td_imagelength - tif->tif_row;
+    if (!isTiled(tif) &&
+        tif->tif_dir.td_row + nrows > tif->tif_dir.td_imagelength)
+        nrows = tif->tif_dir.td_imagelength - tif->tif_dir.td_row;
 
     if (sp->cinfo.c.data_precision == 12)
     {
         line16_count = (int)((sp->bytesperline * 2) / 3);
-        line16 = (short *)_TIFFmallocExt(tif, sizeof(short) * line16_count);
+        line16 = (short *)_TIFFmallocExt(
+            tif, (tmsize_t)(sizeof(short) * (size_t)line16_count));
         if (!line16)
         {
             TIFFErrorExtR(tif, "JPEGEncode", "Failed to allocate memory");
@@ -2369,8 +2394,10 @@
                 unsigned char *in_ptr = ((unsigned char *)buf) + iPair * 3;
                 TIFF_JSAMPLE *out_ptr = (TIFF_JSAMPLE *)(line16 + iPair * 2);
 
-                out_ptr[0] = (in_ptr[0] << 4) | ((in_ptr[1] & 0xf0) >> 4);
-                out_ptr[1] = ((in_ptr[1] & 0x0f) << 8) | in_ptr[2];
+                out_ptr[0] = (TIFF_JSAMPLE)((in_ptr[0] << 4) |
+                                            ((in_ptr[1] & 0xf0) >> 4));
+                out_ptr[1] =
+                    (TIFF_JSAMPLE)(((in_ptr[1] & 0x0f) << 8) | in_ptr[2]);
             }
         }
         else
@@ -2380,7 +2407,7 @@
         if (TIFFjpeg_write_scanlines(sp, bufptr, 1) != 1)
             return (0);
         if (nrows > 0)
-            tif->tif_row++;
+            tif->tif_dir.td_row++;
         buf += sp->bytesperline;
     }
 
@@ -2449,8 +2476,9 @@
         {
             int hsamp = compptr->h_samp_factor;
             int vsamp = compptr->v_samp_factor;
-            int padding = (int)(compptr->width_in_blocks * DCTSIZE -
-                                clumps_per_line * hsamp);
+            int padding =
+                (int)(compptr->width_in_blocks * DCTSIZE -
+                      (JDIMENSION)clumps_per_line * (JDIMENSION)hsamp);
             for (ypos = 0; ypos < vsamp; ypos++)
             {
                 inptr = ((TIFF_JSAMPLE *)buf) + clumpoffset;
@@ -2494,7 +2522,7 @@
             }
             sp->scancount = 0;
         }
-        tif->tif_row += sp->v_sampling;
+        tif->tif_dir.td_row += sp->v_sampling;
         buf += bytesperclumpline;
         nrows -= sp->v_sampling;
     }
@@ -2588,10 +2616,11 @@
      * Must recalculate cached tile size in case sampling state changed.
      * Should we really be doing this now if image size isn't set?
      */
-    if (tif->tif_tilesize > 0)
-        tif->tif_tilesize = isTiled(tif) ? TIFFTileSize(tif) : (tmsize_t)(-1);
-    if (tif->tif_scanlinesize > 0)
-        tif->tif_scanlinesize = TIFFScanlineSize(tif);
+    if (tif->tif_dir.td_tilesize > 0)
+        tif->tif_dir.td_tilesize =
+            isTiled(tif) ? TIFFTileSize(tif) : (tmsize_t)(-1);
+    if (tif->tif_dir.td_scanlinesize > 0)
+        tif->tif_dir.td_scanlinesize = TIFFScanlineSize(tif);
 }
 
 static int JPEGVSetField(TIFF *tif, uint32_t tag, va_list ap)
@@ -2799,6 +2828,33 @@
     return 1;
 }
 
+static uint64_t JPEGGetMaxCompressionRatio(TIFF *tif)
+{
+    /* See README_for_libtiff_developpers.md for raw data used to estimate
+     * the maximum compression rate. */
+
+    const JPEGState *sp = JState(tif);
+    if ((tif->tif_dir.td_photometric == PHOTOMETRIC_YCBCR) &&
+        (tif->tif_dir.td_planarconfig == PLANARCONFIG_CONTIG) &&
+        (tif->tif_dir.td_samplesperpixel == 3))
+    {
+        if (sp->h_sampling == 2 && sp->v_sampling == 2)
+        {
+            if (tif->tif_dir.td_bitspersample == 12)
+                return 768;
+            else
+                return 512;
+        }
+
+        return 0; /* unknown */
+    }
+
+    if (tif->tif_dir.td_bitspersample == 12)
+        return 384;
+    else
+        return 256;
+}
+
 /* Common to tif_jpeg.c and tif_jpeg_12.c */
 static void TIFFInitJPEGCommon(TIFF *tif)
 {
@@ -2835,6 +2891,7 @@
     tif->tif_encoderow = JPEGEncode;
     tif->tif_encodestrip = JPEGEncode;
     tif->tif_encodetile = JPEGEncode;
+    tif->tif_getmaxcompressionratio = JPEGGetMaxCompressionRatio;
     tif->tif_cleanup = JPEGCleanup;
 
     tif->tif_defstripsize = JPEGDefaultStripSize;
diff --git a/third_party/libtiff/tif_luv.c b/third_party/libtiff/tif_luv.c
index ecc3225..d9bc8fe 100644
--- a/third_party/libtiff/tif_luv.c
+++ b/third_party/libtiff/tif_luv.c
@@ -212,7 +212,7 @@
         }
         tp = (int16_t *)sp->tbuf;
     }
-    _TIFFmemset((void *)tp, 0, npixels * sizeof(tp[0]));
+    _TIFFmemset((void *)tp, 0, (tmsize_t)((size_t)npixels * sizeof(tp[0])));
 
     bp = (unsigned char *)tif->tif_rawcp;
     cc = tif->tif_rawcc;
@@ -235,7 +235,7 @@
             {               /* non-run */
                 rc = *bp++; /* nul is noop */
                 while (--cc && rc-- && i < npixels)
-                    tp[i++] |= (int16_t)*bp++ << shft;
+                    tp[i++] |= (int16_t)(*bp++ << shft);
             }
         }
         if (i != npixels)
@@ -243,7 +243,7 @@
             TIFFErrorExtR(tif, module,
                           "Not enough data at row %" PRIu32
                           " (short %" TIFF_SSIZE_FORMAT " pixels)",
-                          tif->tif_row, npixels - i);
+                          tif->tif_dir.td_row, npixels - i);
             tif->tif_rawcp = (uint8_t *)bp;
             tif->tif_rawcc = cc;
             return (0);
@@ -290,7 +290,7 @@
     cc = tif->tif_rawcc;
     for (i = 0; i < npixels && cc >= 3; i++)
     {
-        tp[i] = bp[0] << 16 | bp[1] << 8 | bp[2];
+        tp[i] = (uint32_t)bp[0] << 16 | (uint32_t)bp[1] << 8 | bp[2];
         bp += 3;
         cc -= 3;
     }
@@ -301,7 +301,7 @@
         TIFFErrorExtR(tif, module,
                       "Not enough data at row %" PRIu32
                       " (short %" TIFF_SSIZE_FORMAT " pixels)",
-                      tif->tif_row, npixels - i);
+                      tif->tif_dir.td_row, npixels - i);
         return (0);
     }
     (*sp->tfunc)(sp, op, npixels);
@@ -342,7 +342,7 @@
         }
         tp = (uint32_t *)sp->tbuf;
     }
-    _TIFFmemset((void *)tp, 0, npixels * sizeof(tp[0]));
+    _TIFFmemset((void *)tp, 0, (tmsize_t)((size_t)npixels * sizeof(tp[0])));
 
     bp = (unsigned char *)tif->tif_rawcp;
     cc = tif->tif_rawcc;
@@ -373,7 +373,7 @@
             TIFFErrorExtR(tif, module,
                           "Not enough data at row %" PRIu32
                           " (short %" TIFF_SSIZE_FORMAT " pixels)",
-                          tif->tif_row, npixels - i);
+                          tif->tif_dir.td_row, npixels - i);
             tif->tif_rawcp = (uint8_t *)bp;
             tif->tif_rawcc = cc;
             return (0);
@@ -767,25 +767,21 @@
 #ifndef M_PI
 #define M_PI 3.14159265358979323846
 #endif
-#undef log2 /* Conflict with C'99 function */
-#define log2(x) ((1. / M_LN2) * log(x))
-#undef exp2 /* Conflict with C'99 function */
-#define exp2(x) exp(M_LN2 *(x))
 
 #define TIFF_RAND_MAX 32767
 
 // From POSIX.1-2001 as an example of an implementation of rand()
-static uint32_t _TIFFRand()
+static uint32_t _TIFFRand(void)
 {
     static uint32_t nCounter = 0;
     if (!nCounter)
         nCounter = (uint32_t)(time(NULL) & UINT32_MAX);
     ++nCounter;
     uint32_t nCounterLocal =
-        (uint32_t)(((uint64_t)(nCounter)*1103515245U + 12345U) & UINT32_MAX);
+        (uint32_t)(((uint64_t)(nCounter) * 1103515245U + 12345U) & UINT32_MAX);
     nCounter = nCounterLocal;
     return (nCounterLocal / 65536U) % (TIFF_RAND_MAX + 1);
-};
+}
 
 static int tiff_itrunc(double x, int m)
 {
@@ -797,8 +793,7 @@
 #if !LOGLUV_PUBLIC
 static
 #endif
-    double
-    LogL16toY(int p16) /* compute luminance from 16-bit LogL */
+    double LogL16toY(int p16) /* compute luminance from 16-bit LogL */
 {
     int Le = p16 & 0x7fff;
     double Y;
@@ -812,8 +807,7 @@
 #if !LOGLUV_PUBLIC
 static
 #endif
-    int
-    LogL16fromY(double Y, int em) /* get 16-bit LogL from Y */
+    int LogL16fromY(double Y, int em) /* get 16-bit LogL from Y */
 {
     if (Y >= 1.8371976e19)
         return (0x7fff);
@@ -855,20 +849,22 @@
     float *yp = (float *)op;
 
     while (n-- > 0)
-        *l16++ = (int16_t)(LogL16fromY(*yp++, sp->encode_meth));
+        *l16++ = (int16_t)(LogL16fromY((double)*yp++, sp->encode_meth));
 }
 
 #if !LOGLUV_PUBLIC
 static
 #endif
-    void
-    XYZtoRGB24(float *xyz, uint8_t *rgb)
+    void XYZtoRGB24(float *xyz, uint8_t *rgb)
 {
     double r, g, b;
     /* assume CCIR-709 primaries */
-    r = 2.690 * xyz[0] + -1.276 * xyz[1] + -0.414 * xyz[2];
-    g = -1.022 * xyz[0] + 1.978 * xyz[1] + 0.044 * xyz[2];
-    b = 0.061 * xyz[0] + -0.224 * xyz[1] + 1.163 * xyz[2];
+    r = 2.690 * (double)xyz[0] + -1.276 * (double)xyz[1] +
+        -0.414 * (double)xyz[2];
+    g = -1.022 * (double)xyz[0] + 1.978 * (double)xyz[1] +
+        0.044 * (double)xyz[2];
+    b = 0.061 * (double)xyz[0] + -0.224 * (double)xyz[1] +
+        1.163 * (double)xyz[2];
     /* assume 2.0 gamma for speed */
     /* could use integer sqrt approx., but this is probably faster */
     rgb[0] = (uint8_t)((r <= 0.) ? 0 : (r >= 1.) ? 255 : (int)(256. * sqrt(r)));
@@ -879,8 +875,7 @@
 #if !LOGLUV_PUBLIC
 static
 #endif
-    double
-    LogL10toY(int p10) /* compute luminance from 10-bit LogL */
+    double LogL10toY(int p10) /* compute luminance from 10-bit LogL */
 {
     if (p10 == 0)
         return (0.);
@@ -890,8 +885,7 @@
 #if !LOGLUV_PUBLIC
 static
 #endif
-    int
-    LogL10fromY(double Y, int em) /* get 10-bit LogL from Y */
+    int LogL10fromY(double Y, int em) /* get 10-bit LogL from Y */
 {
     if (Y >= 15.742)
         return (0x3ff);
@@ -903,13 +897,14 @@
 
 #define NANGLES 100
 #define uv2ang(u, v)                                                           \
-    ((NANGLES * .499999999 / M_PI) * atan2((v)-V_NEU, (u)-U_NEU) + .5 * NANGLES)
+    ((NANGLES * .499999999 / M_PI) * atan2((v) - V_NEU, (u) - U_NEU) +         \
+     .5 * NANGLES)
 
 static int oog_encode(double u, double v) /* encode out-of-gamut chroma */
 {
     static int oog_table[NANGLES];
     static int initialized = 0;
-    register int i;
+    int i;
 
     if (!initialized)
     { /* set up perimeter table */
@@ -919,13 +914,14 @@
             eps[i] = 2.;
         for (vi = UV_NVS; vi--;)
         {
-            va = UV_VSTART + (vi + .5) * UV_SQSIZ;
+            va = (double)UV_VSTART + ((double)vi + .5) * (double)UV_SQSIZ;
             ustep = uv_row[vi].nus - 1;
             if (vi == UV_NVS - 1 || vi == 0 || ustep <= 0)
                 ustep = 1;
             for (ui = uv_row[vi].nus - 1; ui >= 0; ui -= ustep)
             {
-                ua = uv_row[vi].ustart + (ui + .5) * UV_SQSIZ;
+                ua = (double)uv_row[vi].ustart +
+                     ((double)ui + .5) * (double)UV_SQSIZ;
                 ang = uv2ang(ua, va);
                 i = (int)ang;
                 epsa = fabs(ang - (i + .5));
@@ -963,27 +959,28 @@
 #if !LOGLUV_PUBLIC
 static
 #endif
-    int
-    uv_encode(double u, double v, int em) /* encode (u',v') coordinates */
+    int uv_encode(double u, double v, int em) /* encode (u',v') coordinates */
 {
     unsigned int vi;
     int ui;
 
     /* check for NaN */
-    if (u != u || v != v)
+    if (isnan(u) || isnan(v))
     {
         u = U_NEU;
         v = V_NEU;
     }
 
-    if (v < UV_VSTART)
+    if ((double)v < (double)UV_VSTART)
         return oog_encode(u, v);
-    vi = tiff_itrunc((v - UV_VSTART) * (1. / UV_SQSIZ), em);
+    vi = (unsigned int)tiff_itrunc(
+        ((double)v - (double)UV_VSTART) * (1. / (double)UV_SQSIZ), em);
     if (vi >= UV_NVS)
         return oog_encode(u, v);
-    if (u < uv_row[vi].ustart)
+    if ((double)u < (double)uv_row[vi].ustart)
         return oog_encode(u, v);
-    ui = tiff_itrunc((u - uv_row[vi].ustart) * (1. / UV_SQSIZ), em);
+    ui = tiff_itrunc(
+        ((double)u - (double)uv_row[vi].ustart) * (1. / (double)UV_SQSIZ), em);
     if (ui >= uv_row[vi].nus)
         return oog_encode(u, v);
 
@@ -993,8 +990,7 @@
 #if !LOGLUV_PUBLIC
 static
 #endif
-    int
-    uv_decode(double *up, double *vp, int c) /* decode (u',v') index */
+    int uv_decode(double *up, double *vp, int c) /* decode (u',v') index */
 {
     unsigned int upper, lower;
     int ui;
@@ -1020,16 +1016,15 @@
     }
     vi = lower;
     ui = c - uv_row[vi].ncum;
-    *up = uv_row[vi].ustart + (ui + .5) * UV_SQSIZ;
-    *vp = UV_VSTART + (vi + .5) * UV_SQSIZ;
+    *up = (double)uv_row[vi].ustart + ((double)ui + .5) * (double)UV_SQSIZ;
+    *vp = (double)UV_VSTART + ((double)vi + .5) * (double)UV_SQSIZ;
     return (0);
 }
 
 #if !LOGLUV_PUBLIC
 static
 #endif
-    void
-    LogLuv24toXYZ(uint32_t p, float *XYZ)
+    void LogLuv24toXYZ(uint32_t p, float *XYZ)
 {
     int Ce;
     double L, u, v, s, x, y;
@@ -1059,15 +1054,14 @@
 #if !LOGLUV_PUBLIC
 static
 #endif
-    uint32_t
-    LogLuv24fromXYZ(float *XYZ, int em)
+    uint32_t LogLuv24fromXYZ(float *XYZ, int em)
 {
     int Le, Ce;
     double u, v, s;
     /* encode luminance */
-    Le = LogL10fromY(XYZ[1], em);
+    Le = LogL10fromY((double)XYZ[1], em);
     /* encode color */
-    s = XYZ[0] + 15. * XYZ[1] + 3. * XYZ[2];
+    s = (double)XYZ[0] + 15. * (double)XYZ[1] + 3. * (double)XYZ[2];
     if (!Le || s <= 0.)
     {
         u = U_NEU;
@@ -1075,14 +1069,14 @@
     }
     else
     {
-        u = 4. * XYZ[0] / s;
-        v = 9. * XYZ[1] / s;
+        u = 4. * (double)XYZ[0] / s;
+        v = 9. * (double)XYZ[1] / s;
     }
     Ce = uv_encode(u, v, em);
     if (Ce < 0) /* never happens */
         Ce = uv_encode(U_NEU, V_NEU, SGILOGENCODE_NODITHER);
     /* combine encodings */
-    return (Le << 14 | Ce);
+    return (uint32_t)Le << 14 | (uint32_t)Ce;
 }
 
 static void Luv24toXYZ(LogLuvState *sp, uint8_t *op, tmsize_t n)
@@ -1113,8 +1107,8 @@
             u = U_NEU;
             v = V_NEU;
         }
-        *luv3++ = (int16_t)(u * (1L << 15));
-        *luv3++ = (int16_t)(v * (1L << 15));
+        *luv3++ = (int16_t)(u * (1 << 15));
+        *luv3++ = (int16_t)(v * (1 << 15));
         luv++;
     }
 }
@@ -1168,7 +1162,7 @@
                        sp->encode_meth);
         if (Ce < 0) /* never happens */
             Ce = uv_encode(U_NEU, V_NEU, SGILOGENCODE_NODITHER);
-        *luv++ = (uint32_t)Le << 14 | Ce;
+        *luv++ = (uint32_t)Le << 14 | (uint32_t)Ce;
         luv3 += 3;
     }
 }
@@ -1176,8 +1170,7 @@
 #if !LOGLUV_PUBLIC
 static
 #endif
-    void
-    LogLuv32toXYZ(uint32_t p, float *XYZ)
+    void LogLuv32toXYZ(uint32_t p, float *XYZ)
 {
     double L, u, v, s, x, y;
     /* decode luminance */
@@ -1202,15 +1195,14 @@
 #if !LOGLUV_PUBLIC
 static
 #endif
-    uint32_t
-    LogLuv32fromXYZ(float *XYZ, int em)
+    uint32_t LogLuv32fromXYZ(float *XYZ, int em)
 {
     unsigned int Le, ue, ve;
     double u, v, s;
     /* encode luminance */
-    Le = (unsigned int)LogL16fromY(XYZ[1], em);
+    Le = (unsigned int)LogL16fromY((double)XYZ[1], em);
     /* encode color */
-    s = XYZ[0] + 15. * XYZ[1] + 3. * XYZ[2];
+    s = (double)XYZ[0] + 15. * (double)XYZ[1] + 3. * (double)XYZ[2];
     if (!Le || s <= 0.)
     {
         u = U_NEU;
@@ -1218,19 +1210,19 @@
     }
     else
     {
-        u = 4. * XYZ[0] / s;
-        v = 9. * XYZ[1] / s;
+        u = 4. * (double)XYZ[0] / s;
+        v = 9. * (double)XYZ[1] / s;
     }
     if (u <= 0.)
         ue = 0;
     else
-        ue = tiff_itrunc(UVSCALE * u, em);
+        ue = (unsigned int)tiff_itrunc(UVSCALE * u, em);
     if (ue > 255)
         ue = 255;
     if (v <= 0.)
         ve = 0;
     else
-        ve = tiff_itrunc(UVSCALE * v, em);
+        ve = (unsigned int)tiff_itrunc(UVSCALE * v, em);
     if (ve > 255)
         ve = 255;
     /* combine encodings */
@@ -1261,8 +1253,8 @@
         *luv3++ = (int16_t)(*luv >> 16);
         u = 1. / UVSCALE * ((*luv >> 8 & 0xff) + .5);
         v = 1. / UVSCALE * ((*luv & 0xff) + .5);
-        *luv3++ = (int16_t)(u * (1L << 15));
-        *luv3++ = (int16_t)(v * (1L << 15));
+        *luv3++ = (int16_t)(u * (1 << 15));
+        *luv3++ = (int16_t)(v * (1 << 15));
         luv++;
     }
 }
@@ -1303,22 +1295,24 @@
     {
         while (n-- > 0)
         {
-            *luv++ = (uint32_t)luv3[0] << 16 |
-                     (luv3[1] * (uint32_t)(UVSCALE + .5) >> 7 & 0xff00) |
-                     (luv3[2] * (uint32_t)(UVSCALE + .5) >> 15 & 0xff);
+            *luv++ =
+                (uint32_t)luv3[0] << 16 |
+                ((uint32_t)luv3[1] * (uint32_t)(UVSCALE + .5) >> 7 & 0xff00) |
+                ((uint32_t)luv3[2] * (uint32_t)(UVSCALE + .5) >> 15 & 0xff);
             luv3 += 3;
         }
         return;
     }
     while (n-- > 0)
     {
-        *luv++ =
-            (uint32_t)luv3[0] << 16 |
-            (tiff_itrunc(luv3[1] * (UVSCALE / (1 << 15)), sp->encode_meth)
-                 << 8 &
-             0xff00) |
-            (tiff_itrunc(luv3[2] * (UVSCALE / (1 << 15)), sp->encode_meth) &
-             0xff);
+        *luv++ = (uint32_t)luv3[0] << 16 |
+                 ((uint32_t)tiff_itrunc(luv3[1] * (UVSCALE / (1 << 15)),
+                                        sp->encode_meth)
+                      << 8 &
+                  0xff00) |
+                 ((uint32_t)tiff_itrunc(luv3[2] * (UVSCALE / (1 << 15)),
+                                        sp->encode_meth) &
+                  0xff);
         luv3 += 3;
     }
 }
@@ -1345,6 +1339,8 @@
         case PACK(1, 8, SAMPLEFORMAT_VOID):
         case PACK(1, 8, SAMPLEFORMAT_UINT):
             return (SGILOGDATAFMT_8BIT);
+        default:
+            break;
     }
 #undef PACK
     return (SGILOGDATAFMT_UNKNOWN);
@@ -1399,7 +1395,7 @@
         sp->tbuflen = multiply_ms(td->td_imagewidth, td->td_imagelength);
     if (multiply_ms(sp->tbuflen, sizeof(int16_t)) == 0 ||
         (sp->tbuf = (uint8_t *)_TIFFmallocExt(
-             tif, sp->tbuflen * sizeof(int16_t))) == NULL)
+             tif, (tmsize_t)((size_t)sp->tbuflen * sizeof(int16_t)))) == NULL)
     {
         TIFFErrorExtR(tif, module, "No space for SGILog translation buffer");
         return (0);
@@ -1506,7 +1502,7 @@
         sp->tbuflen = multiply_ms(td->td_imagewidth, td->td_imagelength);
     if (multiply_ms(sp->tbuflen, sizeof(uint32_t)) == 0 ||
         (sp->tbuf = (uint8_t *)_TIFFmallocExt(
-             tif, sp->tbuflen * sizeof(uint32_t))) == NULL)
+             tif, (tmsize_t)((size_t)sp->tbuflen * sizeof(uint32_t)))) == NULL)
     {
         TIFFErrorExtR(tif, module, "No space for SGILog translation buffer");
         return (0);
@@ -1546,6 +1542,8 @@
                     case SGILOGDATAFMT_8BIT:
                         sp->tfunc = Luv24toRGB;
                         break;
+                    default:
+                        break;
                 }
             }
             else
@@ -1562,6 +1560,8 @@
                     case SGILOGDATAFMT_8BIT:
                         sp->tfunc = Luv32toRGB;
                         break;
+                    default:
+                        break;
                 }
             }
             return (1);
@@ -1577,6 +1577,8 @@
                 case SGILOGDATAFMT_8BIT:
                     sp->tfunc = L16toGry;
                     break;
+                default:
+                    break;
             }
             return (1);
         default:
@@ -1755,8 +1757,9 @@
             /*
              * Must recalculate sizes should bits/sample change.
              */
-            tif->tif_tilesize = isTiled(tif) ? TIFFTileSize(tif) : (tmsize_t)-1;
-            tif->tif_scanlinesize = TIFFScanlineSize(tif);
+            tif->tif_dir.td_tilesize =
+                isTiled(tif) ? TIFFTileSize(tif) : (tmsize_t)-1;
+            tif->tif_dir.td_scanlinesize = TIFFScanlineSize(tif);
             return (1);
         case TIFFTAG_SGILOGENCODE:
             sp->encode_meth = (int)va_arg(ap, int);
diff --git a/third_party/libtiff/tif_lzw.c b/third_party/libtiff/tif_lzw.c
index 4bf845b..d9f56a4 100644
--- a/third_party/libtiff/tif_lzw.c
+++ b/third_party/libtiff/tif_lzw.c
@@ -60,7 +60,7 @@
  */
 #define LZW_COMPAT /* include backwards compatibility code */
 
-#define MAXCODE(n) ((1L << (n)) - 1)
+#define MAXCODE(n) ((1 << (n)) - 1)
 /*
  * The TIFF spec specifies that encoded bit
  * strings range from 9 to 12 bits.
@@ -72,7 +72,7 @@
 #define CODE_EOI 257   /* end-of-information code */
 #define CODE_FIRST 258 /* first free code entry */
 #define CODE_MAX MAXCODE(BITS_MAX)
-#define HSIZE 9001L /* 91% occupancy */
+#define HSIZE 9001 /* 91% occupancy */
 #define HSHIFT (13 - 8)
 #ifdef LZW_COMPAT
 /* NB: +1024 is for compatibility with old files */
@@ -325,7 +325,7 @@
  */
 
 /* Get the next 32 or 64-bit from the input data */
-#ifdef WORDS_BIGENDIAN
+#if WORDS_BIGENDIAN
 #define GetNextData(nextdata, bp) memcpy(&nextdata, bp, sizeof(nextdata))
 #elif SIZEOF_WORDTYPE == 8
 #if defined(_M_X64)
@@ -372,7 +372,7 @@
                 nextbits += 8 * SIZEOF_WORDTYPE;                               \
                 dec_bitsleft -= 8 * SIZEOF_WORDTYPE;                           \
                 code = (WordType)((codetmp | (nextdata >> nextbits)) &         \
-                                  nbitsmask);                                  \
+                                  (WordType)nbitsmask);                        \
                 break;                                                         \
             }                                                                  \
             else                                                               \
@@ -396,7 +396,7 @@
                 }                                                              \
             }                                                                  \
         }                                                                      \
-        code = (WordType)((nextdata >> nextbits) & nbitsmask);                 \
+        code = (WordType)((nextdata >> nextbits) & (WordType)nbitsmask);       \
     } while (0)
 
 static int LZWDecode(TIFF *tif, uint8_t *op0, tmsize_t occ0, uint16_t s)
@@ -420,7 +420,7 @@
         TIFFErrorExtR(tif, module,
                       "LZWDecode: Scanline %" PRIu32 " cannot be read due to "
                       "previous error",
-                      tif->tif_row);
+                      tif->tif_dir.td_row);
         return 0;
     }
 
@@ -472,7 +472,8 @@
     }
 
     bp = (uint8_t *)tif->tif_rawcp;
-    sp->dec_bitsleft += (((uint64_t)tif->tif_rawcc - sp->old_tif_rawcc) << 3);
+    sp->dec_bitsleft +=
+        (((uint64_t)tif->tif_rawcc - (uint64_t)sp->old_tif_rawcc) << 3);
     uint64_t dec_bitsleft = sp->dec_bitsleft;
     nbits = sp->lzw_nbits;
     nextdata = sp->lzw_nextdata;
@@ -493,7 +494,7 @@
 {
     WordType code;
     GetNextCodeLZW();
-    codep = dec_codetab + code;
+    codep = dec_codetab + (unsigned long)code;
     if (code >= CODE_FIRST)
         goto code_above_or_equal_to_258;
     if (code < 256)
@@ -508,7 +509,7 @@
         goto error_code;
     free_entp->next = oldcodep;
     free_entp->firstchar = oldcodep->firstchar;
-    free_entp->length = oldcodep->length + 1;
+    free_entp->length = (uint16_t)(oldcodep->length + 1);
     free_entp->value = (uint8_t)code;
     free_entp->repeated =
         (bool)(oldcodep->repeated & (oldcodep->value == code));
@@ -556,7 +557,7 @@
     free_entp->next = oldcodep;
 
     free_entp->firstchar = oldcodep->firstchar;
-    free_entp->length = oldcodep->length + 1;
+    free_entp->length = (uint16_t)(oldcodep->length + 1);
     if (++free_entp > maxcodep)
     {
         if (++nbits > BITS_MAX) /* should not happen for a conformant encoder */
@@ -673,7 +674,7 @@
     free_entp = dec_codetab + CODE_FIRST;
     nbits = BITS_MIN;
     nbitsmask = MAXCODE(BITS_MIN);
-    maxcodep = dec_codetab + nbitsmask - 1;
+    maxcodep = dec_codetab + (unsigned long)nbitsmask - 1;
     do
     {
         GetNextCodeLZW();
@@ -736,7 +737,7 @@
         TIFFErrorExtR(tif, module,
                       "Not enough data at scanline %" PRIu32 " (short %" PRIu64
                       " bytes)",
-                      tif->tif_row, (uint64_t)occ);
+                      tif->tif_dir.td_row, (uint64_t)occ);
         return (0);
     }
     return (1);
@@ -746,7 +747,7 @@
     sp->read_error = 1;
     TIFFErrorExtR(tif, module,
                   "LZWDecode: Strip %" PRIu32 " not terminated with EOI code",
-                  tif->tif_curstrip);
+                  tif->tif_dir.td_curstrip);
     return 0;
 error_code:
     memset(op, 0, (size_t)occ);
@@ -768,13 +769,13 @@
             TIFFWarningExtR(_tif, module,                                      \
                             "LZWDecode: Strip %" PRIu32                        \
                             " not terminated with EOI code",                   \
-                            _tif->tif_curstrip);                               \
+                            _tif->tif_dir.td_curstrip);                        \
             _code = CODE_EOI;                                                  \
         }                                                                      \
         else                                                                   \
         {                                                                      \
             _get(_sp, _bp, _code);                                             \
-            dec_bitsleft -= nbits;                                             \
+            dec_bitsleft -= (uint64_t)nbits;                                   \
         }                                                                      \
     }
 
@@ -790,7 +791,7 @@
             nextdata |= (unsigned long)*(bp)++ << nextbits;                    \
             nextbits += 8;                                                     \
         }                                                                      \
-        code = (hcode_t)(nextdata & nbitsmask);                                \
+        code = (hcode_t)(nextdata & (unsigned long)nbitsmask);                 \
         nextdata >>= nbits;                                                    \
         nextbits -= nbits;                                                     \
     }
@@ -858,7 +859,8 @@
 
     bp = (uint8_t *)tif->tif_rawcp;
 
-    sp->dec_bitsleft += (((uint64_t)tif->tif_rawcc - sp->old_tif_rawcc) << 3);
+    sp->dec_bitsleft +=
+        (((uint64_t)tif->tif_rawcc - (uint64_t)sp->old_tif_rawcc) << 3);
     uint64_t dec_bitsleft = sp->dec_bitsleft;
 
     nbits = sp->lzw_nbits;
@@ -893,7 +895,7 @@
                 TIFFErrorExtR(
                     tif, tif->tif_name,
                     "LZWDecode: Corrupted LZW table at scanline %" PRIu32,
-                    tif->tif_row);
+                    tif->tif_dir.td_row);
                 return (0);
             }
             *op++ = (uint8_t)code;
@@ -911,7 +913,7 @@
         {
             TIFFErrorExtR(tif, module,
                           "Corrupted LZW table at scanline %" PRIu32,
-                          tif->tif_row);
+                          tif->tif_dir.td_row);
             return (0);
         }
 
@@ -921,11 +923,11 @@
         {
             TIFFErrorExtR(tif, module,
                           "Corrupted LZW table at scanline %" PRIu32,
-                          tif->tif_row);
+                          tif->tif_dir.td_row);
             return (0);
         }
         free_entp->firstchar = free_entp->next->firstchar;
-        free_entp->length = free_entp->next->length + 1;
+        free_entp->length = (uint16_t)(free_entp->next->length + 1);
         free_entp->value =
             (codep < free_entp) ? codep->firstchar : free_entp->firstchar;
         if (++free_entp > maxcodep)
@@ -948,7 +950,7 @@
                     tif, module,
                     "Wrong length of decoded "
                     "string: data probably corrupted at scanline %" PRIu32,
-                    tif->tif_row);
+                    tif->tif_dir.td_row);
                 return (0);
             }
             if (codep->length > occ)
@@ -1010,7 +1012,7 @@
         TIFFErrorExtR(tif, module,
                       "Not enough data at scanline %" PRIu32 " (short %" PRIu64
                       " bytes)",
-                      tif->tif_row, (uint64_t)occ);
+                      tif->tif_dir.td_row, (uint64_t)occ);
         return (0);
     }
     return (1);
@@ -1116,10 +1118,10 @@
  */
 static int LZWEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
 {
-    register LZWCodecState *sp = LZWEncoderState(tif);
-    register long fcode;
-    register hash_t *hp;
-    register int h, c;
+    LZWCodecState *sp = LZWEncoderState(tif);
+    long fcode;
+    hash_t *hp;
+    int h, c;
     hcode_t ent;
     long disp;
     tmsize_t incount, outcount, checkpoint;
@@ -1196,7 +1198,7 @@
                  * Avoid pointer arithmetic because of
                  * wraparound problems with segments.
                  */
-                if ((h -= disp) < 0)
+                if ((h -= (int)disp) < 0)
                     h += HSIZE;
                 hp = &sp->enc_hashtab[h];
                 if (hp->hash == fcode)
@@ -1301,7 +1303,7 @@
  */
 static int LZWPostEncode(TIFF *tif)
 {
-    register LZWCodecState *sp = LZWEncoderState(tif);
+    LZWCodecState *sp = LZWEncoderState(tif);
     uint8_t *op = tif->tif_rawcp;
     long nextbits = sp->lzw_nextbits;
     WordType nextdata = sp->lzw_nextdata;
@@ -1319,7 +1321,7 @@
     {
         int free_ent = sp->lzw_free_ent;
 
-        PutNextCode(op, sp->enc_oldcode);
+        PutNextCode(op, (WordType)sp->enc_oldcode);
         sp->enc_oldcode = (hcode_t)-1;
         free_ent++;
 
@@ -1357,8 +1359,8 @@
  */
 static void cl_hash(LZWCodecState *sp)
 {
-    register hash_t *hp = &sp->enc_hashtab[HSIZE - 1];
-    register long i = HSIZE - 8;
+    hash_t *hp = &sp->enc_hashtab[HSIZE - 1];
+    long i = HSIZE - 8;
 
     do
     {
@@ -1397,6 +1399,21 @@
     _TIFFSetDefaultCompressionState(tif);
 }
 
+static uint64_t LZWGetMaxCompressionRatio(TIFF *tif)
+{
+    (void)tif;
+
+    /* See README_for_libtiff_developpers.md for raw data used to estimate
+     * the maximum compression rate. */
+
+    /* 1024x1024: 562 */
+    /* 4096x4096: 1243 */
+    /* 16383x16383: 1353 */
+    /* 65536x65536: 1362 */
+
+    return 1400;
+}
+
 int TIFFInitLZW(TIFF *tif, int scheme)
 {
     static const char module[] = "TIFFInitLZW";
@@ -1430,6 +1447,7 @@
     tif->tif_encodestrip = LZWEncode;
     tif->tif_encodetile = LZWEncode;
 #endif
+    tif->tif_getmaxcompressionratio = LZWGetMaxCompressionRatio;
     tif->tif_cleanup = LZWCleanup;
     /*
      * Setup predictor setup.
diff --git a/third_party/libtiff/tif_next.c b/third_party/libtiff/tif_next.c
index f000574..04ae474 100644
--- a/third_party/libtiff/tif_next.c
+++ b/third_party/libtiff/tif_next.c
@@ -38,21 +38,22 @@
                 op[0] = (unsigned char)((v) << 6);                             \
                 break;                                                         \
             case 1:                                                            \
-                op[0] |= (v) << 4;                                             \
+                op[0] |= (unsigned char)((v) << 4);                            \
                 break;                                                         \
             case 2:                                                            \
-                op[0] |= (v) << 2;                                             \
+                op[0] |= (unsigned char)((v) << 2);                            \
                 break;                                                         \
             case 3:                                                            \
-                *op++ |= (v);                                                  \
+                *op++ |= (unsigned char)(v);                                   \
                 op_offset++;                                                   \
                 break;                                                         \
+            default:                                                           \
+                break;                                                         \
         }                                                                      \
     }
 
 #define LITERALROW 0x00
 #define LITERALSPAN 0x40
-#define WHITE ((1 << 2) - 1)
 
 static int NeXTDecode(TIFF *tif, uint8_t *buf, tmsize_t occ, uint16_t s)
 {
@@ -73,7 +74,7 @@
 
     bp = (unsigned char *)tif->tif_rawcp;
     cc = tif->tif_rawcc;
-    scanline = tif->tif_scanlinesize;
+    scanline = tif->tif_dir.td_scanlinesize;
     if (occ % scanline)
     {
         TIFFErrorExtR(tif, module, "Fractional scanlines cannot be read");
@@ -146,7 +147,7 @@
                     {
                         TIFFErrorExtR(tif, module,
                                       "Invalid data for scanline %" PRIu32,
-                                      tif->tif_row);
+                                      tif->tif_dir.td_row);
                         return (0);
                     }
                     if (cc == 0)
@@ -163,7 +164,7 @@
     return (1);
 bad:
     TIFFErrorExtR(tif, module, "Not enough data for scanline %" PRIu32,
-                  tif->tif_row);
+                  tif->tif_dir.td_row);
     return (0);
 }
 
diff --git a/third_party/libtiff/tif_open.c b/third_party/libtiff/tif_open.c
index 565d13c..43cb170 100644
--- a/third_party/libtiff/tif_open.c
+++ b/third_party/libtiff/tif_open.c
@@ -77,7 +77,7 @@
     return (m);
 }
 
-TIFFOpenOptions *TIFFOpenOptionsAlloc()
+TIFFOpenOptions *TIFFOpenOptionsAlloc(void)
 {
     TIFFOpenOptions *opts =
         (TIFFOpenOptions *)_TIFFcalloc(1, sizeof(TIFFOpenOptions));
@@ -308,6 +308,7 @@
     TIFF *tif;
     int m;
     const char *cp;
+    tmsize_t size_to_alloc;
 
     /* The following are configuration checks. They should be redundant, but
      * should not compile to any actual code in an optimised release build
@@ -330,7 +331,7 @@
         n.a8[0] = 1;
         n.a8[1] = 0;
         (void)n;
-#ifdef WORDS_BIGENDIAN
+#if WORDS_BIGENDIAN
         assert(n.a16 == 256);
 #else
         assert(n.a16 == 1);
@@ -340,7 +341,7 @@
     m = _TIFFgetMode(opts, clientdata, mode, module);
     if (m == -1)
         goto bad2;
-    tmsize_t size_to_alloc = (tmsize_t)(sizeof(TIFF) + strlen(name) + 1);
+    size_to_alloc = (tmsize_t)(sizeof(TIFF) + strlen(name) + 1);
     if (opts && opts->max_single_mem_alloc > 0 &&
         size_to_alloc > opts->max_single_mem_alloc)
     {
@@ -377,8 +378,6 @@
     tif->tif_curdir = TIFF_NON_EXISTENT_DIR_NUMBER; /* non-existent directory */
     tif->tif_curdircount = TIFF_NON_EXISTENT_DIR_NUMBER;
     tif->tif_curoff = 0;
-    tif->tif_curstrip = (uint32_t)-1; /* invalid strip */
-    tif->tif_row = (uint32_t)-1;      /* read/write pre-increment */
     tif->tif_clientdata = clientdata;
     tif->tif_readproc = readproc;
     tif->tif_writeproc = writeproc;
@@ -398,6 +397,10 @@
         tif->tif_warn_about_unknown_tags = opts->warn_about_unknown_tags;
     }
 
+    /* Reset tif->tif_dir structure to zero and
+     * initialize some IFD strile counter and index parameters. */
+    _TIFFResetTifDirAndInitStrileCounters(&tif->tif_dir);
+
     if (!readproc || !writeproc || !seekproc || !closeproc || !sizeproc)
     {
         TIFFErrorExtR(tif, module,
@@ -480,13 +483,13 @@
         switch (*cp)
         {
             case 'b':
-#ifndef WORDS_BIGENDIAN
+#if !WORDS_BIGENDIAN
                 if (m & O_CREAT)
                     tif->tif_flags |= TIFF_SWAB;
 #endif
                 break;
             case 'l':
-#ifdef WORDS_BIGENDIAN
+#if WORDS_BIGENDIAN
                 if ((m & O_CREAT))
                     tif->tif_flags |= TIFF_SWAB;
 #endif
@@ -536,7 +539,9 @@
             case 'O':
                 if (m == O_RDONLY)
                     tif->tif_flags |=
-                        (TIFF_LAZYSTRILELOAD | TIFF_DEFERSTRILELOAD);
+                        (TIFF_LAZYSTRILELOAD_ASKED | TIFF_DEFERSTRILELOAD);
+                break;
+            default:
                 break;
         }
 
@@ -561,7 +566,7 @@
         /*
          * Setup header and write.
          */
-#ifdef WORDS_BIGENDIAN
+#if WORDS_BIGENDIAN
         tif->tif_header.common.tiff_magic =
             (tif->tif_flags & TIFF_SWAB) ? TIFF_LITTLEENDIAN : TIFF_BIGENDIAN;
 #else
@@ -654,13 +659,13 @@
     }
     if (tif->tif_header.common.tiff_magic == TIFF_BIGENDIAN)
     {
-#ifndef WORDS_BIGENDIAN
+#if !WORDS_BIGENDIAN
         tif->tif_flags |= TIFF_SWAB;
 #endif
     }
     else
     {
-#ifdef WORDS_BIGENDIAN
+#if WORDS_BIGENDIAN
         tif->tif_flags |= TIFF_SWAB;
 #endif
     }
@@ -780,6 +785,8 @@
             if (!TIFFDefaultDirectory(tif))
                 goto bad;
             return (tif);
+        default:
+            break;
     }
 bad:
     tif->tif_mode = O_RDONLY; /* XXX avoid flush */
@@ -861,7 +868,7 @@
 /*
  * Return current row being read/written.
  */
-uint32_t TIFFCurrentRow(TIFF *tif) { return (tif->tif_row); }
+uint32_t TIFFCurrentRow(TIFF *tif) { return (tif->tif_dir.td_row); }
 
 /*
  * Return index of the current directory.
@@ -871,12 +878,12 @@
 /*
  * Return current strip.
  */
-uint32_t TIFFCurrentStrip(TIFF *tif) { return (tif->tif_curstrip); }
+uint32_t TIFFCurrentStrip(TIFF *tif) { return (tif->tif_dir.td_curstrip); }
 
 /*
  * Return current tile.
  */
-uint32_t TIFFCurrentTile(TIFF *tif) { return (tif->tif_curtile); }
+uint32_t TIFFCurrentTile(TIFF *tif) { return (tif->tif_dir.td_curtile); }
 
 /*
  * Return nonzero if the file has byte-swapped data.
diff --git a/third_party/libtiff/tif_packbits.c b/third_party/libtiff/tif_packbits.c
index d7db9b6..13d0f1d 100644
--- a/third_party/libtiff/tif_packbits.c
+++ b/third_party/libtiff/tif_packbits.c
@@ -194,12 +194,17 @@
                  */
                 if (n == 1 && op[-2] == (uint8_t)-1 && *lastliteral < 126)
                 {
-                    state = (((*lastliteral) += 2) == 127 ? BASE : LITERAL);
+                    state =
+                        (((*lastliteral) = (uint8_t)(*lastliteral + 2)) == 127
+                             ? BASE
+                             : LITERAL);
                     op[-2] = op[-1]; /* replicate */
                 }
                 else
                     state = RUN;
                 goto again;
+            default:
+                break;
         }
     }
     tif->tif_rawcc += (tmsize_t)(op - tif->tif_rawcp);
@@ -306,12 +311,22 @@
     {
         memset(op, 0, (size_t)occ);
         TIFFErrorExtR(tif, module, "Not enough data for scanline %" PRIu32,
-                      tif->tif_row);
+                      tif->tif_dir.td_row);
         return (0);
     }
     return (1);
 }
 
+static uint64_t PackBitsGetMaxCompressionRatio(TIFF *tif)
+{
+    (void)tif;
+
+    /* See README_for_libtiff_developpers.md for raw data used to estimate
+     * the maximum compression rate. */
+
+    return 64;
+}
+
 int TIFFInitPackBits(TIFF *tif, int scheme)
 {
     (void)scheme;
@@ -325,6 +340,8 @@
     tif->tif_encodestrip = PackBitsEncodeChunk;
     tif->tif_encodetile = PackBitsEncodeChunk;
 #endif
+    tif->tif_getmaxcompressionratio = PackBitsGetMaxCompressionRatio;
+
     return (1);
 }
 #endif /* PACKBITS_SUPPORT */
diff --git a/third_party/libtiff/tif_pixarlog.c b/third_party/libtiff/tif_pixarlog.c
index 6b0d6f1..7892522 100644
--- a/third_party/libtiff/tif_pixarlog.c
+++ b/third_party/libtiff/tif_pixarlog.c
@@ -117,11 +117,11 @@
         } while (i > 0);                                                       \
     }
 
-static void horizontalAccumulateF(uint16_t *wp, int n, int stride, float *op,
-                                  float *ToLinearF)
+static void horizontalAccumulateF(uint16_t *wp, tmsize_t n, int stride,
+                                  float *op, float *ToLinearF)
 {
-    register unsigned int cr, cg, cb, ca, mask;
-    register float t0, t1, t2, t3;
+    unsigned int cr, cg, cb, ca, mask;
+    float t0, t1, t2, t3;
 
     if (n >= stride)
     {
@@ -180,22 +180,22 @@
             n -= stride;
             while (n > 0)
             {
-                REPEAT(stride, wp[stride] += *wp; *op = ToLinearF[*wp & mask];
-                       wp++; op++)
+                REPEAT(stride, *wp = (uint16_t)(*wp + wp[-stride]);
+                       *op = ToLinearF[*wp & mask]; wp++; op++)
                 n -= stride;
             }
         }
     }
 }
 
-static void horizontalAccumulate12(uint16_t *wp, int n, int stride, int16_t *op,
-                                   float *ToLinearF)
+static void horizontalAccumulate12(uint16_t *wp, tmsize_t n, int stride,
+                                   int16_t *op, float *ToLinearF)
 {
-    register unsigned int cr, cg, cb, ca, mask;
-    register float t0, t1, t2, t3;
+    unsigned int cr, cg, cb, ca, mask;
+    float t0, t1, t2, t3;
 
-#define SCALE12 2048.0F
-#define CLAMP12(t) (((t) < 3071) ? (uint16_t)(t) : 3071)
+#define SCALE12 2048.0f
+#define CLAMP12(t) (((t) < 3071) ? (int16_t)(uint16_t)(t) : (int16_t)3071)
 
     if (n >= stride)
     {
@@ -255,19 +255,19 @@
             n -= stride;
             while (n > 0)
             {
-                REPEAT(stride, wp[stride] += *wp;
-                       t0 = ToLinearF[wp[stride] & mask] * SCALE12;
-                       *op = CLAMP12(t0); wp++; op++)
+                REPEAT(stride, *wp = (uint16_t)(*wp + wp[-stride]);
+                       t0 = ToLinearF[*wp & mask] * SCALE12; *op = CLAMP12(t0);
+                       wp++; op++)
                 n -= stride;
             }
         }
     }
 }
 
-static void horizontalAccumulate16(uint16_t *wp, int n, int stride,
+static void horizontalAccumulate16(uint16_t *wp, tmsize_t n, int stride,
                                    uint16_t *op, uint16_t *ToLinear16)
 {
-    register unsigned int cr, cg, cb, ca, mask;
+    unsigned int cr, cg, cb, ca, mask;
 
     if (n >= stride)
     {
@@ -312,8 +312,8 @@
             n -= stride;
             while (n > 0)
             {
-                REPEAT(stride, wp[stride] += *wp; *op = ToLinear16[*wp & mask];
-                       wp++; op++)
+                REPEAT(stride, *wp = (uint16_t)(*wp + wp[-stride]);
+                       *op = ToLinear16[*wp & mask]; wp++; op++)
                 n -= stride;
             }
         }
@@ -324,10 +324,10 @@
  * Returns the log encoded 11-bit values with the horizontal
  * differencing undone.
  */
-static void horizontalAccumulate11(uint16_t *wp, int n, int stride,
+static void horizontalAccumulate11(uint16_t *wp, tmsize_t n, int stride,
                                    uint16_t *op)
 {
-    register unsigned int cr, cg, cb, ca, mask;
+    unsigned int cr, cg, cb, ca, mask;
 
     if (n >= stride)
     {
@@ -375,21 +375,22 @@
         }
         else
         {
-            REPEAT(stride, *op = *wp & mask; wp++; op++)
+            REPEAT(stride, *op = (uint16_t)(*wp & mask); wp++; op++)
             n -= stride;
             while (n > 0)
             {
-                REPEAT(stride, wp[stride] += *wp; *op = *wp & mask; wp++; op++)
+                REPEAT(stride, *wp = (uint16_t)(*wp + wp[-stride]);
+                       *op = (uint16_t)(*wp & mask); wp++; op++)
                 n -= stride;
             }
         }
     }
 }
 
-static void horizontalAccumulate8(uint16_t *wp, int n, int stride,
+static void horizontalAccumulate8(uint16_t *wp, tmsize_t n, int stride,
                                   unsigned char *op, unsigned char *ToLinear8)
 {
-    register unsigned int cr, cg, cb, ca, mask;
+    unsigned int cr, cg, cb, ca, mask;
 
     if (n >= stride)
     {
@@ -434,20 +435,20 @@
             n -= stride;
             while (n > 0)
             {
-                REPEAT(stride, wp[stride] += *wp; *op = ToLinear8[*wp & mask];
-                       wp++; op++)
+                REPEAT(stride, *wp = (uint16_t)(*wp + wp[-stride]);
+                       *op = ToLinear8[*wp & mask]; wp++; op++)
                 n -= stride;
             }
         }
     }
 }
 
-static void horizontalAccumulate8abgr(uint16_t *wp, int n, int stride,
+static void horizontalAccumulate8abgr(uint16_t *wp, tmsize_t n, int stride,
                                       unsigned char *op,
                                       unsigned char *ToLinear8)
 {
-    register unsigned int cr, cg, cb, ca, mask;
-    register unsigned char t0, t1, t2, t3;
+    unsigned int cr, cg, cb, ca, mask;
+    unsigned char t0, t1, t2, t3;
 
     if (n >= stride)
     {
@@ -508,8 +509,8 @@
             n -= stride;
             while (n > 0)
             {
-                REPEAT(stride, wp[stride] += *wp; *op = ToLinear8[*wp & mask];
-                       wp++; op++)
+                REPEAT(stride, *wp = (uint16_t)(*wp + wp[-stride]);
+                       *op = ToLinear8[*wp & mask]; wp++; op++)
                 n -= stride;
             }
         }
@@ -577,7 +578,8 @@
     LogK1 = (float)(1. / c); /* if (v >= 2)  token = k1*log(v*k2) */
     LogK2 = (float)(1. / b);
     lt2size = (int)(2. / linstep) + 1;
-    FromLT2 = (uint16_t *)_TIFFmallocExt(tif, lt2size * sizeof(uint16_t));
+    FromLT2 = (uint16_t *)_TIFFmallocExt(
+        tif, (tmsize_t)((size_t)lt2size * sizeof(uint16_t)));
     From14 = (uint16_t *)_TIFFmallocExt(tif, 16384 * sizeof(uint16_t));
     From8 = (uint16_t *)_TIFFmallocExt(tif, 256 * sizeof(uint16_t));
     ToLinearF = (float *)_TIFFmallocExt(tif, TSIZEP1 * sizeof(float));
@@ -623,16 +625,17 @@
 
     for (i = 0; i < TSIZEP1; i++)
     {
-        v = ToLinearF[i] * 65535.0 + 0.5;
+        v = (double)ToLinearF[i] * 65535.0 + 0.5;
         ToLinear16[i] = (v > 65535.0) ? 65535 : (uint16_t)v;
-        v = ToLinearF[i] * 255.0 + 0.5;
+        v = (double)ToLinearF[i] * 255.0 + 0.5;
         ToLinear8[i] = (v > 255.0) ? 255 : (unsigned char)v;
     }
 
     j = 0;
     for (i = 0; i < lt2size; i++)
     {
-        if ((i * linstep) * (i * linstep) > ToLinearF[j] * ToLinearF[j + 1])
+        if ((i * linstep) * (i * linstep) >
+            (double)ToLinearF[j] * (double)ToLinearF[j + 1])
             j++;
         FromLT2[i] = (uint16_t)j;
     }
@@ -645,7 +648,8 @@
     j = 0;
     for (i = 0; i < 16384; i++)
     {
-        while ((i / 16383.) * (i / 16383.) > ToLinearF[j] * ToLinearF[j + 1])
+        while ((i / 16383.) * (i / 16383.) >
+               (double)ToLinearF[j] * (double)ToLinearF[j + 1])
             j++;
         From14[i] = (uint16_t)j;
     }
@@ -653,7 +657,8 @@
     j = 0;
     for (i = 0; i < 256; i++)
     {
-        while ((i / 255.) * (i / 255.) > ToLinearF[j] * ToLinearF[j + 1])
+        while ((i / 255.) * (i / 255.) >
+               (double)ToLinearF[j] * (double)ToLinearF[j + 1])
             j++;
         From8[i] = (uint16_t)j;
     }
@@ -708,6 +713,8 @@
             if (format == SAMPLEFORMAT_VOID || format == SAMPLEFORMAT_UINT)
                 guess = PIXARLOGDATAFMT_8BIT;
             break;
+        default:
+            break;
     }
 
     return guess;
@@ -769,7 +776,8 @@
         multiply_ms(multiply_ms(sp->stride, td->td_imagewidth), strip_height),
         sizeof(uint16_t));
     /* add one more stride in case input ends mid-stride */
-    tbuf_size = add_ms(tbuf_size, sizeof(uint16_t) * sp->stride);
+    tbuf_size =
+        add_ms(tbuf_size, (tmsize_t)(sizeof(uint16_t) * (size_t)sp->stride));
     if (tbuf_size == 0)
         return (0); /* TODO: this is an error return without error report
                        through TIFFErrorExt */
@@ -838,18 +846,21 @@
     PixarLogState *sp = PixarLogDecoderState(tif);
     tmsize_t i;
     tmsize_t nsamples;
-    int llen;
+    tmsize_t llen;
     uint16_t *up;
 
     switch (sp->user_datafmt)
     {
         case PIXARLOGDATAFMT_FLOAT:
-            nsamples = occ / sizeof(float); /* XXX float == 32 bits */
+            nsamples = (tmsize_t)((uint64_t)occ /
+                                  sizeof(float)); /* XXX float == 32 bits */
             break;
         case PIXARLOGDATAFMT_16BIT:
         case PIXARLOGDATAFMT_12BITPICIO:
         case PIXARLOGDATAFMT_11BITLOG:
-            nsamples = occ / sizeof(uint16_t); /* XXX uint16_t == 16 bits */
+            nsamples =
+                (tmsize_t)((uint64_t)occ /
+                           sizeof(uint16_t)); /* XXX uint16_t == 16 bits */
             break;
         case PIXARLOGDATAFMT_8BIT:
         case PIXARLOGDATAFMT_8BITABGR:
@@ -863,7 +874,55 @@
             return 0;
     }
 
-    llen = sp->stride * td->td_imagewidth;
+    llen = (tmsize_t)sp->stride * td->td_imagewidth;
+
+    /* Fix: ABGR with stride=3 expands 3 samples to 4 output bytes per pixel */
+    if (sp->user_datafmt == PIXARLOGDATAFMT_8BITABGR && sp->stride == 3)
+    {
+        tmsize_t required = (tmsize_t)td->td_imagewidth * 4;
+        tmsize_t max_rows;
+        tmsize_t max_nsamples;
+
+        /*
+         * Ensure at least one expanded output row fits.
+         */
+        if (occ < required)
+        {
+            TIFFErrorExtR(tif, module,
+                          "Output buffer too small for PixarLog ABGR data");
+            memset(op, 0, (size_t)occ);
+            return (0);
+        }
+
+        /*
+         * The caller-provided output buffer size must represent a whole
+         * number of expanded ABGR scanlines.
+         */
+        if (occ % required)
+        {
+            TIFFErrorExtR(
+                tif, module,
+                "Fractional scanline not supported for PixarLog ABGR data");
+            memset(op, 0, (size_t)occ);
+            return (0);
+        }
+
+        /*
+         * PixarLogDecode() may process multiple rows per call
+         * (e.g. strip decoding). Limit nsamples so the total
+         * output written by the loop below never exceeds occ.
+         */
+        max_rows = occ / required;
+        max_nsamples = max_rows * llen;
+
+        if (nsamples > max_nsamples)
+        {
+            TIFFErrorExtR(tif, module,
+                          "Output buffer too small for PixarLog ABGR data");
+            memset(op, 0, (size_t)occ);
+            return (0);
+        }
+    }
 
     (void)s;
     assert(sp != NULL);
@@ -876,8 +935,8 @@
          we need to simplify this code to reflect a ZLib that is likely updated
          to deal with 8byte memory sizes, though this code will respond
          appropriately even before we simplify it */
-    sp->stream.avail_out = (uInt)(nsamples * sizeof(uint16_t));
-    if (sp->stream.avail_out != nsamples * sizeof(uint16_t))
+    sp->stream.avail_out = (uInt)((unsigned long)nsamples * sizeof(uint16_t));
+    if (sp->stream.avail_out != (unsigned long)nsamples * sizeof(uint16_t))
     {
         TIFFErrorExtR(tif, module, "ZLib cannot deal with buffers this size");
         memset(op, 0, (size_t)occ);
@@ -899,9 +958,10 @@
         }
         if (state == Z_DATA_ERROR)
         {
-            TIFFErrorExtR(
-                tif, module, "Decoding error at scanline %" PRIu32 ", %s",
-                tif->tif_row, sp->stream.msg ? sp->stream.msg : "(null)");
+            TIFFErrorExtR(tif, module,
+                          "Decoding error at scanline %" PRIu32 ", %s",
+                          tif->tif_dir.td_row,
+                          sp->stream.msg ? sp->stream.msg : "(null)");
             memset(op, 0, (size_t)occ);
             return (0);
         }
@@ -920,7 +980,7 @@
         TIFFErrorExtR(tif, module,
                       "Not enough data at scanline %" PRIu32
                       " (short %u bytes)",
-                      tif->tif_row, sp->stream.avail_out);
+                      tif->tif_dir.td_row, sp->stream.avail_out);
         memset(op, 0, (size_t)occ);
         return (0);
     }
@@ -941,7 +1001,8 @@
     if (nsamples % llen)
     {
         TIFFWarningExtR(tif, module,
-                        "stride %d is not a multiple of sample count, "
+                        "stride %" TIFF_SSIZE_FORMAT
+                        " is not a multiple of sample count, "
                         "%" TIFF_SSIZE_FORMAT ", data truncated.",
                         llen, nsamples);
         nsamples -= nsamples % llen;
@@ -954,31 +1015,37 @@
             case PIXARLOGDATAFMT_FLOAT:
                 horizontalAccumulateF(up, llen, sp->stride, (float *)op,
                                       sp->ToLinearF);
-                op += llen * sizeof(float);
+                op += (unsigned long)llen * sizeof(float);
                 break;
             case PIXARLOGDATAFMT_16BIT:
                 horizontalAccumulate16(up, llen, sp->stride, (uint16_t *)op,
                                        sp->ToLinear16);
-                op += llen * sizeof(uint16_t);
+                op += (unsigned long)llen * sizeof(uint16_t);
                 break;
             case PIXARLOGDATAFMT_12BITPICIO:
                 horizontalAccumulate12(up, llen, sp->stride, (int16_t *)op,
                                        sp->ToLinearF);
-                op += llen * sizeof(int16_t);
+                op += (unsigned long)llen * sizeof(int16_t);
                 break;
             case PIXARLOGDATAFMT_11BITLOG:
                 horizontalAccumulate11(up, llen, sp->stride, (uint16_t *)op);
-                op += llen * sizeof(uint16_t);
+                op += (unsigned long)llen * sizeof(uint16_t);
                 break;
             case PIXARLOGDATAFMT_8BIT:
                 horizontalAccumulate8(up, llen, sp->stride, (unsigned char *)op,
                                       sp->ToLinear8);
-                op += llen * sizeof(unsigned char);
+                op += (unsigned long)llen * sizeof(unsigned char);
                 break;
             case PIXARLOGDATAFMT_8BITABGR:
                 horizontalAccumulate8abgr(up, llen, sp->stride,
                                           (unsigned char *)op, sp->ToLinear8);
-                op += llen * sizeof(unsigned char);
+
+                /* For stride == 3 (RGB), horizontalAccumulate8abgr expands to 4
+                 * bytes/pixel (ABGR) */
+                if (sp->stride == 3)
+                    op += (unsigned long)td->td_imagewidth * 4;
+                else
+                    op += (unsigned long)llen * sizeof(unsigned char);
                 break;
             default:
                 TIFFErrorExtR(tif, module, "Unsupported bits/sample: %" PRIu16,
@@ -1063,17 +1130,18 @@
     return (deflateReset(&sp->stream) == Z_OK);
 }
 
-static void horizontalDifferenceF(float *ip, int n, int stride, uint16_t *wp,
-                                  uint16_t *FromLT2)
+static void horizontalDifferenceF(float *ip, tmsize_t n, int stride,
+                                  uint16_t *wp, uint16_t *FromLT2)
 {
     int32_t r1, g1, b1, a1, r2, g2, b2, a2, mask;
     float fltsize = Fltsize;
 
 #define CLAMP(v)                                                               \
-    ((v < (float)0.)     ? 0                                                   \
-     : (v < (float)2.)   ? FromLT2[(int)(v * fltsize)]                         \
-     : (v > (float)24.2) ? 2047                                                \
-                         : LogK1 * log(v * LogK2) + 0.5)
+    ((v < (float)0.)   ? 0                                                     \
+     : (v < (float)2.) ? FromLT2[(int)(v * fltsize)]                           \
+     : (v > (float)24.2)                                                       \
+         ? 2047                                                                \
+         : (double)LogK1 * log((double)v * (double)LogK2) + 0.5)
 
     mask = CODE_MASK;
     if (n >= stride)
@@ -1143,10 +1211,10 @@
     }
 }
 
-static void horizontalDifference16(unsigned short *ip, int n, int stride,
+static void horizontalDifference16(unsigned short *ip, tmsize_t n, int stride,
                                    unsigned short *wp, uint16_t *From14)
 {
-    register int r1, g1, b1, a1, r2, g2, b2, a2, mask;
+    int r1, g1, b1, a1, r2, g2, b2, a2, mask;
 
 /* assumption is unsigned pixel values */
 #undef CLAMP
@@ -1219,10 +1287,10 @@
     }
 }
 
-static void horizontalDifference8(unsigned char *ip, int n, int stride,
+static void horizontalDifference8(unsigned char *ip, tmsize_t n, int stride,
                                   unsigned short *wp, uint16_t *From8)
 {
-    register int r1, g1, b1, a1, r2, g2, b2, a2, mask;
+    int r1, g1, b1, a1, r2, g2, b2, a2, mask;
 
 #undef CLAMP
 #define CLAMP(v) (From8[(v)])
@@ -1304,7 +1372,7 @@
     PixarLogState *sp = PixarLogEncoderState(tif);
     tmsize_t i;
     tmsize_t n;
-    int llen;
+    tmsize_t llen;
     unsigned short *up;
 
     (void)s;
@@ -1312,12 +1380,14 @@
     switch (sp->user_datafmt)
     {
         case PIXARLOGDATAFMT_FLOAT:
-            n = cc / sizeof(float); /* XXX float == 32 bits */
+            n = (tmsize_t)((unsigned long)cc /
+                           sizeof(float)); /* XXX float == 32 bits */
             break;
         case PIXARLOGDATAFMT_16BIT:
         case PIXARLOGDATAFMT_12BITPICIO:
         case PIXARLOGDATAFMT_11BITLOG:
-            n = cc / sizeof(uint16_t); /* XXX uint16_t == 16 bits */
+            n = (tmsize_t)((unsigned long)cc /
+                           sizeof(uint16_t)); /* XXX uint16_t == 16 bits */
             break;
         case PIXARLOGDATAFMT_8BIT:
         case PIXARLOGDATAFMT_8BITABGR:
@@ -1330,7 +1400,7 @@
             return 0;
     }
 
-    llen = sp->stride * td->td_imagewidth;
+    llen = (tmsize_t)sp->stride * td->td_imagewidth;
     /* Check against the number of elements (of size uint16_t) of sp->tbuf */
     if (n > ((tmsize_t)td->td_rowsperstrip * llen))
     {
@@ -1345,17 +1415,17 @@
             case PIXARLOGDATAFMT_FLOAT:
                 horizontalDifferenceF((float *)bp, llen, sp->stride, up,
                                       sp->FromLT2);
-                bp += llen * sizeof(float);
+                bp += (unsigned long)llen * sizeof(float);
                 break;
             case PIXARLOGDATAFMT_16BIT:
                 horizontalDifference16((uint16_t *)bp, llen, sp->stride, up,
                                        sp->From14);
-                bp += llen * sizeof(uint16_t);
+                bp += (unsigned long)llen * sizeof(uint16_t);
                 break;
             case PIXARLOGDATAFMT_8BIT:
                 horizontalDifference8((unsigned char *)bp, llen, sp->stride, up,
                                       sp->From8);
-                bp += llen * sizeof(unsigned char);
+                bp += (unsigned long)llen * sizeof(unsigned char);
                 break;
             default:
                 TIFFErrorExtR(tif, module,
@@ -1370,8 +1440,8 @@
          we need to simplify this code to reflect a ZLib that is likely updated
          to deal with 8byte memory sizes, though this code will respond
          appropriately even before we simplify it */
-    sp->stream.avail_in = (uInt)(n * sizeof(uint16_t));
-    if ((sp->stream.avail_in / sizeof(uint16_t)) != (uInt)n)
+    sp->stream.avail_in = (uInt)((unsigned long)n * sizeof(uint16_t));
+    if ((sp->stream.avail_in / sizeof(uint16_t)) != (unsigned long)n)
     {
         TIFFErrorExtR(tif, module, "ZLib cannot deal with buffers this size");
         return (0);
@@ -1562,13 +1632,15 @@
                     TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT,
                                  SAMPLEFORMAT_IEEEFP);
                     break;
+                default:
+                    break;
             }
             /*
              * Must recalculate sizes should bits/sample change.
              */
-            tif->tif_tilesize =
+            tif->tif_dir.td_tilesize =
                 isTiled(tif) ? TIFFTileSize(tif) : (tmsize_t)(-1);
-            tif->tif_scanlinesize = TIFFScanlineSize(tif);
+            tif->tif_dir.td_scanlinesize = TIFFScanlineSize(tif);
             result = 1; /* NB: pseudo tag */
             break;
         default:
@@ -1601,6 +1673,16 @@
     {TIFFTAG_PIXARLOGQUALITY, 0, 0, TIFF_ANY, 0, TIFF_SETGET_INT, FIELD_PSEUDO,
      FALSE, FALSE, "", NULL}};
 
+static uint64_t PixarLogGetMaxCompressionRatio(TIFF *tif)
+{
+    (void)tif;
+    /* cf https://zlib.net/zlib_tech.html */
+    const uint64_t MAX_DEFLATE_RATIO = 1032;
+
+    /* security margin as I don't understand what this codec does */
+    return MAX_DEFLATE_RATIO * (uint64_t)4;
+}
+
 int TIFFInitPixarLog(TIFF *tif, int scheme)
 {
     static const char module[] = "TIFFInitPixarLog";
@@ -1648,6 +1730,7 @@
     tif->tif_encodetile = PixarLogEncode;
     tif->tif_close = PixarLogClose;
     tif->tif_cleanup = PixarLogCleanup;
+    tif->tif_getmaxcompressionratio = PixarLogGetMaxCompressionRatio;
 
     /* Override SetField so we can handle our private pseudo-tag */
     sp->vgetparent = tif->tif_tagmethods.vgetfield;
diff --git a/third_party/libtiff/tif_predict.c b/third_party/libtiff/tif_predict.c
index 7a6fc4a..18b90c2 100644
--- a/third_party/libtiff/tif_predict.c
+++ b/third_party/libtiff/tif_predict.c
@@ -30,7 +30,7 @@
 #include "tif_predict.h"
 #include "tiffiop.h"
 
-#if defined(__x86_64__) || defined(_M_X64)
+#if defined(__x86_64__) || (defined(_M_X64) && !defined(_M_ARM64EC))
 #include <emmintrin.h>
 #endif
 
@@ -151,6 +151,8 @@
             case 64:
                 sp->decodepfunc = horAcc64;
                 break;
+            default:
+                break;
         }
         /*
          * Override default decoding method with one that does the
@@ -247,6 +249,8 @@
             case 64:
                 sp->encodepfunc = horDiff64;
                 break;
+            default:
+                break;
         }
         /*
          * Override default encoding method with one that does the
@@ -590,7 +594,7 @@
     cp = (uint8_t *)cp0;
     count = 0;
 
-#if defined(__x86_64__) || defined(_M_X64)
+#if defined(__x86_64__) || (defined(_M_X64) && !defined(_M_ARM64EC))
     if (bps == 4)
     {
         /* Optimization of general case */
@@ -972,7 +976,7 @@
                       (int64_t)cc);
         return 0;
     }
-    memcpy(working_copy, bp, cc);
+    memcpy(working_copy, bp, (size_t)cc);
 
     if (!(*sp->encodepfunc)(tif, working_copy, cc))
     {
@@ -1010,7 +1014,7 @@
                       (int64_t)cc0);
         return 0;
     }
-    memcpy(working_copy, bp0, cc0);
+    memcpy(working_copy, bp0, (size_t)cc0);
     bp = working_copy;
 
     rowsize = sp->rowsize;
@@ -1098,8 +1102,10 @@
             case 3:
                 fprintf(fd, "floating point predictor ");
                 break;
+            default:
+                break;
         }
-        fprintf(fd, "%d (0x%x)\n", sp->predictor, sp->predictor);
+        fprintf(fd, "%d (0x%x)\n", sp->predictor, (unsigned)sp->predictor);
     }
     if (sp->printdir)
         (*sp->printdir)(tif, fd, flags);
diff --git a/third_party/libtiff/tif_print.c b/third_party/libtiff/tif_print.c
index addc03a..1ea450d 100644
--- a/third_party/libtiff/tif_print.c
+++ b/third_party/libtiff/tif_print.c
@@ -118,10 +118,10 @@
             if (tv_size == 8)
                 fprintf(fd, "%lf", ((double *)raw_data)[j]);
             else
-                fprintf(fd, "%f", ((float *)raw_data)[j]);
+                fprintf(fd, "%f", (double)((float *)raw_data)[j]);
         }
         else if (fip->field_type == TIFF_FLOAT)
-            fprintf(fd, "%f", ((float *)raw_data)[j]);
+            fprintf(fd, "%f", (double)((float *)raw_data)[j]);
         else if (fip->field_type == TIFF_LONG8)
             fprintf(fd, "%" PRIu64, ((uint64_t *)raw_data)[j]);
         else if (fip->field_type == TIFF_SLONG8)
@@ -193,8 +193,9 @@
         case TIFFTAG_WHITEPOINT:
             if (value_count == 2 && fip->field_type == TIFF_RATIONAL)
             {
-                fprintf(fd, "  White Point: %g-%g\n", ((float *)raw_data)[0],
-                        ((float *)raw_data)[1]);
+                fprintf(fd, "  White Point: %g-%g\n",
+                        (double)((float *)raw_data)[0],
+                        (double)((float *)raw_data)[1]);
                 return 1;
             }
             return 0;
@@ -232,6 +233,9 @@
                 return 1;
             }
             return 0;
+
+        default:
+            break;
     }
 
     return 0;
@@ -244,8 +248,7 @@
 void TIFFPrintDirectory(TIFF *tif, FILE *fd, long flags)
 {
     TIFFDirectory *td = &tif->tif_dir;
-    char *sep;
-    long l, n;
+    const char *sep;
 
     fprintf(fd, "TIFF Directory at offset 0x%" PRIx64 " (%" PRIu64 ")\n",
             tif->tif_diroff, tif->tif_diroff);
@@ -286,8 +289,8 @@
     }
     if (TIFFFieldSet(tif, FIELD_RESOLUTION))
     {
-        fprintf(fd, "  Resolution: %g, %g", td->td_xresolution,
-                td->td_yresolution);
+        fprintf(fd, "  Resolution: %g, %g", (double)td->td_xresolution,
+                (double)td->td_yresolution);
         if (TIFFFieldSet(tif, FIELD_RESOLUTIONUNIT))
         {
             switch (td->td_resolutionunit)
@@ -310,7 +313,8 @@
         fprintf(fd, "\n");
     }
     if (TIFFFieldSet(tif, FIELD_POSITION))
-        fprintf(fd, "  Position: %g, %g\n", td->td_xposition, td->td_yposition);
+        fprintf(fd, "  Position: %g, %g\n", (double)td->td_xposition,
+                (double)td->td_yposition);
     if (TIFFFieldSet(tif, FIELD_BITSPERSAMPLE))
         fprintf(fd, "  Bits/Sample: %" PRIu16 "\n", td->td_bitspersample);
     if (TIFFFieldSet(tif, FIELD_SAMPLEFORMAT))
@@ -374,7 +378,8 @@
             }
         }
     }
-    if (TIFFFieldSet(tif, FIELD_EXTRASAMPLES) && td->td_extrasamples)
+    if (TIFFFieldSet(tif, FIELD_EXTRASAMPLES) && td->td_extrasamples &&
+        td->td_sampleinfo)
     {
         uint16_t i;
         fprintf(fd, "  Extra Samples: %" PRIu16 "<", td->td_extrasamples);
@@ -412,7 +417,8 @@
              i > 0 && cp < td->td_inknames + td->td_inknameslen;
              cp = strchr(cp, '\0') + 1, i--)
         {
-            size_t max_chars = td->td_inknameslen - (cp - td->td_inknames);
+            size_t max_chars =
+                (size_t)(td->td_inknameslen - (cp - td->td_inknames));
             fputs(sep, fd);
             _TIFFprintAsciiBounded(fd, cp, max_chars);
             sep = ", ";
@@ -548,17 +554,25 @@
     if (TIFFFieldSet(tif, FIELD_PAGENUMBER))
         fprintf(fd, "  Page Number: %" PRIu16 "-%" PRIu16 "\n",
                 td->td_pagenumber[0], td->td_pagenumber[1]);
-    if (TIFFFieldSet(tif, FIELD_COLORMAP))
+    if (TIFFFieldSet(tif, FIELD_COLORMAP) && td->td_colormap[0] &&
+        td->td_colormap[1] && td->td_colormap[2])
     {
         fprintf(fd, "  Color Map: ");
         if (flags & TIFFPRINT_COLORMAP)
         {
             fprintf(fd, "\n");
-            n = 1L << td->td_bitspersample;
-            for (l = 0; l < n; l++)
-                fprintf(fd, "   %5ld: %5" PRIu16 " %5" PRIu16 " %5" PRIu16 "\n",
-                        l, td->td_colormap[0][l], td->td_colormap[1][l],
-                        td->td_colormap[2][l]);
+            if (td->td_bitspersample >= 64)
+                fprintf(fd, "   (BitsPerSample too large to print safely)\n");
+            else
+            {
+                uint64_t n = 1ULL << td->td_bitspersample;
+                for (uint64_t l = 0u; l < n; l++)
+                    fprintf(fd,
+                            "   %5" PRIu64 ": %5" PRIu16 " %5" PRIu16
+                            " %5" PRIu16 "\n",
+                            l, td->td_colormap[0][l], td->td_colormap[1][l],
+                            td->td_colormap[2][l]);
+            }
         }
         else
             fprintf(fd, "(present)\n");
@@ -569,26 +583,37 @@
         fprintf(fd, "  Reference Black/White:\n");
         for (i = 0; i < 3; i++)
             fprintf(fd, "    %2d: %5g %5g\n", i,
-                    td->td_refblackwhite[2 * i + 0],
-                    td->td_refblackwhite[2 * i + 1]);
+                    (double)td->td_refblackwhite[2 * i + 0],
+                    (double)td->td_refblackwhite[2 * i + 1]);
     }
-    if (TIFFFieldSet(tif, FIELD_TRANSFERFUNCTION))
+    if (TIFFFieldSet(tif, FIELD_TRANSFERFUNCTION) &&
+        td->td_transferfunction[0] &&
+        ((td->td_samplesperpixel - td->td_extrasamples > 1 &&
+          td->td_transferfunction[1] && td->td_transferfunction[2]) ||
+         td->td_samplesperpixel - td->td_extrasamples <= 1))
     {
         fprintf(fd, "  Transfer Function: ");
         if (flags & TIFFPRINT_CURVES)
         {
             fprintf(fd, "\n");
-            n = 1L << td->td_bitspersample;
-            for (l = 0; l < n; l++)
+            if (td->td_bitspersample >= 64)
+                fprintf(fd, "    (BitsPerSample too large to print safely)\n");
+            else
             {
-                uint16_t i;
-                fprintf(fd, "    %2ld: %5" PRIu16, l,
-                        td->td_transferfunction[0][l]);
-                for (i = 1;
-                     i < td->td_samplesperpixel - td->td_extrasamples && i < 3;
-                     i++)
-                    fprintf(fd, " %5" PRIu16, td->td_transferfunction[i][l]);
-                fputc('\n', fd);
+                uint64_t n = 1ULL << td->td_bitspersample;
+                for (uint64_t l = 0; l < n; l++)
+                {
+                    uint16_t i;
+                    fprintf(fd, "    %2" PRIu64 ": %5" PRIu16, l,
+                            td->td_transferfunction[0][l]);
+                    for (i = 1;
+                         i < td->td_samplesperpixel - td->td_extrasamples &&
+                         i < 3;
+                         i++)
+                        fprintf(fd, " %5" PRIu16,
+                                td->td_transferfunction[i][l]);
+                    fputc('\n', fd);
+                }
             }
         }
         else
@@ -655,7 +680,7 @@
                 else if (fip->field_readcount == TIFF_SPP)
                     value_count = td->td_samplesperpixel;
                 else
-                    value_count = fip->field_readcount;
+                    value_count = (uint32_t)fip->field_readcount;
                 if (fip->field_tag == TIFFTAG_DOTRANGE &&
                     strcmp(fip->field_name, "DotRange") == 0)
                 {
@@ -680,7 +705,8 @@
                      * "set_get_field_type" to determine internal storage size.
                      */
                     int tv_size = TIFFFieldSetGetSize(fip);
-                    raw_data = _TIFFmallocExt(tif, tv_size * value_count);
+                    raw_data = _TIFFCheckMalloc(tif, value_count, tv_size,
+                                                "for tag data");
                     mem_alloc = 1;
                     if (TIFFGetField(tif, tag, raw_data) != 1)
                     {
@@ -744,7 +770,7 @@
         if (*tp)
             fprintf(fd, "\\%c", *tp);
         else
-            fprintf(fd, "\\%03o", *cp & 0xff);
+            fprintf(fd, "\\%03o", (unsigned int)(*cp & 0xff));
     }
 }
 
diff --git a/third_party/libtiff/tif_read.c b/third_party/libtiff/tif_read.c
index a2bb304..d1a4e89 100644
--- a/third_party/libtiff/tif_read.c
+++ b/third_party/libtiff/tif_read.c
@@ -27,6 +27,7 @@
  * Scanline-oriented Read Support
  */
 #include "tiffiop.h"
+#include <limits.h>
 #include <stdio.h>
 
 int TIFFFillStrip(TIFF *tif, uint32_t strip);
@@ -39,9 +40,6 @@
 static tmsize_t TIFFReadRawTile1(TIFF *tif, uint32_t tile, void *buf,
                                  tmsize_t size, const char *module);
 
-#define NOSTRIP ((uint32_t)(-1)) /* undefined state */
-#define NOTILE ((uint32_t)(-1))  /* undefined state */
-
 #define INITIAL_THRESHOLD (1024 * 1024)
 #define THRESHOLD_MULTIPLIER 10
 #define MAX_THRESHOLD                                                          \
@@ -99,7 +97,9 @@
             uint8_t *new_rawdata;
             assert((tif->tif_flags & TIFF_MYBUFFER) != 0);
             tif->tif_rawdatasize = (tmsize_t)TIFFroundup_64(
-                (uint64_t)already_read + to_read + rawdata_offset, 1024);
+                (uint64_t)already_read + (uint64_t)to_read +
+                    (uint64_t)rawdata_offset,
+                1024);
             if (tif->tif_rawdatasize == 0)
             {
                 TIFFErrorExtR(tif, module, "Invalid buffer size");
@@ -111,7 +111,7 @@
             {
                 TIFFErrorExtR(tif, module,
                               "No space for data buffer at scanline %" PRIu32,
-                              tif->tif_row);
+                              tif->tif_dir.td_row);
                 _TIFFfreeExt(tif, tif->tif_rawdata);
                 tif->tif_rawdata = 0;
                 tif->tif_rawdatasize = 0;
@@ -127,18 +127,22 @@
 
         bytes_read = TIFFReadFile(
             tif, tif->tif_rawdata + rawdata_offset + already_read, to_read);
+        if (bytes_read < 0)
+            /* Treat read errors as short reads before updating offsets. */
+            bytes_read = 0;
         already_read += bytes_read;
         if (bytes_read != to_read)
         {
-            memset(tif->tif_rawdata + rawdata_offset + already_read, 0,
-                   tif->tif_rawdatasize - rawdata_offset - already_read);
+            memset(
+                tif->tif_rawdata + rawdata_offset + already_read, 0,
+                (size_t)(tif->tif_rawdatasize - rawdata_offset - already_read));
             if (is_strip)
             {
                 TIFFErrorExtR(tif, module,
                               "Read error at scanline %" PRIu32
                               "; got %" TIFF_SSIZE_FORMAT " bytes, "
                               "expected %" TIFF_SSIZE_FORMAT,
-                              tif->tif_row, already_read, size);
+                              tif->tif_dir.td_row, already_read, size);
             }
             else
             {
@@ -147,8 +151,8 @@
                               ", tile %" PRIu32 "; "
                               "got %" TIFF_SSIZE_FORMAT
                               " bytes, expected %" TIFF_SSIZE_FORMAT "",
-                              tif->tif_row, tif->tif_col, strip_or_tile,
-                              already_read, size);
+                              tif->tif_dir.td_row, tif->tif_dir.td_col,
+                              strip_or_tile, already_read, size);
             }
             return 0;
         }
@@ -160,7 +164,7 @@
                                 int restart)
 {
     static const char module[] = "TIFFFillStripPartial";
-    register TIFFDirectory *td = &tif->tif_dir;
+    TIFFDirectory *td = &tif->tif_dir;
     tmsize_t unused_data;
     uint64_t read_offset;
     tmsize_t to_read;
@@ -185,7 +189,7 @@
     {
         assert(restart);
 
-        tif->tif_curstrip = NOSTRIP;
+        tif->tif_dir.td_curstrip = NOSTRIP;
         if ((tif->tif_flags & TIFF_MYBUFFER) == 0)
         {
             TIFFErrorExtR(tif, module,
@@ -214,20 +218,30 @@
     if (unused_data > 0)
     {
         assert((tif->tif_flags & TIFF_BUFFERMMAP) == 0);
-        memmove(tif->tif_rawdata, tif->tif_rawcp, unused_data);
+        memmove(tif->tif_rawdata, tif->tif_rawcp, (size_t)unused_data);
     }
 
     /*
     ** Seek to the point in the file where more data should be read.
     */
-    read_offset = TIFFGetStrileOffset(tif, strip) + tif->tif_rawdataoff +
-                  tif->tif_rawdataloaded;
+    read_offset = TIFFGetStrileOffset(tif, (uint32_t)strip);
+    if (read_offset > UINT64_MAX - (uint64_t)tif->tif_rawdataoff ||
+        read_offset + (uint64_t)tif->tif_rawdataoff >
+            UINT64_MAX - (uint64_t)tif->tif_rawdataloaded)
+    {
+        TIFFErrorExtR(tif, module,
+                      "Seek error at scanline %" PRIu32 ", strip %d",
+                      tif->tif_dir.td_row, strip);
+        return 0;
+    }
+    read_offset +=
+        (uint64_t)tif->tif_rawdataoff + (uint64_t)tif->tif_rawdataloaded;
 
     if (!SeekOK(tif, read_offset))
     {
         TIFFErrorExtR(tif, module,
                       "Seek error at scanline %" PRIu32 ", strip %d",
-                      tif->tif_row, strip);
+                      tif->tif_dir.td_row, strip);
         return 0;
     }
 
@@ -238,11 +252,13 @@
         to_read = read_ahead_mod - unused_data;
     else
         to_read = tif->tif_rawdatasize - unused_data;
-    if ((uint64_t)to_read > TIFFGetStrileByteCount(tif, strip) -
-                                tif->tif_rawdataoff - tif->tif_rawdataloaded)
+    if ((uint64_t)to_read > TIFFGetStrileByteCount(tif, (uint32_t)strip) -
+                                (uint64_t)tif->tif_rawdataoff -
+                                (uint64_t)tif->tif_rawdataloaded)
     {
-        to_read = (tmsize_t)TIFFGetStrileByteCount(tif, strip) -
-                  tif->tif_rawdataoff - tif->tif_rawdataloaded;
+        to_read = (tmsize_t)(TIFFGetStrileByteCount(tif, (uint32_t)strip) -
+                             (uint64_t)tif->tif_rawdataoff -
+                             (uint64_t)tif->tif_rawdataloaded);
     }
 
     assert((tif->tif_flags & TIFF_BUFFERMMAP) == 0);
@@ -281,16 +297,17 @@
         /* For JPEG, if there are multiple scans (can generally be known */
         /* with the  read_ahead used), we need to read the whole strip */
         if (tif->tif_dir.td_compression == COMPRESSION_JPEG &&
-            (uint64_t)tif->tif_rawcc < TIFFGetStrileByteCount(tif, strip))
+            (uint64_t)tif->tif_rawcc <
+                TIFFGetStrileByteCount(tif, (uint32_t)strip))
         {
             if (TIFFJPEGIsFullStripRequired(tif))
             {
-                return TIFFFillStrip(tif, strip);
+                return TIFFFillStrip(tif, (uint32_t)strip);
             }
         }
 #endif
 
-        return TIFFStartStrip(tif, strip);
+        return TIFFStartStrip(tif, (uint32_t)strip);
     }
     else
     {
@@ -308,7 +325,7 @@
  */
 static int TIFFSeek(TIFF *tif, uint32_t row, uint16_t sample)
 {
-    register TIFFDirectory *td = &tif->tif_dir;
+    TIFFDirectory *td = &tif->tif_dir;
     uint32_t strip;
     int whole_strip;
     tmsize_t read_ahead = 0;
@@ -323,8 +340,16 @@
                       td->td_imagelength);
         return (0);
     }
+    if (td->td_rowsperstrip == 0)
+    {
+        TIFFErrorExtR(tif, tif->tif_name,
+                      "Cannot compute strip: RowsPerStrip is zero");
+        return (0);
+    }
     if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
     {
+        uint64_t sample_offset;
+        uint64_t strip64;
         if (sample >= td->td_samplesperpixel)
         {
             TIFFErrorExtR(tif, tif->tif_name,
@@ -332,16 +357,26 @@
                           sample, td->td_samplesperpixel);
             return (0);
         }
-        strip = (uint32_t)sample * td->td_stripsperimage +
-                row / td->td_rowsperstrip;
+        sample_offset =
+            _TIFFMultiply64(tif, sample, td->td_stripsperimage, "TIFFSeek");
+        if (sample_offset == 0 && sample != 0 && td->td_stripsperimage != 0)
+            return (0);
+        strip64 = _TIFFAdd64(tif, sample_offset, row / td->td_rowsperstrip,
+                             "TIFFSeek");
+        if (strip64 == 0 &&
+            (sample_offset != 0 || (row / td->td_rowsperstrip) != 0))
+            return (0);
+        strip = _TIFFCastUInt64ToUInt32(tif, strip64, "TIFFSeek");
+        if (strip == 0 && strip64 != 0)
+            return (0);
     }
     else
         strip = row / td->td_rowsperstrip;
 
-        /*
-         * Do we want to treat this strip as one whole chunk or
-         * read it a few lines at a time?
-         */
+    /*
+     * Do we want to treat this strip as one whole chunk or
+     * read it a few lines at a time?
+     */
 #if defined(CHUNKY_STRIP_READ_SUPPORT)
     whole_strip = TIFFGetStrileByteCount(tif, strip) < 10 || isMapped(tif);
     if (td->td_compression == COMPRESSION_LERC ||
@@ -359,14 +394,14 @@
         /* is some constant value, for example for JPEG tables */
 
         /* coverity[dead_error_line:SUPPRESS] */
-        if (tif->tif_scanlinesize < TIFF_TMSIZE_T_MAX / 16 &&
-            tif->tif_scanlinesize * 16 < TIFF_TMSIZE_T_MAX - 5000)
+        if (tif->tif_dir.td_scanlinesize < TIFF_TMSIZE_T_MAX / 16 &&
+            tif->tif_dir.td_scanlinesize * 16 < TIFF_TMSIZE_T_MAX - 5000)
         {
-            read_ahead = tif->tif_scanlinesize * 16 + 5000;
+            read_ahead = tif->tif_dir.td_scanlinesize * 16 + 5000;
         }
         else
         {
-            read_ahead = tif->tif_scanlinesize;
+            read_ahead = tif->tif_dir.td_scanlinesize;
         }
     }
 #else
@@ -377,7 +412,7 @@
      * If we haven't loaded this strip, do so now, possibly
      * only reading the first part.
      */
-    if (strip != tif->tif_curstrip)
+    if (strip != tif->tif_dir.td_curstrip)
     { /* different strip, refill */
 
         if (whole_strip)
@@ -412,7 +447,7 @@
     }
 #endif
 
-    if (row < tif->tif_row)
+    if (row < tif->tif_dir.td_row)
     {
         /*
          * Moving backwards within the same strip: backup
@@ -425,7 +460,7 @@
 
         if (tif->tif_rawdataoff != 0)
         {
-            if (!TIFFFillStripPartial(tif, strip, read_ahead, 1))
+            if (!TIFFFillStripPartial(tif, (int)strip, read_ahead, 1))
                 return 0;
         }
         else
@@ -435,7 +470,7 @@
         }
     }
 
-    if (row != tif->tif_row)
+    if (row != tif->tif_dir.td_row)
     {
         /*
          * Seek forward to the desired row.
@@ -443,9 +478,9 @@
 
         /* TODO: Will this really work with partial buffers? */
 
-        if (!(*tif->tif_seek)(tif, row - tif->tif_row))
+        if (!(*tif->tif_seek)(tif, row - tif->tif_dir.td_row))
             return (0);
-        tif->tif_row = row;
+        tif->tif_dir.td_row = row;
     }
 
     return (1);
@@ -462,20 +497,21 @@
         /*
          * Decompress desired row into user buffer.
          */
-        e = (*tif->tif_decoderow)(tif, (uint8_t *)buf, tif->tif_scanlinesize,
-                                  sample);
+        e = (*tif->tif_decoderow)(tif, (uint8_t *)buf,
+                                  tif->tif_dir.td_scanlinesize, sample);
 
         /* we are now poised at the beginning of the next row */
-        tif->tif_row = row + 1;
+        tif->tif_dir.td_row = row + 1;
 
         if (e)
-            (*tif->tif_postdecode)(tif, (uint8_t *)buf, tif->tif_scanlinesize);
+            (*tif->tif_postdecode)(tif, (uint8_t *)buf,
+                                   tif->tif_dir.td_scanlinesize);
     }
     else
     {
         /* See TIFFReadEncodedStrip comment regarding TIFFTAG_FAXFILLFUNC. */
         if (buf)
-            memset(buf, 0, (size_t)tif->tif_scanlinesize);
+            memset(buf, 0, (size_t)tif->tif_dir.td_scanlinesize);
     }
     return (e > 0 ? 1 : -1);
 }
@@ -553,9 +589,9 @@
 
         if (!isFillOrder(tif, td->td_fillorder) &&
             (tif->tif_flags & TIFF_NOBITREV) == 0)
-            TIFFReverseBits(buf, stripsize);
+            TIFFReverseBits((uint8_t *)buf, stripsize);
 
-        (*tif->tif_postdecode)(tif, buf, stripsize);
+        (*tif->tif_postdecode)(tif, (uint8_t *)buf, stripsize);
         return (stripsize);
     }
 
@@ -569,9 +605,9 @@
             memset(buf, 0, (size_t)stripsize);
         return ((tmsize_t)(-1));
     }
-    if ((*tif->tif_decodestrip)(tif, buf, stripsize, plane) <= 0)
+    if ((*tif->tif_decodestrip)(tif, (uint8_t *)buf, stripsize, plane) <= 0)
         return ((tmsize_t)(-1));
-    (*tif->tif_postdecode)(tif, buf, stripsize);
+    (*tif->tif_postdecode)(tif, (uint8_t *)buf, stripsize);
     return (stripsize);
 }
 
@@ -603,17 +639,39 @@
     if (!TIFFFillStrip(tif, strip))
         return ((tmsize_t)(-1));
 
-    *buf = _TIFFmallocExt(tif, bufsizetoalloc);
+    /* Sanity checks to avoid excessive memory allocation */
+    /* Max compression ratio experimentally determined. Might be fragile...
+     * Only apply this heuristics to situations where the memory allocation
+     * would be big, to avoid breaking nominal use cases.
+     */
+    if (bufsizetoalloc > 100 * 1024 * 1024)
+    {
+        const uint64_t maxCompressionRatio = TIFFGetMaxCompressionRatio(tif);
+        if (maxCompressionRatio > 0 &&
+            (uint64_t)tif->tif_rawdatasize <
+                (uint64_t)this_stripsize / maxCompressionRatio)
+        {
+            TIFFErrorExtR(tif, TIFFFileName(tif),
+                          "Likely invalid strip byte count for strip %u. "
+                          "Uncompressed strip size is %" PRIu64 ", "
+                          "compressed one is %" PRIu64,
+                          strip, (uint64_t)this_stripsize,
+                          (uint64_t)tif->tif_rawdatasize);
+            return ((tmsize_t)(-1));
+        }
+    }
+
+    *buf = _TIFFcallocExt(tif, 1, bufsizetoalloc);
     if (*buf == NULL)
     {
         TIFFErrorExtR(tif, TIFFFileName(tif), "No space for strip buffer");
         return ((tmsize_t)(-1));
     }
-    _TIFFmemset(*buf, 0, bufsizetoalloc);
 
-    if ((*tif->tif_decodestrip)(tif, *buf, this_stripsize, plane) <= 0)
+    if ((*tif->tif_decodestrip)(tif, (uint8_t *)*buf, this_stripsize, plane) <=
+        0)
         return ((tmsize_t)(-1));
-    (*tif->tif_postdecode)(tif, *buf, this_stripsize);
+    (*tif->tif_postdecode)(tif, (uint8_t *)*buf, this_stripsize);
     return (this_stripsize);
 }
 
@@ -629,7 +687,7 @@
         {
             TIFFErrorExtR(tif, module,
                           "Seek error at scanline %" PRIu32 ", strip %" PRIu32,
-                          tif->tif_row, strip);
+                          tif->tif_dir.td_row, strip);
             return ((tmsize_t)(-1));
         }
         cc = TIFFReadFile(tif, buf, size);
@@ -639,7 +697,7 @@
                           "Read error at scanline %" PRIu32
                           "; got %" TIFF_SSIZE_FORMAT
                           " bytes, expected %" TIFF_SSIZE_FORMAT,
-                          tif->tif_row, cc, size);
+                          tif->tif_dir.td_row, cc, size);
             return ((tmsize_t)(-1));
         }
     }
@@ -670,7 +728,7 @@
                           "Read error at scanline %" PRIu32 ", strip %" PRIu32
                           "; got %" TIFF_SSIZE_FORMAT
                           " bytes, expected %" TIFF_SSIZE_FORMAT,
-                          tif->tif_row, strip, n, size);
+                          tif->tif_dir.td_row, strip, n, size);
             return ((tmsize_t)(-1));
         }
         _TIFFmemcpy(buf, tif->tif_base + ma, size);
@@ -691,14 +749,14 @@
         {
             TIFFErrorExtR(tif, module,
                           "Seek error at scanline %" PRIu32 ", strip %" PRIu32,
-                          tif->tif_row, strip_or_tile);
+                          tif->tif_dir.td_row, strip_or_tile);
         }
         else
         {
-            TIFFErrorExtR(tif, module,
-                          "Seek error at row %" PRIu32 ", col %" PRIu32
-                          ", tile %" PRIu32,
-                          tif->tif_row, tif->tif_col, strip_or_tile);
+            TIFFErrorExtR(
+                tif, module,
+                "Seek error at row %" PRIu32 ", col %" PRIu32 ", tile %" PRIu32,
+                tif->tif_dir.td_row, tif->tif_dir.td_col, strip_or_tile);
         }
         return ((tmsize_t)(-1));
     }
@@ -774,22 +832,50 @@
         }
 
         /* To avoid excessive memory allocations: */
-        /* Byte count should normally not be larger than a number of */
-        /* times the uncompressed size plus some margin */
-        if (bytecount > 1024 * 1024)
+        const tmsize_t stripsize = TIFFStripSize(tif);
+        if (stripsize > 0)
         {
-            /* 10 and 4096 are just values that could be adjusted. */
-            /* Hopefully they are safe enough for all codecs */
-            tmsize_t stripsize = TIFFStripSize(tif);
-            if (stripsize != 0 && (bytecount - 4096) / 10 > (uint64_t)stripsize)
+            if (bytecount > 1024 * 1024 &&
+                (bytecount - 4096) / 10 > (uint64_t)stripsize)
             {
+                /* Byte count should normally not be larger than a number of */
+                /* times the uncompressed size plus some margin */
+                /* 10 and 4096 are just values that could be adjusted. */
+                /* Hopefully they are safe enough for all codecs */
+                /* What happens next will depend on whether only the bytecount
+                 */
+                /* was corrupted to a large value but the strip/tile data is */
+                /* fine. In that situation most codecs should work fine and */
+                /* only used part of the tile/strip data. If the strip/tile */
+                /* data is corrupted too, then codecs will later error out. */
                 uint64_t newbytecount = (uint64_t)stripsize * 10 + 4096;
-                TIFFErrorExtR(tif, module,
-                              "Too large strip byte count %" PRIu64
-                              ", strip %" PRIu32 ". Limiting to %" PRIu64,
-                              bytecount, strip, newbytecount);
+                TIFFWarningExtR(tif, module,
+                                "Too large strip byte count %" PRIu64
+                                ", strip %" PRIu32 ". Limiting to %" PRIu64,
+                                bytecount, strip, newbytecount);
                 bytecount = newbytecount;
             }
+            else if (stripsize > 100 * 1024 * 1024)
+            {
+                /* Max compression ratio experimentally determined. Might be
+                 * fragile... Only apply this heuristics to situations where the
+                 * memory allocation would be big, to avoid breaking nominal use
+                 * cases.
+                 */
+                const uint64_t maxCompressionRatio =
+                    TIFFGetMaxCompressionRatio(tif);
+                if (maxCompressionRatio > 0 &&
+                    bytecount < (uint64_t)stripsize / maxCompressionRatio)
+                {
+                    TIFFErrorExtR(
+                        tif, module,
+                        "Likely invalid strip byte count for strip %u. "
+                        "Uncompressed strip size is %" PRIu64 ", "
+                        "compressed one is %" PRIu64,
+                        strip, (uint64_t)stripsize, bytecount);
+                    return 0;
+                }
+            }
         }
 
         if (isMapped(tif))
@@ -818,10 +904,10 @@
                     "Read error on strip %" PRIu32 "; "
                     "got %" PRIu64 " bytes, expected %" PRIu64,
                     strip,
-                    NoSanitizeSubUInt64(tif->tif_size,
+                    NoSanitizeSubUInt64((uint64_t)tif->tif_size,
                                         TIFFGetStrileOffset(tif, strip)),
                     bytecount);
-                tif->tif_curstrip = NOSTRIP;
+                tif->tif_dir.td_curstrip = NOSTRIP;
                 return (0);
             }
         }
@@ -878,7 +964,7 @@
             }
             if (bytecountm > tif->tif_rawdatasize)
             {
-                tif->tif_curstrip = NOSTRIP;
+                tif->tif_dir.td_curstrip = NOSTRIP;
                 if ((tif->tif_flags & TIFF_MYBUFFER) == 0)
                 {
                     TIFFErrorExtR(
@@ -889,7 +975,7 @@
             }
             if (tif->tif_flags & TIFF_BUFFERMMAP)
             {
-                tif->tif_curstrip = NOSTRIP;
+                tif->tif_dir.td_curstrip = NOSTRIP;
                 tif->tif_rawdata = NULL;
                 tif->tif_rawdatasize = 0;
                 tif->tif_flags &= ~TIFF_BUFFERMMAP;
@@ -954,7 +1040,7 @@
 {
     static const char module[] = "TIFFReadEncodedTile";
     TIFFDirectory *td = &tif->tif_dir;
-    tmsize_t tilesize = tif->tif_tilesize;
+    tmsize_t tilesize = tif->tif_dir.td_tilesize;
 
     if (!TIFFCheckRead(tif, 1))
         return ((tmsize_t)(-1));
@@ -976,9 +1062,9 @@
 
         if (!isFillOrder(tif, td->td_fillorder) &&
             (tif->tif_flags & TIFF_NOBITREV) == 0)
-            TIFFReverseBits(buf, tilesize);
+            TIFFReverseBits((uint8_t *)buf, tilesize);
 
-        (*tif->tif_postdecode)(tif, buf, tilesize);
+        (*tif->tif_postdecode)(tif, (uint8_t *)buf, tilesize);
         return (tilesize);
     }
 
@@ -1032,7 +1118,7 @@
 {
     static const char module[] = "_TIFFReadEncodedTileAndAllocBuffer";
     TIFFDirectory *td = &tif->tif_dir;
-    tmsize_t tilesize = tif->tif_tilesize;
+    tmsize_t tilesize = tif->tif_dir.td_tilesize;
 
     if (*buf != NULL)
     {
@@ -1072,25 +1158,22 @@
          * Only apply this heuristics to situations where the memory allocation
          * would be big, to avoid breaking nominal use cases.
          */
-        const int maxCompressionRatio =
-            td->td_compression == COMPRESSION_ZSTD ? 33000
-            : td->td_compression == COMPRESSION_JXL
-                ?
-                /* Evaluated on a 8000x8000 tile */
-                25000 * (td->td_planarconfig == PLANARCONFIG_CONTIG
-                             ? td->td_samplesperpixel
-                             : 1)
-                : td->td_compression == COMPRESSION_LZMA ? 7000 : 1000;
-        if (bufsizetoalloc > 100 * 1000 * 1000 &&
-            tif->tif_rawdatasize < tilesize / maxCompressionRatio)
+        if (bufsizetoalloc > 100 * 1024 * 1024)
         {
-            TIFFErrorExtR(tif, TIFFFileName(tif),
-                          "Likely invalid tile byte count for tile %u. "
-                          "Uncompressed tile size is %" PRIu64 ", "
-                          "compressed one is %" PRIu64,
-                          tile, (uint64_t)tilesize,
-                          (uint64_t)tif->tif_rawdatasize);
-            return ((tmsize_t)(-1));
+            const uint64_t maxCompressionRatio =
+                TIFFGetMaxCompressionRatio(tif);
+            if (maxCompressionRatio > 0 &&
+                (uint64_t)tif->tif_rawdatasize <
+                    (uint64_t)tilesize / maxCompressionRatio)
+            {
+                TIFFErrorExtR(tif, TIFFFileName(tif),
+                              "Likely invalid tile byte count for tile %u. "
+                              "Uncompressed tile size is %" PRIu64 ", "
+                              "compressed one is %" PRIu64,
+                              tile, (uint64_t)tilesize,
+                              (uint64_t)tif->tif_rawdatasize);
+                return ((tmsize_t)(-1));
+            }
         }
     }
 
@@ -1129,7 +1212,7 @@
             TIFFErrorExtR(tif, module,
                           "Seek error at row %" PRIu32 ", col %" PRIu32
                           ", tile %" PRIu32,
-                          tif->tif_row, tif->tif_col, tile);
+                          tif->tif_dir.td_row, tif->tif_dir.td_col, tile);
             return ((tmsize_t)(-1));
         }
         cc = TIFFReadFile(tif, buf, size);
@@ -1139,7 +1222,7 @@
                           "Read error at row %" PRIu32 ", col %" PRIu32
                           "; got %" TIFF_SSIZE_FORMAT
                           " bytes, expected %" TIFF_SSIZE_FORMAT,
-                          tif->tif_row, tif->tif_col, cc, size);
+                          tif->tif_dir.td_row, tif->tif_dir.td_col, cc, size);
             return ((tmsize_t)(-1));
         }
     }
@@ -1162,7 +1245,8 @@
                           "Read error at row %" PRIu32 ", col %" PRIu32
                           ", tile %" PRIu32 "; got %" TIFF_SSIZE_FORMAT
                           " bytes, expected %" TIFF_SSIZE_FORMAT,
-                          tif->tif_row, tif->tif_col, tile, n, size);
+                          tif->tif_dir.td_row, tif->tif_dir.td_col, tile, n,
+                          size);
             return ((tmsize_t)(-1));
         }
         _TIFFmemcpy(buf, tif->tif_base + ma, size);
@@ -1229,22 +1313,49 @@
         }
 
         /* To avoid excessive memory allocations: */
-        /* Byte count should normally not be larger than a number of */
-        /* times the uncompressed size plus some margin */
-        if (bytecount > 1024 * 1024)
+        const tmsize_t tilesize = TIFFTileSize(tif);
+        if (tilesize > 0)
         {
-            /* 10 and 4096 are just values that could be adjusted. */
-            /* Hopefully they are safe enough for all codecs */
-            tmsize_t stripsize = TIFFTileSize(tif);
-            if (stripsize != 0 && (bytecount - 4096) / 10 > (uint64_t)stripsize)
+            if (bytecount > 1024 * 1024 &&
+                (bytecount - 4096) / 10 > (uint64_t)tilesize)
             {
-                uint64_t newbytecount = (uint64_t)stripsize * 10 + 4096;
-                TIFFErrorExtR(tif, module,
-                              "Too large tile byte count %" PRIu64
-                              ", tile %" PRIu32 ". Limiting to %" PRIu64,
-                              bytecount, tile, newbytecount);
+                /* Byte count should normally not be larger than a number of */
+                /* times the uncompressed size plus some margin */
+                /* 10 and 4096 are just values that could be adjusted. */
+                /* Hopefully they are safe enough for all codecs */
+                /* What happens next will depend on whether only the bytecount
+                 */
+                /* was corrupted to a large value but the strip/tile data is */
+                /* fine. In that situation most codecs should work fine and */
+                /* only used part of the tile/strip data. If the strip/tile */
+                /* data is corrupted too, then codecs will later error out. */
+                uint64_t newbytecount = (uint64_t)tilesize * 10 + 4096;
+                TIFFWarningExtR(tif, module,
+                                "Too large tile byte count %" PRIu64
+                                ", tile %" PRIu32 ". Limiting to %" PRIu64,
+                                bytecount, tile, newbytecount);
                 bytecount = newbytecount;
             }
+            else if (tilesize > 100 * 1024 * 1024)
+            {
+                /* Max compression ratio experimentally determined. Might be
+                 * fragile... Only apply this heuristics to situations where the
+                 * memory allocation would be big, to avoid breaking nominal use
+                 * cases.
+                 */
+                const uint64_t maxCompressionRatio =
+                    TIFFGetMaxCompressionRatio(tif);
+                if (maxCompressionRatio > 0 &&
+                    bytecount < (uint64_t)tilesize / maxCompressionRatio)
+                {
+                    TIFFErrorExtR(tif, module,
+                                  "Likely invalid tile byte count for tile %u. "
+                                  "Uncompressed tile size is %" PRIu64 ", "
+                                  "compressed one is %" PRIu64,
+                                  tile, (uint64_t)tilesize, bytecount);
+                    return 0;
+                }
+            }
         }
 
         if (isMapped(tif))
@@ -1262,7 +1373,7 @@
                 TIFFGetStrileOffset(tif, tile) >
                     (uint64_t)tif->tif_size - bytecount)
             {
-                tif->tif_curtile = NOTILE;
+                tif->tif_dir.td_curtile = NOTILE;
                 return (0);
             }
         }
@@ -1312,7 +1423,7 @@
             }
             if (bytecountm > tif->tif_rawdatasize)
             {
-                tif->tif_curtile = NOTILE;
+                tif->tif_dir.td_curtile = NOTILE;
                 if ((tif->tif_flags & TIFF_MYBUFFER) == 0)
                 {
                     TIFFErrorExtR(tif, module,
@@ -1323,7 +1434,7 @@
             }
             if (tif->tif_flags & TIFF_BUFFERMMAP)
             {
-                tif->tif_curtile = NOTILE;
+                tif->tif_dir.td_curtile = NOTILE;
                 tif->tif_rawdata = NULL;
                 tif->tif_rawdatasize = 0;
                 tif->tif_flags &= ~TIFF_BUFFERMMAP;
@@ -1410,7 +1521,7 @@
     {
         TIFFErrorExtR(tif, module,
                       "No space for data buffer at scanline %" PRIu32,
-                      tif->tif_row);
+                      tif->tif_dir.td_row);
         tif->tif_rawdatasize = 0;
         return (0);
     }
@@ -1431,8 +1542,13 @@
             return (0);
         tif->tif_flags |= TIFF_CODERSETUP;
     }
-    tif->tif_curstrip = strip;
-    tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip;
+    if (td->td_stripsperimage == 0)
+    {
+        TIFFErrorExtR(tif, "TIFFStartStrip", "Zero strips per image");
+        return 0;
+    }
+    tif->tif_dir.td_curstrip = strip;
+    tif->tif_dir.td_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip;
     tif->tif_flags &= ~TIFF_BUF4WRITE;
 
     if (tif->tif_flags & TIFF_NOREADRAW)
@@ -1456,7 +1572,7 @@
          */
         /* tif_curstrip, we'd call tif_decoderow() on a possibly invalid */
         /* codec state. */
-        tif->tif_curstrip = NOSTRIP;
+        tif->tif_dir.td_curstrip = NOSTRIP;
         return 0;
     }
     return 1;
@@ -1478,7 +1594,7 @@
             return (0);
         tif->tif_flags |= TIFF_CODERSETUP;
     }
-    tif->tif_curtile = tile;
+    tif->tif_dir.td_curtile = tile;
     if (td->td_tilewidth == 0)
     {
         TIFFErrorExtR(tif, module, "Zero tilewidth");
@@ -1490,14 +1606,14 @@
         TIFFErrorExtR(tif, module, "Zero tiles");
         return 0;
     }
-    tif->tif_row = (tile % howmany32) * td->td_tilelength;
+    tif->tif_dir.td_row = (tile % howmany32) * td->td_tilelength;
     howmany32 = TIFFhowmany_32(td->td_imagelength, td->td_tilelength);
     if (howmany32 == 0)
     {
         TIFFErrorExtR(tif, module, "Zero tiles");
         return 0;
     }
-    tif->tif_col = (tile % howmany32) * td->td_tilewidth;
+    tif->tif_dir.td_col = (tile % howmany32) * td->td_tilewidth;
     tif->tif_flags &= ~TIFF_BUF4WRITE;
     if (tif->tif_flags & TIFF_NOREADRAW)
     {
@@ -1568,14 +1684,14 @@
     tif->tif_flags &= ~TIFF_MYBUFFER;
     tif->tif_flags |= TIFF_BUFFERMMAP;
     tif->tif_rawdatasize = insize;
-    tif->tif_rawdata = inbuf;
+    tif->tif_rawdata = (uint8_t *)inbuf;
     tif->tif_rawdataoff = 0;
     tif->tif_rawdataloaded = insize;
 
     if (!isFillOrder(tif, td->td_fillorder) &&
         (tif->tif_flags & TIFF_NOBITREV) == 0)
     {
-        TIFFReverseBits(inbuf, insize);
+        TIFFReverseBits((uint8_t *)inbuf, insize);
     }
 
     if (TIFFIsTiled(tif))
@@ -1632,13 +1748,13 @@
     if (!isFillOrder(tif, td->td_fillorder) &&
         (tif->tif_flags & TIFF_NOBITREV) == 0)
     {
-        TIFFReverseBits(inbuf, insize);
+        TIFFReverseBits((uint8_t *)inbuf, insize);
     }
 
     tif->tif_flags = (old_tif_flags & (TIFF_MYBUFFER | TIFF_BUFFERMMAP)) |
                      (tif->tif_flags & ~(TIFF_MYBUFFER | TIFF_BUFFERMMAP));
     tif->tif_rawdatasize = old_rawdatasize;
-    tif->tif_rawdata = old_rawdata;
+    tif->tif_rawdata = (uint8_t *)old_rawdata;
     tif->tif_rawdataoff = 0;
     tif->tif_rawdataloaded = 0;
 
diff --git a/third_party/libtiff/tif_strip.c b/third_party/libtiff/tif_strip.c
index c9ba393..b07bf9f 100644
--- a/third_party/libtiff/tif_strip.c
+++ b/third_party/libtiff/tif_strip.c
@@ -47,6 +47,8 @@
     strip = row / td->td_rowsperstrip;
     if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
     {
+        uint64_t sample_offset;
+        uint64_t strip64;
         if (sample >= td->td_samplesperpixel)
         {
             TIFFErrorExtR(tif, module, "%lu: Sample out of range, max %lu",
@@ -54,7 +56,16 @@
                           (unsigned long)td->td_samplesperpixel);
             return (0);
         }
-        strip += (uint32_t)sample * td->td_stripsperimage;
+        sample_offset = _TIFFMultiply64(tif, sample, td->td_stripsperimage,
+                                        "TIFFComputeStrip");
+        if (sample_offset == 0 && sample != 0 && td->td_stripsperimage != 0)
+            return (0);
+        strip64 = _TIFFAdd64(tif, sample_offset, strip, "TIFFComputeStrip");
+        if (strip64 == 0 && (sample_offset != 0 || strip != 0))
+            return (0);
+        strip = _TIFFCastUInt64ToUInt32(tif, strip64, "TIFFComputeStrip");
+        if (strip == 0 && strip64 != 0)
+            return (0);
     }
     return (strip);
 }
@@ -83,14 +94,24 @@
 }
 
 /*
- * Compute the # bytes in a variable height, row-aligned strip.
+ * Compute the # bytes in a variable height, row-aligned strip if isStrip is
+ * TRUE, or in a tile if isStrip is FALSE
  */
-uint64_t TIFFVStripSize64(TIFF *tif, uint32_t nrows)
+uint64_t _TIFFStrileSize64(TIFF *tif, uint32_t nrows, int isStrip)
 {
-    static const char module[] = "TIFFVStripSize64";
+    static const char module[] = "_TIFFStrileSize64";
     TIFFDirectory *td = &tif->tif_dir;
-    if (nrows == (uint32_t)(-1))
-        nrows = td->td_imagelength;
+    if (isStrip)
+    {
+        if (nrows == (uint32_t)(-1))
+            nrows = td->td_imagelength;
+    }
+    else
+    {
+        if (td->td_tilelength == 0 || td->td_tilewidth == 0 ||
+            td->td_tiledepth == 0)
+            return (0);
+    }
     if ((td->td_planarconfig == PLANARCONFIG_CONTIG) &&
         (td->td_photometric == PHOTOMETRIC_YCBCR) && (!isUpSampled(tif)))
     {
@@ -125,9 +146,10 @@
                           ycbcrsubsampling[0], ycbcrsubsampling[1]);
             return 0;
         }
-        samplingblock_samples = ycbcrsubsampling[0] * ycbcrsubsampling[1] + 2;
-        samplingblocks_hor =
-            TIFFhowmany_32(td->td_imagewidth, ycbcrsubsampling[0]);
+        samplingblock_samples =
+            (uint16_t)(ycbcrsubsampling[0] * ycbcrsubsampling[1] + 2);
+        const uint32_t width = isStrip ? td->td_imagewidth : td->td_tilewidth;
+        samplingblocks_hor = TIFFhowmany_32(width, ycbcrsubsampling[0]);
         samplingblocks_ver = TIFFhowmany_32(nrows, ycbcrsubsampling[1]);
         samplingrow_samples = _TIFFMultiply64(tif, samplingblocks_hor,
                                               samplingblock_samples, module);
@@ -137,8 +159,20 @@
             _TIFFMultiply64(tif, samplingrow_size, samplingblocks_ver, module));
     }
     else
-        return (_TIFFMultiply64(tif, nrows, TIFFScanlineSize64(tif), module));
+        return (_TIFFMultiply64(tif, nrows,
+                                isStrip ? TIFFScanlineSize64(tif)
+                                        : TIFFTileRowSize64(tif),
+                                module));
 }
+
+/*
+ * Compute the # bytes in a variable height, row-aligned strip.
+ */
+uint64_t TIFFVStripSize64(TIFF *tif, uint32_t nrows)
+{
+    return _TIFFStrileSize64(tif, nrows, /* isStrip = */ TRUE);
+}
+
 tmsize_t TIFFVStripSize(TIFF *tif, uint32_t nrows)
 {
     static const char module[] = "TIFFVStripSize";
@@ -286,7 +320,7 @@
                 return 0;
             }
             samplingblock_samples =
-                ycbcrsubsampling[0] * ycbcrsubsampling[1] + 2;
+                (uint16_t)(ycbcrsubsampling[0] * ycbcrsubsampling[1] + 2);
             samplingblocks_hor =
                 TIFFhowmany_32(td->td_imagewidth, ycbcrsubsampling[0]);
             samplingrow_samples = _TIFFMultiply64(
diff --git a/third_party/libtiff/tif_swab.c b/third_party/libtiff/tif_swab.c
index 827b025..50fe635 100644
--- a/third_party/libtiff/tif_swab.c
+++ b/third_party/libtiff/tif_swab.c
@@ -32,7 +32,7 @@
 #if defined(DISABLE_CHECK_TIFFSWABMACROS) || !defined(TIFFSwabShort)
 void TIFFSwabShort(uint16_t *wp)
 {
-    register unsigned char *cp = (unsigned char *)wp;
+    unsigned char *cp = (unsigned char *)wp;
     unsigned char t;
     assert(sizeof(uint16_t) == 2);
     t = cp[1];
@@ -44,7 +44,7 @@
 #if defined(DISABLE_CHECK_TIFFSWABMACROS) || !defined(TIFFSwabLong)
 void TIFFSwabLong(uint32_t *lp)
 {
-    register unsigned char *cp = (unsigned char *)lp;
+    unsigned char *cp = (unsigned char *)lp;
     unsigned char t;
     assert(sizeof(uint32_t) == 4);
     t = cp[3];
@@ -59,7 +59,7 @@
 #if defined(DISABLE_CHECK_TIFFSWABMACROS) || !defined(TIFFSwabLong8)
 void TIFFSwabLong8(uint64_t *lp)
 {
-    register unsigned char *cp = (unsigned char *)lp;
+    unsigned char *cp = (unsigned char *)lp;
     unsigned char t;
     assert(sizeof(uint64_t) == 8);
     t = cp[7];
@@ -78,10 +78,10 @@
 #endif
 
 #if defined(DISABLE_CHECK_TIFFSWABMACROS) || !defined(TIFFSwabArrayOfShort)
-void TIFFSwabArrayOfShort(register uint16_t *wp, tmsize_t n)
+void TIFFSwabArrayOfShort(uint16_t *wp, tmsize_t n)
 {
-    register unsigned char *cp;
-    register unsigned char t;
+    unsigned char *cp;
+    unsigned char t;
     assert(sizeof(uint16_t) == 2);
     /* XXX unroll loop some */
     while (n-- > 0)
@@ -96,7 +96,7 @@
 #endif
 
 #if defined(DISABLE_CHECK_TIFFSWABMACROS) || !defined(TIFFSwabArrayOfTriples)
-void TIFFSwabArrayOfTriples(register uint8_t *tp, tmsize_t n)
+void TIFFSwabArrayOfTriples(uint8_t *tp, tmsize_t n)
 {
     unsigned char *cp;
     unsigned char t;
@@ -114,10 +114,10 @@
 #endif
 
 #if defined(DISABLE_CHECK_TIFFSWABMACROS) || !defined(TIFFSwabArrayOfLong)
-void TIFFSwabArrayOfLong(register uint32_t *lp, tmsize_t n)
+void TIFFSwabArrayOfLong(uint32_t *lp, tmsize_t n)
 {
-    register unsigned char *cp;
-    register unsigned char t;
+    unsigned char *cp;
+    unsigned char t;
     assert(sizeof(uint32_t) == 4);
     /* XXX unroll loop some */
     while (n-- > 0)
@@ -135,10 +135,10 @@
 #endif
 
 #if defined(DISABLE_CHECK_TIFFSWABMACROS) || !defined(TIFFSwabArrayOfLong8)
-void TIFFSwabArrayOfLong8(register uint64_t *lp, tmsize_t n)
+void TIFFSwabArrayOfLong8(uint64_t *lp, tmsize_t n)
 {
-    register unsigned char *cp;
-    register unsigned char t;
+    unsigned char *cp;
+    unsigned char t;
     assert(sizeof(uint64_t) == 8);
     /* XXX unroll loop some */
     while (n-- > 0)
@@ -164,7 +164,7 @@
 #if defined(DISABLE_CHECK_TIFFSWABMACROS) || !defined(TIFFSwabFloat)
 void TIFFSwabFloat(float *fp)
 {
-    register unsigned char *cp = (unsigned char *)fp;
+    unsigned char *cp = (unsigned char *)fp;
     unsigned char t;
     assert(sizeof(float) == 4);
     t = cp[3];
@@ -177,10 +177,10 @@
 #endif
 
 #if defined(DISABLE_CHECK_TIFFSWABMACROS) || !defined(TIFFSwabArrayOfFloat)
-void TIFFSwabArrayOfFloat(register float *fp, tmsize_t n)
+void TIFFSwabArrayOfFloat(float *fp, tmsize_t n)
 {
-    register unsigned char *cp;
-    register unsigned char t;
+    unsigned char *cp;
+    unsigned char t;
     assert(sizeof(float) == 4);
     /* XXX unroll loop some */
     while (n-- > 0)
@@ -200,7 +200,7 @@
 #if defined(DISABLE_CHECK_TIFFSWABMACROS) || !defined(TIFFSwabDouble)
 void TIFFSwabDouble(double *dp)
 {
-    register unsigned char *cp = (unsigned char *)dp;
+    unsigned char *cp = (unsigned char *)dp;
     unsigned char t;
     assert(sizeof(double) == 8);
     t = cp[7];
@@ -221,8 +221,8 @@
 #if defined(DISABLE_CHECK_TIFFSWABMACROS) || !defined(TIFFSwabArrayOfDouble)
 void TIFFSwabArrayOfDouble(double *dp, tmsize_t n)
 {
-    register unsigned char *cp;
-    register unsigned char t;
+    unsigned char *cp;
+    unsigned char t;
     assert(sizeof(double) == 8);
     /* XXX unroll loop some */
     while (n-- > 0)
diff --git a/third_party/libtiff/tif_thunder.c b/third_party/libtiff/tif_thunder.c
index bac0607..0c688db 100644
--- a/third_party/libtiff/tif_thunder.c
+++ b/third_party/libtiff/tif_thunder.c
@@ -41,7 +41,7 @@
  * or 3-bit delta values are used, with the deltas packed
  * into a single byte.
  */
-#define THUNDER_DATA 0x3f /* mask for 6-bit data */
+// #define THUNDER_DATA 0x3f /* mask for 6-bit data */
 #define THUNDER_CODE 0xc0 /* mask for 2-bit code word */
 /* code values */
 #define THUNDER_RUN 0x00        /* run of pixels w/ encoded count */
@@ -56,11 +56,11 @@
 
 #define SETPIXEL(op, v)                                                        \
     {                                                                          \
-        lastpixel = (v)&0xf;                                                   \
+        lastpixel = (v) & 0xf;                                                 \
         if (npixels < maxpixels)                                               \
         {                                                                      \
             if (npixels++ & 1)                                                 \
-                *op++ |= lastpixel;                                            \
+                *op++ |= (uint8_t)lastpixel;                                   \
             else                                                               \
                 op[0] = (uint8_t)(lastpixel << 4);                             \
         }                                                                      \
@@ -85,8 +85,8 @@
 static int ThunderDecode(TIFF *tif, uint8_t *op0, tmsize_t maxpixels)
 {
     static const char module[] = "ThunderDecode";
-    register unsigned char *bp;
-    register tmsize_t cc;
+    unsigned char *bp;
+    tmsize_t cc;
     unsigned int lastpixel;
     tmsize_t npixels;
     uint8_t *op = op0;
@@ -112,7 +112,7 @@
                     break;
                 if (npixels & 1)
                 {
-                    op[0] |= lastpixel;
+                    op[0] |= (uint8_t)lastpixel;
                     lastpixel = *op++;
                     npixels++;
                     n--;
@@ -150,6 +150,8 @@
             case THUNDER_RAW: /* raw data */
                 SETPIXEL(op, n);
                 break;
+            default:
+                break;
         }
     }
     tif->tif_rawcp = (uint8_t *)bp;
@@ -161,7 +163,7 @@
         TIFFErrorExtR(tif, module,
                       "%s data at scanline %lu (%" PRIu64 " != %" PRIu64 ")",
                       npixels < maxpixels ? "Not enough" : "Too much",
-                      (unsigned long)tif->tif_row, (uint64_t)npixels,
+                      (unsigned long)tif->tif_dir.td_row, (uint64_t)npixels,
                       (uint64_t)maxpixels);
         return (0);
     }
@@ -175,7 +177,7 @@
     uint8_t *row = buf;
 
     (void)s;
-    if (occ % tif->tif_scanlinesize)
+    if (occ % tif->tif_dir.td_scanlinesize)
     {
         TIFFErrorExtR(tif, module, "Fractional scanlines cannot be read");
         return (0);
@@ -184,8 +186,8 @@
     {
         if (!ThunderDecode(tif, row, tif->tif_dir.td_imagewidth))
             return (0);
-        occ -= tif->tif_scanlinesize;
-        row += tif->tif_scanlinesize;
+        occ -= tif->tif_dir.td_scanlinesize;
+        row += tif->tif_dir.td_scanlinesize;
     }
     return (1);
 }
diff --git a/third_party/libtiff/tif_tile.c b/third_party/libtiff/tif_tile.c
index f07032f..f907609 100644
--- a/third_party/libtiff/tif_tile.c
+++ b/third_party/libtiff/tif_tile.c
@@ -54,12 +54,50 @@
         uint32_t xpt = TIFFhowmany_32(td->td_imagewidth, dx);
         uint32_t ypt = TIFFhowmany_32(td->td_imagelength, dy);
         uint32_t zpt = TIFFhowmany_32(td->td_imagedepth, dz);
+        uint32_t xpt_ypt = _TIFFMultiply32(tif, xpt, ypt, "TIFFComputeTile");
+        uint32_t xpt_ypt_zpt =
+            _TIFFMultiply32(tif, xpt_ypt, zpt, "TIFFComputeTile");
+        uint64_t z_offset;
+        uint64_t y_offset;
+        uint64_t tile64;
 
+        if ((xpt_ypt == 0 && xpt != 0 && ypt != 0) ||
+            (xpt_ypt_zpt == 0 && xpt_ypt != 0 && zpt != 0))
+            return (0);
+
+        z_offset = _TIFFMultiply64(tif, xpt_ypt, z / dz, "TIFFComputeTile");
+        y_offset = _TIFFMultiply64(tif, xpt, y / dy, "TIFFComputeTile");
+        if ((z_offset == 0 && xpt_ypt != 0 && (z / dz) != 0) ||
+            (y_offset == 0 && xpt != 0 && (y / dy) != 0))
+            return (0);
+        tile64 = _TIFFAdd64(tif, z_offset, y_offset, "TIFFComputeTile");
+        if (tile64 == 0 && (z_offset != 0 || y_offset != 0))
+            return (0);
+        tile64 = _TIFFAdd64(tif, tile64, x / dx, "TIFFComputeTile");
+        if (tile64 == 0 && (z_offset != 0 || y_offset != 0 || (x / dx) != 0))
+            return (0);
         if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
-            tile = (xpt * ypt * zpt) * s + (xpt * ypt) * (z / dz) +
-                   xpt * (y / dy) + x / dx;
-        else
-            tile = (xpt * ypt) * (z / dz) + xpt * (y / dy) + x / dx;
+        {
+            uint64_t sample_offset;
+            if (s >= td->td_samplesperpixel)
+            {
+                TIFFErrorExtR(
+                    tif, "TIFFComputeTile", "%lu: Sample out of range, max %lu",
+                    (unsigned long)s, (unsigned long)td->td_samplesperpixel);
+                return (0);
+            }
+            sample_offset =
+                _TIFFMultiply64(tif, xpt_ypt_zpt, s, "TIFFComputeTile");
+            if (sample_offset == 0 && xpt_ypt_zpt != 0 && s != 0)
+                return (0);
+            tile64 = _TIFFAdd64(tif, sample_offset, tile64, "TIFFComputeTile");
+            if (tile64 == 0 && (sample_offset != 0 || z_offset != 0 ||
+                                y_offset != 0 || (x / dx) != 0))
+                return (0);
+        }
+        tile = _TIFFCastUInt64ToUInt32(tif, tile64, "TIFFComputeTile");
+        if (tile == 0 && tile64 != 0)
+            return (0);
     }
     return (tile);
 }
@@ -187,54 +225,9 @@
  */
 uint64_t TIFFVTileSize64(TIFF *tif, uint32_t nrows)
 {
-    static const char module[] = "TIFFVTileSize64";
-    TIFFDirectory *td = &tif->tif_dir;
-    if (td->td_tilelength == 0 || td->td_tilewidth == 0 ||
-        td->td_tiledepth == 0)
-        return (0);
-    if ((td->td_planarconfig == PLANARCONFIG_CONTIG) &&
-        (td->td_photometric == PHOTOMETRIC_YCBCR) &&
-        (td->td_samplesperpixel == 3) && (!isUpSampled(tif)))
-    {
-        /*
-         * Packed YCbCr data contain one Cb+Cr for every
-         * HorizontalSampling*VerticalSampling Y values.
-         * Must also roundup width and height when calculating
-         * since images that are not a multiple of the
-         * horizontal/vertical subsampling area include
-         * YCbCr data for the extended image.
-         */
-        uint16_t ycbcrsubsampling[2];
-        uint16_t samplingblock_samples;
-        uint32_t samplingblocks_hor;
-        uint32_t samplingblocks_ver;
-        uint64_t samplingrow_samples;
-        uint64_t samplingrow_size;
-        TIFFGetFieldDefaulted(tif, TIFFTAG_YCBCRSUBSAMPLING,
-                              ycbcrsubsampling + 0, ycbcrsubsampling + 1);
-        if ((ycbcrsubsampling[0] != 1 && ycbcrsubsampling[0] != 2 &&
-             ycbcrsubsampling[0] != 4) ||
-            (ycbcrsubsampling[1] != 1 && ycbcrsubsampling[1] != 2 &&
-             ycbcrsubsampling[1] != 4))
-        {
-            TIFFErrorExtR(tif, module, "Invalid YCbCr subsampling (%dx%d)",
-                          ycbcrsubsampling[0], ycbcrsubsampling[1]);
-            return 0;
-        }
-        samplingblock_samples = ycbcrsubsampling[0] * ycbcrsubsampling[1] + 2;
-        samplingblocks_hor =
-            TIFFhowmany_32(td->td_tilewidth, ycbcrsubsampling[0]);
-        samplingblocks_ver = TIFFhowmany_32(nrows, ycbcrsubsampling[1]);
-        samplingrow_samples = _TIFFMultiply64(tif, samplingblocks_hor,
-                                              samplingblock_samples, module);
-        samplingrow_size = TIFFhowmany8_64(_TIFFMultiply64(
-            tif, samplingrow_samples, td->td_bitspersample, module));
-        return (
-            _TIFFMultiply64(tif, samplingrow_size, samplingblocks_ver, module));
-    }
-    else
-        return (_TIFFMultiply64(tif, nrows, TIFFTileRowSize64(tif), module));
+    return _TIFFStrileSize64(tif, nrows, /* isStrip = */ FALSE);
 }
+
 tmsize_t TIFFVTileSize(TIFF *tif, uint32_t nrows)
 {
     static const char module[] = "TIFFVTileSize";
diff --git a/third_party/libtiff/tif_write.c b/third_party/libtiff/tif_write.c
index 3263853..614a8ea 100644
--- a/third_party/libtiff/tif_write.c
+++ b/third_party/libtiff/tif_write.c
@@ -30,7 +30,7 @@
 #include "tiffiop.h"
 #include <stdio.h>
 
-#define STRIPINCR 20 /* expansion factor on strip array */
+#define NOSTRIP ((uint32_t)(-1)) /* undefined state */
 
 #define WRITECHECKSTRIPS(tif, module)                                          \
     (((tif)->tif_flags & TIFF_BEENWRITING) || TIFFWriteCheck((tif), 0, module))
@@ -38,7 +38,7 @@
     (((tif)->tif_flags & TIFF_BEENWRITING) || TIFFWriteCheck((tif), 1, module))
 #define BUFFERCHECK(tif)                                                       \
     ((((tif)->tif_flags & TIFF_BUFFERSETUP) && tif->tif_rawdata) ||            \
-     TIFFWriteBufferSetup((tif), NULL, (tmsize_t)-1))
+     TIFFWriteBufferSetup((tif), NULL, (tmsize_t)(-1)))
 
 static int TIFFGrowStrips(TIFF *tif, uint32_t delta, const char *module);
 static int TIFFAppendToStrip(TIFF *tif, uint32_t strip, uint8_t *data,
@@ -47,7 +47,7 @@
 int TIFFWriteScanline(TIFF *tif, void *buf, uint32_t row, uint16_t sample)
 {
     static const char module[] = "TIFFWriteScanline";
-    register TIFFDirectory *td;
+    TIFFDirectory *td;
     int status, imagegrew = 0;
     uint32_t strip;
 
@@ -82,8 +82,16 @@
     /*
      * Calculate strip and check for crossings.
      */
+    if (td->td_rowsperstrip == 0)
+    {
+        TIFFErrorExtR(tif, module,
+                      "Cannot compute strip: RowsPerStrip is zero");
+        return (-1);
+    }
     if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
     {
+        uint64_t sample_offset;
+        uint64_t strip64;
         if (sample >= td->td_samplesperpixel)
         {
             TIFFErrorExtR(tif, module, "%lu: Sample out of range, max %lu",
@@ -91,7 +99,18 @@
                           (unsigned long)td->td_samplesperpixel);
             return (-1);
         }
-        strip = sample * td->td_stripsperimage + row / td->td_rowsperstrip;
+        sample_offset =
+            _TIFFMultiply64(tif, sample, td->td_stripsperimage, module);
+        if (sample_offset == 0 && sample != 0 && td->td_stripsperimage != 0)
+            return (-1);
+        strip64 =
+            _TIFFAdd64(tif, sample_offset, row / td->td_rowsperstrip, module);
+        if (strip64 == 0 &&
+            (sample_offset != 0 || (row / td->td_rowsperstrip) != 0))
+            return (-1);
+        strip = _TIFFCastUInt64ToUInt32(tif, strip64, module);
+        if (strip == 0 && strip64 != 0)
+            return (-1);
     }
     else
         strip = row / td->td_rowsperstrip;
@@ -104,14 +123,14 @@
      */
     if (strip >= td->td_nstrips && !TIFFGrowStrips(tif, 1, module))
         return (-1);
-    if (strip != tif->tif_curstrip)
+    if (strip != tif->tif_dir.td_curstrip)
     {
         /*
          * Changing strips -- flush any data present.
          */
         if (!TIFFFlushData(tif))
             return (-1);
-        tif->tif_curstrip = strip;
+        tif->tif_dir.td_curstrip = strip;
         /*
          * Watch out for a growing image.  The value of strips/image
          * will initially be 1 (since it can't be deduced until the
@@ -125,7 +144,8 @@
             TIFFErrorExtR(tif, module, "Zero strips per image");
             return (-1);
         }
-        tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip;
+        tif->tif_dir.td_row =
+            (strip % td->td_stripsperimage) * td->td_rowsperstrip;
         if ((tif->tif_flags & TIFF_CODERSETUP) == 0)
         {
             if (!(*tif->tif_setupencode)(tif))
@@ -148,35 +168,35 @@
      * beginning of a strip (or that we can randomly
      * access the data -- i.e. no encoding).
      */
-    if (row != tif->tif_row)
+    if (row != tif->tif_dir.td_row)
     {
-        if (row < tif->tif_row)
+        if (row < tif->tif_dir.td_row)
         {
             /*
              * Moving backwards within the same strip:
              * backup to the start and then decode
              * forward (below).
              */
-            tif->tif_row =
+            tif->tif_dir.td_row =
                 (strip % td->td_stripsperimage) * td->td_rowsperstrip;
             tif->tif_rawcp = tif->tif_rawdata;
         }
         /*
          * Seek forward to the desired row.
          */
-        if (!(*tif->tif_seek)(tif, row - tif->tif_row))
+        if (!(*tif->tif_seek)(tif, row - tif->tif_dir.td_row))
             return (-1);
-        tif->tif_row = row;
+        tif->tif_dir.td_row = row;
     }
 
     /* swab if needed - note that source buffer will be altered */
-    tif->tif_postdecode(tif, (uint8_t *)buf, tif->tif_scanlinesize);
+    tif->tif_postdecode(tif, (uint8_t *)buf, tif->tif_dir.td_scanlinesize);
 
-    status = (*tif->tif_encoderow)(tif, (uint8_t *)buf, tif->tif_scanlinesize,
-                                   sample);
+    status = (*tif->tif_encoderow)(tif, (uint8_t *)buf,
+                                   tif->tif_dir.td_scanlinesize, sample);
 
     /* we are now poised at the beginning of the next row */
-    tif->tif_row = row + 1;
+    tif->tif_dir.td_row = row + 1;
     return (status);
 }
 
@@ -188,7 +208,21 @@
 /* time if the new compressed tile is bigger than the older one. (GDAL #4771) */
 static int _TIFFReserveLargeEnoughWriteBuffer(TIFF *tif, uint32_t strip_or_tile)
 {
+    static const char module[] = "_TIFFReserveLargeEnoughWriteBuffer";
     TIFFDirectory *td = &tif->tif_dir;
+
+    if (td->td_stripbytecount_p == NULL)
+    {
+        TIFFErrorExtR(tif, module, "Strip bytecount array pointer is NULL");
+        return 0;
+    }
+
+    if (strip_or_tile == NOSTRIP || strip_or_tile >= td->td_nstrips)
+    {
+        TIFFErrorExtR(tif, module, "Strip/tile number not valid");
+        return 0;
+    }
+
     if (td->td_stripbytecount_p[strip_or_tile] > 0)
     {
         /* The +1 is to ensure at least one extra bytes */
@@ -254,7 +288,7 @@
 
     tif->tif_flags |= TIFF_BUF4WRITE;
 
-    tif->tif_curstrip = strip;
+    tif->tif_dir.td_curstrip = strip;
 
     /* this informs TIFFAppendToStrip() we have changed or reset strip */
     tif->tif_curoff = 0;
@@ -273,7 +307,7 @@
         return ((tmsize_t)-1);
     }
 
-    tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip;
+    tif->tif_dir.td_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip;
     if ((tif->tif_flags & TIFF_CODERSETUP) == 0)
     {
         if (!(*tif->tif_setupencode)(tif))
@@ -362,9 +396,9 @@
             return ((tmsize_t)-1);
     }
 
-    if (tif->tif_curstrip != strip)
+    if (tif->tif_dir.td_curstrip != strip)
     {
-        tif->tif_curstrip = strip;
+        tif->tif_dir.td_curstrip = strip;
 
         /* this informs TIFFAppendToStrip() we have changed or reset strip */
         tif->tif_curoff = 0;
@@ -375,7 +409,7 @@
         TIFFErrorExtR(tif, module, "Zero strips per image");
         return ((tmsize_t)-1);
     }
-    tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip;
+    tif->tif_dir.td_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip;
     return (TIFFAppendToStrip(tif, strip, (uint8_t *)data, cc) ? cc
                                                                : (tmsize_t)-1);
 }
@@ -437,7 +471,7 @@
 
     tif->tif_flags |= TIFF_BUF4WRITE;
 
-    tif->tif_curtile = tile;
+    tif->tif_dir.td_curtile = tile;
 
     /* this informs TIFFAppendToStrip() we have changed or reset tile */
     tif->tif_curoff = 0;
@@ -460,14 +494,14 @@
         TIFFErrorExtR(tif, module, "Zero tiles");
         return ((tmsize_t)(-1));
     }
-    tif->tif_row = (tile % howmany32) * td->td_tilelength;
+    tif->tif_dir.td_row = (tile % howmany32) * td->td_tilelength;
     howmany32 = TIFFhowmany_32(td->td_imagewidth, td->td_tilewidth);
     if (howmany32 == 0)
     {
         TIFFErrorExtR(tif, module, "Zero tiles");
         return ((tmsize_t)(-1));
     }
-    tif->tif_col = (tile % howmany32) * td->td_tilewidth;
+    tif->tif_dir.td_col = (tile % howmany32) * td->td_tilewidth;
 
     if ((tif->tif_flags & TIFF_CODERSETUP) == 0)
     {
@@ -482,8 +516,8 @@
      * done so that callers can pass in some large number
      * (e.g. -1) and have the tile size used instead.
      */
-    if (cc < 1 || cc > tif->tif_tilesize)
-        cc = tif->tif_tilesize;
+    if (cc < 1 || cc > tif->tif_dir.td_tilesize)
+        cc = tif->tif_dir.td_tilesize;
 
     /* shortcut to avoid an extra memcpy() */
     if (td->td_compression == COMPRESSION_NONE)
@@ -588,8 +622,10 @@
      * Place data at the end-of-file
      * (by setting offsets to zero).
      */
-    _TIFFmemset(td->td_stripoffset_p, 0, td->td_nstrips * sizeof(uint64_t));
-    _TIFFmemset(td->td_stripbytecount_p, 0, td->td_nstrips * sizeof(uint64_t));
+    _TIFFmemset(td->td_stripoffset_p, 0,
+                (tmsize_t)((size_t)td->td_nstrips * sizeof(uint64_t)));
+    _TIFFmemset(td->td_stripbytecount_p, 0,
+                (tmsize_t)((size_t)td->td_nstrips * sizeof(uint64_t)));
     TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS);
     TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS);
     return (1);
@@ -644,14 +680,14 @@
     }
     if (isTiled(tif))
     {
-        tif->tif_tilesize = TIFFTileSize(tif);
-        if (tif->tif_tilesize == 0)
+        tif->tif_dir.td_tilesize = TIFFTileSize(tif);
+        if (tif->tif_dir.td_tilesize == 0)
             return (0);
     }
     else
-        tif->tif_tilesize = (tmsize_t)(-1);
-    tif->tif_scanlinesize = TIFFScanlineSize(tif);
-    if (tif->tif_scanlinesize == 0)
+        tif->tif_dir.td_tilesize = (tmsize_t)(-1);
+    tif->tif_dir.td_scanlinesize = TIFFScanlineSize(tif);
+    if (tif->tif_dir.td_scanlinesize == 0)
         return (0);
     tif->tif_flags |= TIFF_BEENWRITING;
 
@@ -689,7 +725,7 @@
     }
     if (size == (tmsize_t)(-1))
     {
-        size = (isTiled(tif) ? tif->tif_tilesize : TIFFStripSize(tif));
+        size = (isTiled(tif) ? tif->tif_dir.td_tilesize : TIFFStripSize(tif));
 
         /* Adds 10% margin for cases where compression would expand a bit */
         if (size < TIFF_TMSIZE_T_MAX - size / 10)
@@ -732,26 +768,31 @@
 
     assert(td->td_planarconfig == PLANARCONFIG_CONTIG);
     new_stripoffset = (uint64_t *)_TIFFreallocExt(
-        tif, td->td_stripoffset_p, (td->td_nstrips + delta) * sizeof(uint64_t));
+        tif, td->td_stripoffset_p,
+        (tmsize_t)(((size_t)td->td_nstrips + (size_t)delta) *
+                   sizeof(uint64_t)));
+    /*
+     * Update td_stripoffset_p immediately so the old pointer is not left
+     * dangling if the second realloc fails.
+     */
+    if (new_stripoffset)
+        td->td_stripoffset_p = new_stripoffset;
     new_stripbytecount = (uint64_t *)_TIFFreallocExt(
         tif, td->td_stripbytecount_p,
-        (td->td_nstrips + delta) * sizeof(uint64_t));
+        (tmsize_t)(((size_t)td->td_nstrips + (size_t)delta) *
+                   sizeof(uint64_t)));
+    if (new_stripbytecount)
+        td->td_stripbytecount_p = new_stripbytecount;
     if (new_stripoffset == NULL || new_stripbytecount == NULL)
     {
-        if (new_stripoffset)
-            _TIFFfreeExt(tif, new_stripoffset);
-        if (new_stripbytecount)
-            _TIFFfreeExt(tif, new_stripbytecount);
         td->td_nstrips = 0;
         TIFFErrorExtR(tif, module, "No space to expand strip arrays");
         return (0);
     }
-    td->td_stripoffset_p = new_stripoffset;
-    td->td_stripbytecount_p = new_stripbytecount;
     _TIFFmemset(td->td_stripoffset_p + td->td_nstrips, 0,
-                delta * sizeof(uint64_t));
+                (tmsize_t)((size_t)delta * sizeof(uint64_t)));
     _TIFFmemset(td->td_stripbytecount_p + td->td_nstrips, 0,
-                delta * sizeof(uint64_t));
+                (tmsize_t)((size_t)delta * sizeof(uint64_t)));
     td->td_nstrips += delta;
     tif->tif_flags |= TIFF_DIRTYDIRECT;
 
@@ -769,6 +810,23 @@
     uint64_t m;
     int64_t old_byte_count = -1;
 
+    /* Some security checks */
+    if (td->td_stripoffset_p == NULL)
+    {
+        TIFFErrorExtR(tif, module, "Strip offset array pointer is NULL");
+        return (0);
+    }
+    if (td->td_stripbytecount_p == NULL)
+    {
+        TIFFErrorExtR(tif, module, "Strip bytecount array pointer is NULL");
+        return (0);
+    }
+    if (strip == NOSTRIP)
+    {
+        TIFFErrorExtR(tif, module, "Strip number not valid (NOSTRIP)");
+        return (0);
+    }
+
     if (tif->tif_curoff == 0)
         tif->tif_lastvalidoff = 0;
 
@@ -790,7 +848,7 @@
             if (!SeekOK(tif, td->td_stripoffset_p[strip]))
             {
                 TIFFErrorExtR(tif, module, "Seek error at scanline %lu",
-                              (unsigned long)tif->tif_row);
+                              (unsigned long)tif->tif_dir.td_row);
                 return (0);
             }
 
@@ -812,11 +870,11 @@
         /*
          * We are starting a fresh strip/tile, so set the size to zero.
          */
-        old_byte_count = td->td_stripbytecount_p[strip];
+        old_byte_count = (int64_t)td->td_stripbytecount_p[strip];
         td->td_stripbytecount_p[strip] = 0;
     }
 
-    m = tif->tif_curoff + cc;
+    m = tif->tif_curoff + (uint64_t)cc;
     if (!(tif->tif_flags & TIFF_BIGTIFF))
         m = (uint32_t)m;
     if ((m < tif->tif_curoff) || (m < (uint64_t)cc))
@@ -850,7 +908,7 @@
         offsetRead = td->td_stripoffset_p[strip];
         offsetWrite = TIFFSeekFile(tif, 0, SEEK_END);
 
-        m = offsetWrite + toCopy + cc;
+        m = offsetWrite + (uint64_t)toCopy + (uint64_t)cc;
         if (!(tif->tif_flags & TIFF_BIGTIFF) && m != (uint32_t)m)
         {
             TIFFErrorExtR(tif, module, "Maximum TIFF file size exceeded");
@@ -872,13 +930,15 @@
         /* Move data written by previous calls to us at end of file */
         while (toCopy > 0)
         {
+            tmsize_t chunkSize =
+                toCopy < (uint64_t)tempSize ? (tmsize_t)toCopy : tempSize;
             if (!SeekOK(tif, offsetRead))
             {
                 TIFFErrorExtR(tif, module, "Seek error");
                 _TIFFfreeExt(tif, temp);
                 return (0);
             }
-            if (!ReadOK(tif, temp, tempSize))
+            if (!ReadOK(tif, temp, chunkSize))
             {
                 TIFFErrorExtR(tif, module, "Cannot read");
                 _TIFFfreeExt(tif, temp);
@@ -890,32 +950,32 @@
                 _TIFFfreeExt(tif, temp);
                 return (0);
             }
-            if (!WriteOK(tif, temp, tempSize))
+            if (!WriteOK(tif, temp, chunkSize))
             {
                 TIFFErrorExtR(tif, module, "Cannot write");
                 _TIFFfreeExt(tif, temp);
                 return (0);
             }
-            offsetRead += tempSize;
-            offsetWrite += tempSize;
-            td->td_stripbytecount_p[strip] += tempSize;
-            toCopy -= tempSize;
+            offsetRead += (uint64_t)chunkSize;
+            offsetWrite += (uint64_t)chunkSize;
+            td->td_stripbytecount_p[strip] += (uint64_t)chunkSize;
+            toCopy -= (uint64_t)chunkSize;
         }
         _TIFFfreeExt(tif, temp);
 
         /* Append the data of this call */
-        offsetWrite += cc;
+        offsetWrite += (uint64_t)cc;
         m = offsetWrite;
     }
 
     if (!WriteOK(tif, data, cc))
     {
         TIFFErrorExtR(tif, module, "Write error at scanline %lu",
-                      (unsigned long)tif->tif_row);
+                      (unsigned long)tif->tif_dir.td_row);
         return (0);
     }
     tif->tif_curoff = m;
-    td->td_stripbytecount_p[strip] += cc;
+    td->td_stripbytecount_p[strip] += (uint64_t)cc;
 
     if ((int64_t)td->td_stripbytecount_p[strip] != old_byte_count)
         tif->tif_flags |= TIFF_DIRTYSTRIP;
@@ -935,9 +995,10 @@
         if (!isFillOrder(tif, tif->tif_dir.td_fillorder) &&
             (tif->tif_flags & TIFF_NOBITREV) == 0)
             TIFFReverseBits((uint8_t *)tif->tif_rawdata, tif->tif_rawcc);
-        if (!TIFFAppendToStrip(
-                tif, isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip,
-                tif->tif_rawdata, tif->tif_rawcc))
+        if (!TIFFAppendToStrip(tif,
+                               isTiled(tif) ? tif->tif_dir.td_curtile
+                                            : tif->tif_dir.td_curstrip,
+                               tif->tif_rawdata, tif->tif_rawcc))
         {
             /* We update those variables even in case of error since there's */
             /* code that doesn't really check the return code of this */
diff --git a/third_party/libtiff/tiffio.h b/third_party/libtiff/tiffio.h
index f9c206e..bb8fbde 100644
--- a/third_party/libtiff/tiffio.h
+++ b/third_party/libtiff/tiffio.h
@@ -125,13 +125,13 @@
  */
 
 /* reference white */
-#define D65_X0 (95.0470F)
-#define D65_Y0 (100.0F)
-#define D65_Z0 (108.8827F)
+#define D65_X0 (95.0470f)
+#define D65_Y0 (100.0f)
+#define D65_Z0 (108.8827f)
 
-#define D50_X0 (96.4250F)
-#define D50_Y0 (100.0F)
-#define D50_Z0 (82.4680F)
+#define D50_X0 (96.4250f)
+#define D50_Y0 (100.0f)
+#define D50_Z0 (82.4680f)
 
 /* Structure for holding information about a display device. */
 
@@ -254,7 +254,7 @@
  * Macros for extracting components from the
  * packed ABGR form returned by TIFFReadRGBAImage.
  */
-#define TIFFGetR(abgr) ((abgr)&0xff)
+#define TIFFGetR(abgr) ((abgr) & 0xff)
 #define TIFFGetG(abgr) (((abgr) >> 8) & 0xff)
 #define TIFFGetB(abgr) (((abgr) >> 16) & 0xff)
 #define TIFFGetA(abgr) (((abgr) >> 24) & 0xff)
@@ -269,7 +269,7 @@
 typedef int (*TIFFInitMethod)(TIFF *, int);
 typedef struct
 {
-    char *name;
+    const char *name;
     uint16_t scheme;
     TIFFInitMethod init;
 } TIFFCodec;
@@ -584,6 +584,7 @@
                                          tmsize_t cc);
     extern tmsize_t TIFFWriteRawTile(TIFF *tif, uint32_t tile, void *data,
                                      tmsize_t cc);
+    extern uint64_t TIFFGetMaxCompressionRatio(TIFF *tif);
     extern int TIFFDataWidth(
         TIFFDataType); /* table of tag datatype widths within TIFF file. */
     extern void TIFFSetWriteOffset(TIFF *tif, toff_t off);
@@ -659,7 +660,7 @@
         unsigned short field_bit;       /* bit in fieldsset bit vector */
         unsigned char field_oktochange; /* if true, can change while writing */
         unsigned char field_passcount;  /* if true, pass dir count on set */
-        char *field_name;               /* ASCII name */
+        const char *field_name;         /* ASCII name */
     } TIFFFieldInfo;
 
     extern int TIFFMergeFieldInfo(TIFF *, const TIFFFieldInfo[], uint32_t);
diff --git a/third_party/libtiff/tiffiop.h b/third_party/libtiff/tiffiop.h
index f00ae32..8df0e84 100644
--- a/third_party/libtiff/tiffiop.h
+++ b/third_party/libtiff/tiffiop.h
@@ -38,6 +38,7 @@
 #include <sys/types.h>
 #endif
 
+#include <math.h>
 #include <string.h>
 
 #ifdef HAVE_ASSERT_H
@@ -94,6 +95,7 @@
 typedef void (*TIFFPostMethod)(TIFF *tif, uint8_t *buf, tmsize_t size);
 typedef uint32_t (*TIFFStripMethod)(TIFF *, uint32_t);
 typedef void (*TIFFTileMethod)(TIFF *, uint32_t *, uint32_t *);
+typedef uint64_t (*TIFFGetMaxCompressionRatioMethod)(TIFF *);
 
 struct TIFFOffsetAndDirNumber
 {
@@ -143,13 +145,18 @@
     0x800000U /* read buffer (tif_rawdata) points into mmap() memory */
 #define TIFF_DEFERSTRILELOAD                                                   \
     0x1000000U /* defer strip/tile offset/bytecount array loading. */
-#define TIFF_LAZYSTRILELOAD                                                    \
-    0x2000000U /* lazy/ondemand loading of strip/tile offset/bytecount values. \
-                  Only used if TIFF_DEFERSTRILELOAD is set and in read-only    \
-                  mode */
+#define TIFF_LAZYSTRILELOAD_DONE                                               \
+    0x2000000U /* set when lazy/ondemand loading of strip/tile                 \
+                  offset/bytecount values has been done. Only used if          \
+                  TIFF_DEFERSTRILELOAD is set and in read-only mode */
 #define TIFF_CHOPPEDUPARRAYS                                                   \
     0x4000000U /* set when allocChoppedUpStripArrays() has modified strip      \
                   array */
+#define TIFF_LAZYSTRILELOAD_ASKED                                              \
+    0x8000000U /* set when lazy/ondemand loading of strip/tile                 \
+                  offset/bytecount values has been requested on opening ('O'   \
+                  flag) */
+
     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 */
@@ -162,7 +169,6 @@
         tif_customdir; /* custom IFDs are separated from the main ones */
     TIFFHeaderUnion tif_header; /* file's header block Classic/BigTIFF union */
     uint16_t tif_header_size;   /* file's header block and its length */
-    uint32_t tif_row;           /* current scanline */
 
     /* There are IFDs in the file and an "active" IFD in memory,
      * from which fields are "set" and "get".
@@ -184,7 +190,6 @@
      * - TIFF_NON_EXISTENT_DIR_NUMBER means 'dont know number of IFDs'.
      * - 0 means 'empty file opened for writing, but no IFD written yet' */
     tdir_t tif_curdircount;
-    uint32_t tif_curstrip;     /* current strip for read/write */
     uint64_t tif_curoff;       /* current offset for read/write */
     uint64_t tif_lastvalidoff; /* last valid offset allowed for rewrite in
                                   place. Used only by TIFFAppendToStrip() */
@@ -192,10 +197,6 @@
     /* SubIFD support */
     uint16_t tif_nsubifd;   /* remaining subifds to write */
     uint64_t tif_subifdoff; /* offset for patching SubIFD link */
-    /* tiling support */
-    uint32_t tif_col;      /* current column (offset by row too) */
-    uint32_t tif_curtile;  /* current tile for read/write */
-    tmsize_t tif_tilesize; /* # of bytes in a tile */
     /* compression scheme hooks */
     int tif_decodestatus;
     TIFFBoolMethod tif_fixuptags;   /* called in TIFFReadDirectory */
@@ -216,10 +217,10 @@
     TIFFVoidMethod tif_cleanup;       /* cleanup state routine */
     TIFFStripMethod tif_defstripsize; /* calculate/constrain strip size */
     TIFFTileMethod tif_deftilesize;   /* calculate/constrain tile size */
-    uint8_t *tif_data;                /* compression scheme private data */
+    /* returns maximum compression ratio for current compression method */
+    TIFFGetMaxCompressionRatioMethod tif_getmaxcompressionratio;
+    uint8_t *tif_data; /* compression scheme private data */
     /* input/output buffering */
-    tmsize_t tif_scanlinesize;  /* # of bytes in a scanline */
-    tmsize_t tif_scanlineskew;  /* scanline skew for reading strips */
     uint8_t *tif_rawdata;       /* raw data buffer */
     tmsize_t tif_rawdatasize;   /* # of bytes in raw data buffer */
     tmsize_t tif_rawdataoff;    /* rawdata offset within strip */
@@ -295,13 +296,15 @@
  * Default Read/Seek/Write definitions.
  */
 #ifndef ReadOK
-#define ReadOK(tif, buf, size) (TIFFReadFile((tif), (buf), (size)) == (size))
+#define ReadOK(tif, buf, size)                                                 \
+    (TIFFReadFile((tif), (buf), (size)) == (tmsize_t)(size))
 #endif
 #ifndef SeekOK
 #define SeekOK(tif, off) _TIFFSeekOK(tif, off)
 #endif
 #ifndef WriteOK
-#define WriteOK(tif, buf, size) (TIFFWriteFile((tif), (buf), (size)) == (size))
+#define WriteOK(tif, buf, size)                                                \
+    (TIFFWriteFile((tif), (buf), (size)) == (tmsize_t)(size))
 #endif
 
 /* NB: the uint32_t casts are to silence certain ANSI-C compilers */
@@ -315,19 +318,19 @@
     (((uint32_t)(x) / (uint32_t)(y)) +                                         \
      ((((uint32_t)(x) % (uint32_t)(y)) != 0) ? 1 : 0))
 #define TIFFhowmany8_32(x)                                                     \
-    (((x)&0x07) ? ((uint32_t)(x) >> 3) + 1 : (uint32_t)(x) >> 3)
-#define TIFFroundup_32(x, y) (TIFFhowmany_32(x, y) * (y))
+    (((x) & 0x07) ? ((uint32_t)(x) >> 3) + 1 : (uint32_t)(x) >> 3)
+#define TIFFroundup_32(x, y) ((uint32_t)(TIFFhowmany_32(x, y) * (uint32_t)(y)))
 #define TIFFhowmany_64(x, y)                                                   \
     ((((uint64_t)(x)) + (((uint64_t)(y)) - 1)) / ((uint64_t)(y)))
 #define TIFFhowmany8_64(x)                                                     \
-    (((x)&0x07) ? ((uint64_t)(x) >> 3) + 1 : (uint64_t)(x) >> 3)
-#define TIFFroundup_64(x, y) (TIFFhowmany_64(x, y) * (y))
+    (((x) & 0x07) ? ((uint64_t)(x) >> 3) + 1 : (uint64_t)(x) >> 3)
+#define TIFFroundup_64(x, y) ((uint64_t)(TIFFhowmany_64(x, y) * (uint64_t)(y)))
 
 /* Safe multiply which returns zero if there is an *unsigned* integer overflow.
  * This macro is not safe for *signed* integer types */
 #define TIFFSafeMultiply(t, v, m)                                              \
-    ((((t)(m) != (t)0) && (((t)(((v) * (m)) / (m))) == (t)(v)))                \
-         ? (t)((v) * (m))                                                      \
+    ((((t)(m) != (t)0) && (((t)((((t)(v)) * ((t)(m))) / ((t)(m)))) == (t)(v))) \
+         ? (t)(((t)(v)) * ((t)(m)))                                            \
          : (t)0)
 
 #define TIFFmax(A, B) ((A) > (B) ? (A) : (B))
@@ -335,6 +338,10 @@
 
 #define TIFFArrayCount(a) (sizeof(a) / sizeof((a)[0]))
 
+/* Float/double equality macros that suppress -Wfloat-equal warnings */
+#define TIFF_FLOAT_EQ(x, y) (!(fabsf((x) - (y)) > 0.0f))
+#define TIFF_DOUBLE_EQ(x, y) (!(fabs((x) - (y)) > 0.0))
+
 /*
   Support for large files.
 
@@ -355,7 +362,7 @@
 */
 #if defined(HAVE_FSEEKO)
 #define fseek(stream, offset, whence) fseeko(stream, offset, whence)
-#define ftell(stream, offset, whence) ftello(stream, offset, whence)
+#define ftell(stream) ftello(stream)
 #endif
 #endif
 #if defined(_WIN32) &&                                                         \
@@ -459,9 +466,18 @@
 
     extern uint32_t _TIFFMultiply32(TIFF *, uint32_t, uint32_t, const char *);
     extern uint64_t _TIFFMultiply64(TIFF *, uint64_t, uint64_t, const char *);
+    extern uint64_t _TIFFAdd64(TIFF *, uint64_t, uint64_t, const char *);
     extern tmsize_t _TIFFMultiplySSize(TIFF *, tmsize_t, tmsize_t,
                                        const char *);
+    extern tmsize_t _TIFFAddSSize(TIFF *, tmsize_t, tmsize_t, const char *);
     extern tmsize_t _TIFFCastUInt64ToSSize(TIFF *, uint64_t, const char *);
+    extern uint32_t _TIFFCastUInt64ToUInt32(TIFF *, uint64_t, const char *);
+    extern uint64_t _TIFFComputeRowSize64(TIFF *, uint32_t, uint16_t, uint16_t,
+                                          const char *);
+    extern tmsize_t _TIFFComputeRowOffset(TIFF *, tmsize_t rowstride, uint32_t,
+                                          const char *);
+    extern uint64_t _TIFFComputeBitOffset(TIFF *, uint32_t, uint16_t, uint16_t,
+                                          const char *);
     extern void *_TIFFCheckMalloc(TIFF *, tmsize_t, tmsize_t, const char *);
     extern void *_TIFFCheckRealloc(TIFF *, void *, tmsize_t, tmsize_t,
                                    const char *);
@@ -471,6 +487,8 @@
 
     extern void _TIFFCleanupIFDOffsetAndNumberMaps(TIFF *tif);
 
+    extern uint64_t _TIFFStrileSize64(TIFF *tif, uint32_t nrows, int isStrip);
+
     extern tmsize_t _TIFFReadEncodedStripAndAllocBuffer(TIFF *tif,
                                                         uint32_t strip,
                                                         void **buf,
diff --git a/third_party/libtiff/tiffvers.h b/third_party/libtiff/tiffvers.h
index 77ae6b4..2adbbee 100644
--- a/third_party/libtiff/tiffvers.h
+++ b/third_party/libtiff/tiffvers.h
@@ -3,7 +3,7 @@
 /* clang-format disabled because FindTIFF.cmake is very sensitive to the
  * formatting of below line being a single line.
  */
-#define TIFFLIB_VERSION_STR "LIBTIFF, Version 4.7.1\nCopyright (c) 1988-1996 Sam Leffler\nCopyright (c) 1991-1996 Silicon Graphics, Inc."
+#define TIFFLIB_VERSION_STR "LIBTIFF, Version 4.7.2\nCopyright (c) 1988-1996 Sam Leffler\nCopyright (c) 1991-1996 Silicon Graphics, Inc."
 /*
  * This define can be used in code that requires
  * compilation-related definitions specific to a
@@ -11,12 +11,12 @@
  * version checking should be done based on the
  * string returned by TIFFGetVersion.
  */
-#define TIFFLIB_VERSION 20250912
+#define TIFFLIB_VERSION 20260627
 
 /* The following defines have been added in 4.5.0 */
 #define TIFFLIB_MAJOR_VERSION 4
 #define TIFFLIB_MINOR_VERSION 7
-#define TIFFLIB_MICRO_VERSION 1
+#define TIFFLIB_MICRO_VERSION 2
 
 /* Macro added in 4.5.0. Returns TRUE if the current libtiff version is
  * greater or equal to major.minor.micro