Upgrade libtiff from 4.6.0 to 4.7.0
Also empty out the entries in third_party/libtiff/METADATA, since 4.7.0
has fixes for all of them.
Change-Id: Ic2de828554cbb785aa59243e31ccbe4f43085339
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/125130
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Tom Sepez <tsepez@google.com>
diff --git a/third_party/libtiff/0000-build-config.patch b/third_party/libtiff/0000-build-config.patch
index c3925b0..4312834 100644
--- a/third_party/libtiff/0000-build-config.patch
+++ b/third_party/libtiff/0000-build-config.patch
@@ -35,7 +35,7 @@
diff a/third_party/libtiff/tiffconf.h b/third_party/libtiff/tiffconf.h
--- /dev/null
+++ b/third_party/libtiff/tiffconf.h
-@@ -0,0 +1,244 @@
+@@ -0,0 +1,240 @@
+/* libtiff/tiffconf.h. Generated by configure. */
+/*
+ Configuration defines for installed libtiff.
@@ -211,11 +211,7 @@
+
+/* Native cpu byte order: 1 if big-endian (Motorola) or 0 if little-endian
+ (Intel) */
-+#if _FX_ENDIAN_ == _FX_BIG_ENDIAN_
-+# define HOST_BIGENDIAN 1
-+#else
-+# define HOST_BIGENDIAN 0
-+#endif
++#define HOST_BIGENDIAN 0
+
+/* Support CCITT Group 3 & 4 algorithms */
+#define CCITT_SUPPORT 1
@@ -249,7 +245,7 @@
+/* #undef ZIP_SUPPORT */
+
+/* Support strip chopping (whether or not to convert single-strip uncompressed
-+ images to mutiple strips of ~8Kb to reduce memory usage) */
++ images to multiple strips of ~8Kb to reduce memory usage) */
+#define STRIPCHOP_DEFAULT TIFF_STRIPCHOP
+
+/* Enable SubIFD tag (330) support */
diff --git a/third_party/libtiff/METADATA b/third_party/libtiff/METADATA
index 6cbd8cf..7b31b74 100644
--- a/third_party/libtiff/METADATA
+++ b/third_party/libtiff/METADATA
@@ -6,18 +6,5 @@
third_party {
security {
- # PDFium's copy of libtiff does not ship tools like tiffcrop.
- mitigated_security_patch: "CVE-2022-48281"
- mitigated_security_patch: "CVE-2023-1916"
- mitigated_security_patch: "CVE-2023-3164"
- mitigated_security_patch: "CVE-2023-25433"
- mitigated_security_patch: "CVE-2023-25434"
- mitigated_security_patch: "CVE-2023-25435"
- mitigated_security_patch: "CVE-2023-26965"
- mitigated_security_patch: "CVE-2023-40745"
- mitigated_security_patch: "CVE-2023-41175"
-
- # There are no callers to TIFFRasterScanlineSize() in PDFium's code base.
- mitigated_security_patch: "CVE-2023-52355"
}
}
diff --git a/third_party/libtiff/README.pdfium b/third_party/libtiff/README.pdfium
index fc60596..cfe60c6 100644
--- a/third_party/libtiff/README.pdfium
+++ b/third_party/libtiff/README.pdfium
@@ -1,7 +1,7 @@
Name: LibTIFF
URL: http://www.simplesystems.org/libtiff/
-Version: 4.6.0
-CPEPrefix: cpe:/a:libtiff:libtiff:4.6.0
+Version: 4.7.0
+CPEPrefix: cpe:/a:libtiff:libtiff:4.7.0
Security Critical: yes
Shipped: yes
License: BSD
diff --git a/third_party/libtiff/tif_aux.c b/third_party/libtiff/tif_aux.c
index 49855bb..e9606a4 100644
--- a/third_party/libtiff/tif_aux.c
+++ b/third_party/libtiff/tif_aux.c
@@ -385,53 +385,6 @@
return (ok);
}
-struct _Int64Parts
-{
- int32_t low, high;
-};
-
-typedef union
-{
- struct _Int64Parts part;
- int64_t value;
-} _Int64;
-
-float _TIFFUInt64ToFloat(uint64_t ui64)
-{
- _Int64 i;
-
- i.value = ui64;
- if (i.part.high >= 0)
- {
- return (float)i.value;
- }
- else
- {
- long double df;
- df = (long double)i.value;
- df += 18446744073709551616.0; /* adding 2**64 */
- return (float)df;
- }
-}
-
-double _TIFFUInt64ToDouble(uint64_t ui64)
-{
- _Int64 i;
-
- i.value = ui64;
- if (i.part.high >= 0)
- {
- return (double)i.value;
- }
- else
- {
- long double df;
- df = (long double)i.value;
- df += 18446744073709551616.0; /* adding 2**64 */
- return (double)df;
- }
-}
-
float _TIFFClampDoubleToFloat(double val)
{
if (val > FLT_MAX)
diff --git a/third_party/libtiff/tif_close.c b/third_party/libtiff/tif_close.c
index 907d7f1..d6bb7f1 100644
--- a/third_party/libtiff/tif_close.c
+++ b/third_party/libtiff/tif_close.c
@@ -110,6 +110,14 @@
_TIFFfreeExt(tif, tif->tif_fieldscompat);
}
+ if (tif->tif_cur_cumulated_mem_alloc != 0)
+ {
+ TIFFErrorExtR(tif, "TIFFCleanup",
+ "tif_cur_cumulated_mem_alloc = %" PRIu64 " whereas it "
+ "should be 0",
+ (uint64_t)tif->tif_cur_cumulated_mem_alloc);
+ }
+
_TIFFfreeExt(NULL, tif);
}
diff --git a/third_party/libtiff/tif_color.c b/third_party/libtiff/tif_color.c
index 2d7dcac..a52fdac 100644
--- a/third_party/libtiff/tif_color.c
+++ b/third_party/libtiff/tif_color.c
@@ -89,7 +89,7 @@
void TIFFXYZToRGB(TIFFCIELabToRGB *cielab, float X, float Y, float Z,
uint32_t *r, uint32_t *g, uint32_t *b)
{
- int i;
+ size_t i;
float Yr, Yg, Yb;
float *matrix = &cielab->display.d_mat[0][0];
@@ -109,16 +109,16 @@
Yb = TIFFmin(Yb, cielab->display.d_YCB);
/* Turn luminosity to colour value. */
- i = (int)((Yr - cielab->display.d_Y0R) / cielab->rstep);
- i = TIFFmin(cielab->range, i);
+ i = (size_t)((Yr - cielab->display.d_Y0R) / cielab->rstep);
+ i = TIFFmin((size_t)cielab->range, i);
*r = RINT(cielab->Yr2r[i]);
- i = (int)((Yg - cielab->display.d_Y0G) / cielab->gstep);
- i = TIFFmin(cielab->range, i);
+ i = (size_t)((Yg - cielab->display.d_Y0G) / cielab->gstep);
+ i = TIFFmin((size_t)cielab->range, i);
*g = RINT(cielab->Yg2g[i]);
- i = (int)((Yb - cielab->display.d_Y0B) / cielab->bstep);
- i = TIFFmin(cielab->range, i);
+ i = (size_t)((Yb - cielab->display.d_Y0B) / cielab->bstep);
+ i = TIFFmin((size_t)cielab->range, i);
*b = RINT(cielab->Yb2b[i]);
/* Clip output. */
@@ -135,7 +135,7 @@
int TIFFCIELabToRGBInit(TIFFCIELabToRGB *cielab, const TIFFDisplay *display,
float *refWhite)
{
- int i;
+ size_t i;
double dfGamma;
cielab->range = CIELABTORGB_TABLE_RANGE;
@@ -146,7 +146,7 @@
dfGamma = 1.0 / cielab->display.d_gammaR;
cielab->rstep =
(cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range;
- for (i = 0; i <= cielab->range; i++)
+ for (i = 0; i <= (size_t)cielab->range; i++)
{
cielab->Yr2r[i] = cielab->display.d_Vrwr *
((float)pow((double)i / cielab->range, dfGamma));
@@ -156,7 +156,7 @@
dfGamma = 1.0 / cielab->display.d_gammaG;
cielab->gstep =
(cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range;
- for (i = 0; i <= cielab->range; i++)
+ for (i = 0; i <= (size_t)cielab->range; i++)
{
cielab->Yg2g[i] = cielab->display.d_Vrwg *
((float)pow((double)i / cielab->range, dfGamma));
@@ -166,7 +166,7 @@
dfGamma = 1.0 / cielab->display.d_gammaB;
cielab->bstep =
(cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range;
- for (i = 0; i <= cielab->range; i++)
+ for (i = 0; i <= (size_t)cielab->range; i++)
{
cielab->Yb2b[i] = cielab->display.d_Vrwb *
((float)pow((double)i / cielab->range, dfGamma));
diff --git a/third_party/libtiff/tif_dir.c b/third_party/libtiff/tif_dir.c
index 85006218..459f969 100644
--- a/third_party/libtiff/tif_dir.c
+++ b/third_party/libtiff/tif_dir.c
@@ -211,7 +211,7 @@
}
bad:
TIFFErrorExtR(tif, "TIFFSetField",
- "%s: Invalid InkNames value; no NUL at given buffer end "
+ "%s: Invalid InkNames value; no null at given buffer end "
"location %" PRIu32 ", after %" PRIu16 " ink",
tif->tif_name, slen, i);
return (0);
@@ -1652,6 +1652,17 @@
_TIFFmemset(&(td->td_stripoffset_entry), 0, sizeof(TIFFDirEntry));
_TIFFmemset(&(td->td_stripbytecount_entry), 0, sizeof(TIFFDirEntry));
+
+ /* Reset some internal parameters for IFD data size checking. */
+ tif->tif_dir.td_dirdatasize_read = 0;
+ tif->tif_dir.td_dirdatasize_write = 0;
+ if (tif->tif_dir.td_dirdatasize_offsets != NULL)
+ {
+ _TIFFfreeExt(tif, tif->tif_dir.td_dirdatasize_offsets);
+ tif->tif_dir.td_dirdatasize_offsets = NULL;
+ tif->tif_dir.td_dirdatasize_Noffsets = 0;
+ }
+ tif->tif_dir.td_iswrittentofile = FALSE;
}
#undef CleanupField
@@ -1676,18 +1687,23 @@
*/
int TIFFCreateDirectory(TIFF *tif)
{
+ /* Free previously allocated memory and setup default values. */
+ TIFFFreeDirectory(tif);
TIFFDefaultDirectory(tif);
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;
}
int TIFFCreateCustomDirectory(TIFF *tif, const TIFFFieldArray *infoarray)
{
+ /* Free previously allocated memory and setup default values. */
+ TIFFFreeDirectory(tif);
TIFFDefaultDirectory(tif);
/*
@@ -1848,7 +1864,9 @@
if (((uint64_t)poffa != poff) || (poffb < poffa) ||
(poffb < (tmsize_t)sizeof(uint16_t)) || (poffb > tif->tif_size))
{
- TIFFErrorExtR(tif, module, "Error fetching directory count");
+ TIFFErrorExtR(tif, module,
+ "%s:%d: %s: Error fetching directory count",
+ __FILE__, __LINE__, tif->tif_name);
*nextdiroff = 0;
return (0);
}
@@ -1877,14 +1895,18 @@
uint16_t dircount16;
if (poff > (uint64_t)TIFF_TMSIZE_T_MAX - sizeof(uint64_t))
{
- TIFFErrorExtR(tif, module, "Error fetching directory count");
+ TIFFErrorExtR(tif, module,
+ "%s:%d: %s: Error fetching directory count",
+ __FILE__, __LINE__, tif->tif_name);
return (0);
}
poffa = (tmsize_t)poff;
poffb = poffa + sizeof(uint64_t);
if (poffb > tif->tif_size)
{
- TIFFErrorExtR(tif, module, "Error fetching directory count");
+ TIFFErrorExtR(tif, module,
+ "%s:%d: %s: Error fetching directory count",
+ __FILE__, __LINE__, tif->tif_name);
return (0);
}
_TIFFmemcpy(&dircount64, tif->tif_base + poffa, sizeof(uint64_t));
@@ -1926,8 +1948,9 @@
if (!SeekOK(tif, *nextdiroff) ||
!ReadOK(tif, &dircount, sizeof(uint16_t)))
{
- TIFFErrorExtR(tif, module, "%s: Error fetching directory count",
- tif->tif_name);
+ TIFFErrorExtR(tif, module,
+ "%s:%d: %s: Error fetching directory count",
+ __FILE__, __LINE__, tif->tif_name);
return (0);
}
if (tif->tif_flags & TIFF_SWAB)
@@ -1953,15 +1976,18 @@
if (!SeekOK(tif, *nextdiroff) ||
!ReadOK(tif, &dircount64, sizeof(uint64_t)))
{
- TIFFErrorExtR(tif, module, "%s: Error fetching directory count",
- tif->tif_name);
+ TIFFErrorExtR(tif, module,
+ "%s:%d: %s: Error fetching directory count",
+ __FILE__, __LINE__, tif->tif_name);
return (0);
}
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabLong8(&dircount64);
if (dircount64 > 0xFFFF)
{
- TIFFErrorExtR(tif, module, "Error fetching directory count");
+ TIFFErrorExtR(tif, module,
+ "%s:%d: %s: Error fetching directory count",
+ __FILE__, __LINE__, tif->tif_name);
return (0);
}
dircount16 = (uint16_t)dircount64;
@@ -2018,6 +2044,8 @@
{
++n;
}
+ /* Update number of main-IFDs in file. */
+ tif->tif_curdircount = n;
return (n);
}
@@ -2100,7 +2128,19 @@
tif->tif_curdir = TIFF_NON_EXISTENT_DIR_NUMBER;
else
tif->tif_curdir--;
- return (TIFFReadDirectory(tif));
+
+ tdir_t curdir = tif->tif_curdir;
+
+ int retval = TIFFReadDirectory(tif);
+
+ if (!retval && tif->tif_curdir == curdir)
+ {
+ /* If tif_curdir has not be incremented, TIFFFetchDirectory() in
+ * TIFFReadDirectory() has failed and tif_curdir shall be set
+ * specifically. */
+ tif->tif_curdir = TIFF_NON_EXISTENT_DIR_NUMBER;
+ }
+ return (retval);
}
/*
@@ -2125,8 +2165,11 @@
int8_t probablySubIFD = 0;
if (diroff == 0)
{
- /* Special case to invalidate the tif_lastdiroff member. */
+ /* Special case to set tif_diroff=0, which is done in
+ * TIFFReadDirectory() below to indicate that the currently read IFD is
+ * treated as a new, fresh IFD. */
tif->tif_curdir = TIFF_NON_EXISTENT_DIR_NUMBER;
+ tif->tif_dir.td_iswrittentofile = FALSE;
}
else
{
@@ -2136,32 +2179,40 @@
probablySubIFD = 1;
}
/* -1 because TIFFReadDirectory() will increment tif_curdir. */
- tif->tif_curdir =
- curdir == 0 ? TIFF_NON_EXISTENT_DIR_NUMBER : curdir - 1;
+ if (curdir >= 1)
+ tif->tif_curdir = curdir - 1;
+ else
+ tif->tif_curdir = TIFF_NON_EXISTENT_DIR_NUMBER;
}
+ curdir = tif->tif_curdir;
tif->tif_nextdiroff = diroff;
retval = TIFFReadDirectory(tif);
- /* If failed, curdir was not incremented in TIFFReadDirectory(), so set it
- * back, but leave it for diroff==0. */
- if (!retval && diroff != 0)
+
+ /* tif_curdir is incremented in TIFFReadDirectory(), but if it has not been
+ * incremented, TIFFFetchDirectory() has failed there and tif_curdir shall
+ * be set specifically. */
+ if (!retval && diroff != 0 && tif->tif_curdir == curdir)
{
- if (tif->tif_curdir == TIFF_NON_EXISTENT_DIR_NUMBER)
- tif->tif_curdir = 0;
- else
- tif->tif_curdir++;
+ tif->tif_curdir = TIFF_NON_EXISTENT_DIR_NUMBER;
}
- if (retval && probablySubIFD)
+
+ if (probablySubIFD)
{
- /* Reset IFD list to start new one for SubIFD chain and also start
- * SubIFD chain with tif_curdir=0. */
- _TIFFCleanupIFDOffsetAndNumberMaps(tif); /* invalidate IFD loop lists */
- tif->tif_curdir = 0; /* first directory of new chain */
- /* add this offset to new IFD list */
- _TIFFCheckDirNumberAndOffset(tif, tif->tif_curdir, diroff);
+ if (retval)
+ {
+ /* Reset IFD list to start new one for SubIFD chain and also start
+ * SubIFD chain with tif_curdir=0 for IFD loop checking. */
+ /* invalidate IFD loop lists */
+ _TIFFCleanupIFDOffsetAndNumberMaps(tif);
+ tif->tif_curdir = 0; /* first directory of new chain */
+ /* add this offset to new IFD list */
+ _TIFFCheckDirNumberAndOffset(tif, tif->tif_curdir, diroff);
+ }
/* To be able to return from SubIFD or custom-IFD to main-IFD */
tif->tif_setdirectory_force_absolute = TRUE;
}
+
return (retval);
}
@@ -2257,9 +2308,11 @@
}
else
{
+ /* Need local swap because nextdir has to be used unswapped below. */
+ uint64_t nextdir64 = nextdir;
if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong8(&nextdir);
- if (!WriteOK(tif, &nextdir, sizeof(uint64_t)))
+ TIFFSwabLong8(&nextdir64);
+ if (!WriteOK(tif, &nextdir64, sizeof(uint64_t)))
{
TIFFErrorExtR(tif, module, "Error writing directory link");
return (0);
@@ -2303,6 +2356,10 @@
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--;
+ else
+ tif->tif_curdircount = TIFF_NON_EXISTENT_DIR_NUMBER;
_TIFFCleanupIFDOffsetAndNumberMaps(tif); /* invalidate IFD loop lists */
return (1);
}
diff --git a/third_party/libtiff/tif_dir.h b/third_party/libtiff/tif_dir.h
index 9eaf22f..ffad085 100644
--- a/third_party/libtiff/tif_dir.h
+++ b/third_party/libtiff/tif_dir.h
@@ -65,6 +65,12 @@
tif_dirread.c */
} TIFFDirEntry;
+typedef struct
+{
+ uint64_t offset;
+ uint64_t length;
+} TIFFEntryOffsetAndLength; /* auxiliary for evaluating size of IFD data */
+
/*
* Internal format of a TIFF directory entry.
*/
@@ -115,6 +121,9 @@
#ifdef STRIPBYTECOUNTSORTED_UNUSED
int td_stripbytecountsorted; /* is the bytecount array sorted ascending? */
#endif
+ /* Be aware that the parameters of td_stripoffset_entry and
+ * td_stripbytecount_entry are swapped but tdir_offset is not
+ * and has to be swapped when used. */
TIFFDirEntry td_stripoffset_entry; /* for deferred loading */
TIFFDirEntry td_stripbytecount_entry; /* for deferred loading */
uint16_t td_nsubifd;
@@ -135,6 +144,24 @@
unsigned char
td_deferstrilearraywriting; /* see TIFFDeferStrileArrayWriting() */
+
+ unsigned char
+ td_iswrittentofile; /* indicates if current IFD is present on file */
+
+ /* LibTIFF writes all data that does not fit into the IFD entries directly
+ * after the IFD tag entry part. When reading, only the IFD data directly
+ * and continuously behind the IFD tags is taken into account for the IFD
+ * data size.*/
+ uint64_t td_dirdatasize_write; /* auxiliary for evaluating size of IFD data
+ to be written */
+ uint64_t td_dirdatasize_read; /* auxiliary for evaluating size of IFD data
+ read from file */
+ uint32_t td_dirdatasize_Noffsets; /* auxiliary counter for
+ tif_dir.td_dirdatasize_offsets array */
+ TIFFEntryOffsetAndLength
+ *td_dirdatasize_offsets; /* auxiliary array for all offsets of IFD tag
+ entries with data outside the IFD tag
+ entries. */
} TIFFDirectory;
/*
@@ -308,11 +335,10 @@
TIFFDataType field_type; /* type of associated data */
uint32_t
field_anonymous; /* if true, this is a unknown / anonymous tag */
- TIFFSetGetFieldType
- set_field_type; /* type to be passed to TIFFSetField */
- TIFFSetGetFieldType
- get_field_type; /* type to be passed to TIFFGetField */
- unsigned short field_bit; /* bit in fieldsset bit vector */
+ TIFFSetGetFieldType set_field_type; /* type to be passed to TIFFSetField
+ and TIFFGetField*/
+ TIFFSetGetFieldType get_field_type; /* not used */
+ 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 */
diff --git a/third_party/libtiff/tif_dirinfo.c b/third_party/libtiff/tif_dirinfo.c
index 0e705e8..432e6e1 100644
--- a/third_party/libtiff/tif_dirinfo.c
+++ b/third_party/libtiff/tif_dirinfo.c
@@ -213,8 +213,6 @@
{TIFFTAG_CURRENTPREPROFILEMATRIX, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "CurrentPreProfileMatrix", NULL},
{TIFFTAG_PERSAMPLE, 0, 0, TIFF_SHORT, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_PSEUDO, TRUE, FALSE, "PerSample", NULL},
#if 0
- /* TODO: revert above #if 0 for TIFF 4.6.0 */
-
/* begin DNG 1.2.0.0 tags */
{TIFFTAG_COLORIMETRICREFERENCE, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ColorimetricReference", NULL},
{TIFFTAG_CAMERACALIBRATIONSIGNATURE, -1, -1, TIFF_BYTE, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "CameraCalibrationSignature", NULL},
@@ -282,9 +280,11 @@
{TIFFTAG_ILLUMINANTDATA2, -3, -3, TIFF_UNDEFINED, 0, TIFF_SETGET_C32_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "IlluminantData2", NULL},
{TIFFTAG_ILLUMINANTDATA3, -3, -3, TIFF_UNDEFINED, 0, TIFF_SETGET_C32_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "IlluminantData3", NULL},
/* end DNG tags */
+#endif
/* begin TIFF/EP tags */
{TIFFTAG_EP_CFAREPEATPATTERNDIM, 2, 2, TIFF_SHORT, 0, TIFF_SETGET_C0_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "EP CFARepeatPatternDim", NULL},
{TIFFTAG_EP_CFAPATTERN, -1, -1, TIFF_BYTE, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "EP CFAPattern", NULL},
+#if 0
/* TIFFTAG_EP_BATTERYLEVEL can be RATIONAL or ASCII.
* LibTiff defines it as ASCII and converts RATIONAL to an ASCII string. */
{TIFFTAG_EP_BATTERYLEVEL, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "EP BatteryLevel", NULL},
@@ -374,7 +374,7 @@
{EXIFTAG_BRIGHTNESSVALUE, 1, 1, TIFF_SRATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "BrightnessValue", NULL},
{EXIFTAG_EXPOSUREBIASVALUE, 1, 1, TIFF_SRATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ExposureBiasValue", NULL},
{EXIFTAG_MAXAPERTUREVALUE, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "MaxApertureValue", NULL},
- /*--: EXIFTAG_SUBJECTDISTANCE: LibTiff returns value of "-1" if numerator equals 4294967295 (0xFFFFFFFF) to indicate infinite distance!
+ /*--: EXIFTAG_SUBJECTDISTANCE: LibTiff returns value of "-1" if numerator equals 4294967295 (0xFFFFFFFF) to indicate infinite distance!
* However, there are two other EXIF tags where numerator indicates a special value and six other cases where the denominator indicates special values,
* which are not treated within LibTiff!! */
{EXIFTAG_SUBJECTDISTANCE, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "SubjectDistance", NULL},
@@ -887,7 +887,7 @@
if (fld == NULL)
{
fld = _TIFFCreateAnonField(tif, tag, dt);
- if (!_TIFFMergeFields(tif, fld, 1))
+ if (fld == NULL || !_TIFFMergeFields(tif, fld, 1))
return NULL;
}
@@ -1197,12 +1197,24 @@
for (i = 0; i < n; i++)
{
tp->field_tag = info[i].field_tag;
+ if (info[i].field_readcount < TIFF_VARIABLE2 ||
+ info[i].field_readcount == 0 ||
+ info[i].field_writecount < TIFF_VARIABLE2 ||
+ info[i].field_writecount == 0)
+ {
+ /* The fields (field_readcount) and (field_writecount) may use the
+ * values TIFF_VARIABLE (-1), TIFF_SPP (-2), TIFF_VARIABLE2 (-3). */
+ TIFFErrorExtR(tif, module,
+ "The value of field_readcount and field_writecount "
+ "must be greater than or equal to -3 and not zero.");
+ return -1;
+ }
tp->field_readcount = info[i].field_readcount;
tp->field_writecount = info[i].field_writecount;
tp->field_type = info[i].field_type;
tp->field_anonymous = 0;
tp->set_field_type =
- _TIFFSetGetType(info[i].field_type, info[i].field_readcount,
+ _TIFFSetGetType(info[i].field_type, info[i].field_writecount,
info[i].field_passcount);
tp->get_field_type =
_TIFFSetGetType(info[i].field_type, info[i].field_readcount,
diff --git a/third_party/libtiff/tif_dirread.c b/third_party/libtiff/tif_dirread.c
index 4a5015e..2b6e0b4 100644
--- a/third_party/libtiff/tif_dirread.c
+++ b/third_party/libtiff/tif_dirread.c
@@ -1016,16 +1016,7 @@
err = TIFFReadDirEntryCheckedLong8(tif, direntry, &m);
if (err != TIFFReadDirEntryErrOk)
return (err);
-#if defined(__WIN32__) && (_MSC_VER < 1500)
- /*
- * XXX: MSVC 6.0 does not support conversion
- * of 64-bit integers into floating point
- * values.
- */
- *value = _TIFFUInt64ToFloat(m);
-#else
*value = (float)m;
-#endif
return (TIFFReadDirEntryErrOk);
}
case TIFF_SLONG8:
@@ -1130,16 +1121,7 @@
err = TIFFReadDirEntryCheckedLong8(tif, direntry, &m);
if (err != TIFFReadDirEntryErrOk)
return (err);
-#if defined(__WIN32__) && (_MSC_VER < 1500)
- /*
- * XXX: MSVC 6.0 does not support conversion
- * of 64-bit integers into floating point
- * values.
- */
- *value = _TIFFUInt64ToDouble(m);
-#else
*value = (double)m;
-#endif
return (TIFFReadDirEntryErrOk);
}
case TIFF_SLONG8:
@@ -1308,6 +1290,24 @@
datasize = (*count) * typesize;
assert((tmsize_t)datasize > 0);
+ if (datasize > 100 * 1024 * 1024)
+ {
+ /* Before allocating a huge amount of memory for corrupted files, check
+ * if size of requested memory is not greater than file size.
+ */
+ const uint64_t filesize = TIFFGetFileSize(tif);
+ if (datasize > filesize)
+ {
+ TIFFWarningExtR(tif, "ReadDirEntryArray",
+ "Requested memory size for tag %d (0x%x) %" PRIu32
+ " is greater than filesize %" PRIu64
+ ". Memory not allocated, tag not read",
+ direntry->tdir_tag, direntry->tdir_tag, datasize,
+ filesize);
+ return (TIFFReadDirEntryErrAlloc);
+ }
+ }
+
if (isMapped(tif) && datasize > (uint64_t)tif->tif_size)
return TIFFReadDirEntryErrIo;
@@ -2886,16 +2886,7 @@
{
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabLong8(ma);
-#if defined(__WIN32__) && (_MSC_VER < 1500)
- /*
- * XXX: MSVC 6.0 does not support
- * conversion of 64-bit integers into
- * floating point values.
- */
- *mb++ = _TIFFUInt64ToFloat(*ma++);
-#else
*mb++ = (float)(*ma++);
-#endif
}
}
break;
@@ -3131,16 +3122,7 @@
{
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabLong8(ma);
-#if defined(__WIN32__) && (_MSC_VER < 1500)
- /*
- * XXX: MSVC 6.0 does not support
- * conversion of 64-bit integers into
- * floating point values.
- */
- *mb++ = _TIFFUInt64ToDouble(*ma++);
-#else
*mb++ = (double)(*ma++);
-#endif
}
}
break;
@@ -4096,6 +4078,155 @@
}
/*
+ * To evaluate the IFD data size when reading, save the offset and data size of
+ * all data that does not fit into the IFD entries themselves.
+ */
+static bool EvaluateIFDdatasizeReading(TIFF *tif, TIFFDirEntry *dp)
+{
+ const uint64_t data_width = TIFFDataWidth(dp->tdir_type);
+ if (data_width != 0 && dp->tdir_count > UINT64_MAX / data_width)
+ {
+ TIFFErrorExtR(tif, "EvaluateIFDdatasizeReading",
+ "Too large IFD data size");
+ return false;
+ }
+ const uint64_t datalength = dp->tdir_count * data_width;
+ if (datalength > ((tif->tif_flags & TIFF_BIGTIFF) ? 0x8U : 0x4U))
+ {
+ if (tif->tif_dir.td_dirdatasize_read > UINT64_MAX - datalength)
+ {
+ TIFFErrorExtR(tif, "EvaluateIFDdatasizeReading",
+ "Too large IFD data size");
+ return false;
+ }
+ tif->tif_dir.td_dirdatasize_read += datalength;
+ if (!(tif->tif_flags & TIFF_BIGTIFF))
+ {
+ /* The offset of TIFFDirEntry are not swapped when read in. That has
+ * to be done when used. */
+ uint32_t offset = dp->tdir_offset.toff_long;
+ if (tif->tif_flags & TIFF_SWAB)
+ TIFFSwabLong(&offset);
+ tif->tif_dir
+ .td_dirdatasize_offsets[tif->tif_dir.td_dirdatasize_Noffsets]
+ .offset = (uint64_t)offset;
+ }
+ else
+ {
+ tif->tif_dir
+ .td_dirdatasize_offsets[tif->tif_dir.td_dirdatasize_Noffsets]
+ .offset = dp->tdir_offset.toff_long8;
+ if (tif->tif_flags & TIFF_SWAB)
+ TIFFSwabLong8(
+ &tif->tif_dir
+ .td_dirdatasize_offsets[tif->tif_dir
+ .td_dirdatasize_Noffsets]
+ .offset);
+ }
+ tif->tif_dir
+ .td_dirdatasize_offsets[tif->tif_dir.td_dirdatasize_Noffsets]
+ .length = datalength;
+ tif->tif_dir.td_dirdatasize_Noffsets++;
+ }
+ return true;
+}
+
+/*
+ * Compare function for qsort() sorting TIFFEntryOffsetAndLength array entries.
+ */
+static int cmpTIFFEntryOffsetAndLength(const void *a, const void *b)
+{
+ const TIFFEntryOffsetAndLength *ta = (const TIFFEntryOffsetAndLength *)a;
+ const TIFFEntryOffsetAndLength *tb = (const TIFFEntryOffsetAndLength *)b;
+ /* Compare offsets */
+ if (ta->offset > tb->offset)
+ return 1;
+ else if (ta->offset < tb->offset)
+ return -1;
+ else
+ return 0;
+}
+
+/*
+ * Determine the IFD data size after reading an IFD from the file that can be
+ * overwritten and saving it in tif_dir.td_dirdatasize_read. This data size
+ * includes the IFD entries themselves as well as the data that does not fit
+ * directly into the IFD entries but is located directly after the IFD entries
+ * in the file.
+ */
+static void CalcFinalIFDdatasizeReading(TIFF *tif, uint16_t dircount)
+{
+ /* IFD data size is only needed if file-writing is enabled.
+ * This also avoids the seek() to EOF to determine the file size, which
+ * causes the stdin-streaming-friendly mode of libtiff for GDAL to fail. */
+ if (tif->tif_mode == O_RDONLY)
+ return;
+
+ /* Sort TIFFEntryOffsetAndLength array in ascending order. */
+ qsort(tif->tif_dir.td_dirdatasize_offsets,
+ tif->tif_dir.td_dirdatasize_Noffsets,
+ sizeof(TIFFEntryOffsetAndLength), cmpTIFFEntryOffsetAndLength);
+
+ /* 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;
+ else
+ IFDendoffset = tif->tif_diroff + 8 + 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.
+ * Thus gaps of 1 byte can occur. */
+ uint64_t size = 0;
+ uint64_t offset;
+ uint32_t i;
+ for (i = 0; i < tif->tif_dir.td_dirdatasize_Noffsets; i++)
+ {
+ offset = tif->tif_dir.td_dirdatasize_offsets[i].offset;
+ if (offset == IFDendoffset)
+ {
+ size += tif->tif_dir.td_dirdatasize_offsets[i].length;
+ IFDendoffset += tif->tif_dir.td_dirdatasize_offsets[i].length;
+ }
+ else if (offset == IFDendoffset + 1)
+ {
+ /* Add gap byte after previous IFD data set. */
+ size += tif->tif_dir.td_dirdatasize_offsets[i].length + 1;
+ IFDendoffset += tif->tif_dir.td_dirdatasize_offsets[i].length;
+ }
+ else
+ {
+ /* Further data is no more continuously after IFD */
+ break;
+ }
+ }
+ /* Check for gap byte of some easy cases. This should cover 90% of cases.
+ * Otherwise, IFD will be re-written even it might be safely overwritten. */
+ if (tif->tif_nextdiroff != 0)
+ {
+ if (tif->tif_nextdiroff == IFDendoffset + 1)
+ size++;
+ }
+ else
+ {
+ /* Check for IFD data ends at EOF. Then IFD can always be safely
+ * overwritten. */
+ offset = TIFFSeekFile(tif, 0, SEEK_END);
+ if (offset == IFDendoffset)
+ {
+ tif->tif_dir.td_dirdatasize_read = UINT64_MAX;
+ return;
+ }
+ }
+
+ /* 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;
+ else
+ tif->tif_dir.td_dirdatasize_read = 8 + dircount * 20 + 8 + size;
+} /*-- CalcFinalIFDdatasizeReading() --*/
+
+/*
* Read the next TIFF directory from a file and convert it to the internal
* format. We read directories sequentially.
*/
@@ -4150,7 +4281,6 @@
tif->tif_curdir = 0;
else
tif->tif_curdir++;
- (*tif->tif_cleanup)(tif); /* cleanup any previous compression state */
TIFFReadDirectoryCheckOrder(tif, dir, dircount);
@@ -4180,8 +4310,27 @@
tif->tif_flags &= ~TIFF_CHOPPEDUPARRAYS;
/* free any old stuff and reinit */
+ (*tif->tif_cleanup)(tif); /* cleanup any previous compression state */
TIFFFreeDirectory(tif);
TIFFDefaultDirectory(tif);
+
+ /* After setup a fresh directory indicate that now active IFD is also
+ * present on file, even if its entries could not be read successfully
+ * below. */
+ tif->tif_dir.td_iswrittentofile = TRUE;
+
+ /* Allocate arrays for offset values outside IFD entry for IFD data size
+ * checking. Note: Counter are reset within TIFFFreeDirectory(). */
+ tif->tif_dir.td_dirdatasize_offsets =
+ (TIFFEntryOffsetAndLength *)_TIFFmallocExt(
+ tif, dircount * sizeof(TIFFEntryOffsetAndLength));
+ if (tif->tif_dir.td_dirdatasize_offsets == NULL)
+ {
+ TIFFErrorExtR(
+ tif, module,
+ "Failed to allocate memory for counting IFD data size at reading");
+ goto bad;
+ }
/*
* Electronic Arts writes gray-scale TIFF files
* without a PlanarConfiguration directory entry.
@@ -4260,11 +4409,9 @@
dp->tdir_tag, dp->tdir_tag);
/* the following knowingly leaks the
anonymous field structure */
- if (!_TIFFMergeFields(
- tif,
- _TIFFCreateAnonField(tif, dp->tdir_tag,
- (TIFFDataType)dp->tdir_type),
- 1))
+ const TIFFField *fld = _TIFFCreateAnonField(
+ tif, dp->tdir_tag, (TIFFDataType)dp->tdir_type);
+ if (fld == NULL || !_TIFFMergeFields(tif, fld, 1))
{
TIFFWarningExtR(
tif, module,
@@ -4381,6 +4528,8 @@
uint16_t value;
enum TIFFReadDirEntryErr err;
err = TIFFReadDirEntryShort(tif, dp, &value);
+ if (!EvaluateIFDdatasizeReading(tif, dp))
+ goto bad;
if (err == TIFFReadDirEntryErrCount)
err =
TIFFReadDirEntryPersampleShort(tif, dp, &value);
@@ -4411,6 +4560,8 @@
err = TIFFReadDirEntryErrCount;
else
err = TIFFReadDirEntryDoubleArray(tif, dp, &data);
+ if (!EvaluateIFDdatasizeReading(tif, dp))
+ goto bad;
if (err != TIFFReadDirEntryErrOk)
{
fip = TIFFFieldWithTag(tif, dp->tdir_tag);
@@ -4430,6 +4581,7 @@
break;
case TIFFTAG_STRIPOFFSETS:
case TIFFTAG_TILEOFFSETS:
+ {
switch (dp->tdir_type)
{
case TIFF_SHORT:
@@ -4452,9 +4604,13 @@
}
_TIFFmemcpy(&(tif->tif_dir.td_stripoffset_entry), dp,
sizeof(TIFFDirEntry));
- break;
+ if (!EvaluateIFDdatasizeReading(tif, dp))
+ goto bad;
+ }
+ break;
case TIFFTAG_STRIPBYTECOUNTS:
case TIFFTAG_TILEBYTECOUNTS:
+ {
switch (dp->tdir_type)
{
case TIFF_SHORT:
@@ -4477,7 +4633,10 @@
}
_TIFFmemcpy(&(tif->tif_dir.td_stripbytecount_entry), dp,
sizeof(TIFFDirEntry));
- break;
+ if (!EvaluateIFDdatasizeReading(tif, dp))
+ goto bad;
+ }
+ break;
case TIFFTAG_COLORMAP:
case TIFFTAG_TRANSFERFUNCTION:
{
@@ -4531,6 +4690,8 @@
err = TIFFReadDirEntryErrCount;
else
err = TIFFReadDirEntryShortArray(tif, dp, &value);
+ if (!EvaluateIFDdatasizeReading(tif, dp))
+ goto bad;
if (err != TIFFReadDirEntryErrOk)
{
fip = TIFFFieldWithTag(tif, dp->tdir_tag);
@@ -4621,9 +4782,12 @@
default:
(void)TIFFFetchNormalTag(tif, dp, TRUE);
break;
- }
- } /* -- if (!dp->tdir_ignore) */
- } /* -- for-loop -- */
+ } /* -- switch (dp->tdir_tag) -- */
+ } /* -- if (!dp->tdir_ignore) */
+ } /* -- for-loop -- */
+
+ /* Evaluate final IFD data size. */
+ CalcFinalIFDdatasizeReading(tif, dircount);
/*
* OJPEG hack:
@@ -5040,7 +5204,7 @@
if (dir)
_TIFFfreeExt(tif, dir);
return (0);
-}
+} /*-- TIFFReadDirectory() --*/
static void TIFFReadDirectoryCheckOrder(TIFF *tif, TIFFDirEntry *dir,
uint16_t dircount)
@@ -5124,8 +5288,7 @@
uint16_t di;
const TIFFField *fip;
uint32_t fii;
- (*tif->tif_cleanup)(tif); /* cleanup any previous compression state */
- _TIFFSetupFields(tif, infoarray);
+
dircount = TIFFFetchDirectory(tif, diroff, &dir, NULL);
if (!dircount)
{
@@ -5134,9 +5297,56 @@
diroff);
return 0;
}
- TIFFFreeDirectory(tif);
- _TIFFmemset(&tif->tif_dir, 0, sizeof(TIFFDirectory));
TIFFReadDirectoryCheckOrder(tif, dir, dircount);
+
+ /*
+ * Mark duplicates of any tag to be ignored (bugzilla 1994)
+ * to avoid certain pathological problems.
+ */
+ {
+ TIFFDirEntry *ma;
+ uint16_t mb;
+ for (ma = dir, mb = 0; mb < dircount; ma++, mb++)
+ {
+ TIFFDirEntry *na;
+ uint16_t nb;
+ for (na = ma + 1, nb = mb + 1; nb < dircount; na++, nb++)
+ {
+ if (ma->tdir_tag == na->tdir_tag)
+ {
+ na->tdir_ignore = TRUE;
+ }
+ }
+ }
+ }
+
+ /* Free any old stuff and reinit. */
+ (*tif->tif_cleanup)(tif); /* cleanup any previous compression state */
+ TIFFFreeDirectory(tif);
+ /* Even if custom directories do not need the default settings of a standard
+ * IFD, the pointer to the TIFFSetField() and TIFFGetField() (i.e.
+ * tif->tif_tagmethods.vsetfield and tif->tif_tagmethods.vgetfield) need to
+ * be initialized, which is done in TIFFDefaultDirectory().
+ * After that, the field array for the custom tags needs to be setup again.
+ */
+ TIFFDefaultDirectory(tif);
+ _TIFFSetupFields(tif, infoarray);
+
+ /* Allocate arrays for offset values outside IFD entry for IFD data size
+ * checking. Note: Counter are reset within TIFFFreeDirectory(). */
+ tif->tif_dir.td_dirdatasize_offsets =
+ (TIFFEntryOffsetAndLength *)_TIFFmallocExt(
+ tif, dircount * sizeof(TIFFEntryOffsetAndLength));
+ if (tif->tif_dir.td_dirdatasize_offsets == NULL)
+ {
+ TIFFErrorExtR(
+ tif, module,
+ "Failed to allocate memory for counting IFD data size at reading");
+ if (dir)
+ _TIFFfreeExt(tif, dir);
+ return 0;
+ }
+
for (di = 0, dp = dir; di < dircount; di++, dp++)
{
TIFFReadDirectoryFindFieldInfo(tif, dp->tdir_tag, &fii);
@@ -5146,11 +5356,9 @@
"Unknown field with tag %" PRIu16 " (0x%" PRIx16
") encountered",
dp->tdir_tag, dp->tdir_tag);
- if (!_TIFFMergeFields(
- tif,
- _TIFFCreateAnonField(tif, dp->tdir_tag,
- (TIFFDataType)dp->tdir_type),
- 1))
+ const TIFFField *fld = _TIFFCreateAnonField(
+ tif, dp->tdir_tag, (TIFFDataType)dp->tdir_type);
+ if (fld == NULL || !_TIFFMergeFields(tif, fld, 1))
{
TIFFWarningExtR(tif, module,
"Registering anonymous field with tag %" PRIu16
@@ -5233,6 +5441,9 @@
} /*-- if (!dp->tdir_ignore) */
}
}
+ /* Evaluate final IFD data size. */
+ CalcFinalIFDdatasizeReading(tif, dircount);
+
/* To be able to return from SubIFD or custom-IFD to main-IFD */
tif->tif_setdirectory_force_absolute = TRUE;
if (dir)
@@ -5246,9 +5457,7 @@
*/
int TIFFReadEXIFDirectory(TIFF *tif, toff_t diroff)
{
- const TIFFFieldArray *exifFieldArray;
- exifFieldArray = _TIFFGetExifFields();
- return TIFFReadCustomDirectory(tif, diroff, exifFieldArray);
+ return TIFFReadCustomDirectory(tif, diroff, _TIFFGetExifFields());
}
/*
@@ -5256,9 +5465,7 @@
*/
int TIFFReadGPSDirectory(TIFF *tif, toff_t diroff)
{
- const TIFFFieldArray *gpsFieldArray;
- gpsFieldArray = _TIFFGetGpsFields();
- return TIFFReadCustomDirectory(tif, diroff, gpsFieldArray);
+ return TIFFReadCustomDirectory(tif, diroff, _TIFFGetGpsFields());
}
static int EstimateStripByteCounts(TIFF *tif, TIFFDirEntry *dir,
@@ -5274,6 +5481,24 @@
if (!_TIFFFillStrilesInternal(tif, 0))
return -1;
+ const uint64_t allocsize = (uint64_t)td->td_nstrips * sizeof(uint64_t);
+ uint64_t filesize = 0;
+ if (allocsize > 100 * 1024 * 1024)
+ {
+ /* Before allocating a huge amount of memory for corrupted files, check
+ * if size of requested memory is not greater than file size. */
+ filesize = TIFFGetFileSize(tif);
+ if (allocsize > filesize)
+ {
+ TIFFWarningExtR(
+ tif, module,
+ "Requested memory size for StripByteCounts of %" PRIu64
+ " is greater than filesize %" PRIu64 ". Memory not allocated",
+ allocsize, filesize);
+ return -1;
+ }
+ }
+
if (td->td_stripbytecount_p)
_TIFFfreeExt(tif, td->td_stripbytecount_p);
td->td_stripbytecount_p = (uint64_t *)_TIFFCheckMalloc(
@@ -5284,9 +5509,7 @@
if (td->td_compression != COMPRESSION_NONE)
{
uint64_t space;
- uint64_t filesize;
uint16_t n;
- filesize = TIFFGetFileSize(tif);
if (!(tif->tif_flags & TIFF_BIGTIFF))
space = sizeof(TIFFHeaderClassic) + 2 + dircount * 12 + 4;
else
@@ -5322,6 +5545,8 @@
return -1;
space += datasize;
}
+ if (filesize == 0)
+ filesize = TIFFGetFileSize(tif);
if (filesize < space)
/* we should perhaps return in error ? */
space = filesize;
@@ -5929,6 +6154,20 @@
"directories not supported");
return 0;
}
+ /* Before allocating a huge amount of memory for corrupted files, check
+ * if size of requested memory is not greater than file size. */
+ uint64_t filesize = TIFFGetFileSize(tif);
+ uint64_t allocsize = (uint64_t)dircount16 * dirsize;
+ if (allocsize > filesize)
+ {
+ TIFFWarningExtR(
+ tif, module,
+ "Requested memory size for TIFF directory of %" PRIu64
+ " is greater than filesize %" PRIu64
+ ". Memory not allocated, TIFF directory not read",
+ allocsize, filesize);
+ return 0;
+ }
origdir = _TIFFCheckMalloc(tif, dircount16, dirsize,
"to read TIFF directory");
if (origdir == NULL)
@@ -5976,6 +6215,8 @@
}
}
}
+ /* No check against filesize needed here because "dir" should have same size
+ * than "origdir" checked above. */
dir = (TIFFDirEntry *)_TIFFCheckMalloc(
tif, dircount16, sizeof(TIFFDirEntry), "to read TIFF directory");
if (dir == 0)
@@ -6088,6 +6329,12 @@
}
}
}
+ if (!EvaluateIFDdatasizeReading(tif, dp))
+ {
+ if (data != NULL)
+ _TIFFfreeExt(tif, data);
+ return (0);
+ }
if (mb + 1 < (uint32_t)dp->tdir_count)
TIFFWarningExtR(
tif, module,
@@ -6097,15 +6344,15 @@
fip->field_name);
else if (mb + 1 > (uint32_t)dp->tdir_count)
{
- uint8_t *o;
- TIFFWarningExtR(
- tif, module,
- "ASCII value for tag \"%s\" does not end in null byte",
- fip->field_name);
+ TIFFWarningExtR(tif, module,
+ "ASCII value for tag \"%s\" does not end "
+ "in null byte. Forcing it to be null",
+ fip->field_name);
/* TIFFReadDirEntryArrayWithLimit() ensures this can't be
* larger than MAX_SIZE_TAG_DATA */
assert((uint32_t)dp->tdir_count + 1 == dp->tdir_count + 1);
- o = _TIFFmallocExt(tif, (uint32_t)dp->tdir_count + 1);
+ uint8_t *o =
+ _TIFFmallocExt(tif, (uint32_t)dp->tdir_count + 1);
if (o == NULL)
{
if (data != NULL)
@@ -6215,6 +6462,8 @@
err = TIFFReadDirEntryLong8(tif, dp, &data);
if (err == TIFFReadDirEntryErrOk)
{
+ if (!EvaluateIFDdatasizeReading(tif, dp))
+ return 0;
if (!TIFFSetField(tif, dp->tdir_tag, data))
return (0);
}
@@ -6228,6 +6477,8 @@
err = TIFFReadDirEntrySlong8(tif, dp, &data);
if (err == TIFFReadDirEntryErrOk)
{
+ if (!EvaluateIFDdatasizeReading(tif, dp))
+ return 0;
if (!TIFFSetField(tif, dp->tdir_tag, data))
return (0);
}
@@ -6241,6 +6492,8 @@
err = TIFFReadDirEntryFloat(tif, dp, &data);
if (err == TIFFReadDirEntryErrOk)
{
+ if (!EvaluateIFDdatasizeReading(tif, dp))
+ return 0;
if (!TIFFSetField(tif, dp->tdir_tag, data))
return (0);
}
@@ -6254,6 +6507,8 @@
err = TIFFReadDirEntryDouble(tif, dp, &data);
if (err == TIFFReadDirEntryErrOk)
{
+ if (!EvaluateIFDdatasizeReading(tif, dp))
+ return 0;
if (!TIFFSetField(tif, dp->tdir_tag, data))
return (0);
}
@@ -6267,6 +6522,8 @@
err = TIFFReadDirEntryIfd8(tif, dp, &data);
if (err == TIFFReadDirEntryErrOk)
{
+ if (!EvaluateIFDdatasizeReading(tif, dp))
+ return 0;
if (!TIFFSetField(tif, dp->tdir_tag, data))
return (0);
}
@@ -6316,6 +6573,12 @@
err = TIFFReadDirEntryByteArray(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)
@@ -6345,6 +6608,12 @@
err = TIFFReadDirEntrySbyteArray(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)
@@ -6374,6 +6643,12 @@
err = TIFFReadDirEntryShortArray(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)
@@ -6403,6 +6678,12 @@
err = TIFFReadDirEntrySshortArray(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)
@@ -6432,6 +6713,12 @@
err = TIFFReadDirEntryLongArray(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)
@@ -6461,6 +6748,12 @@
err = TIFFReadDirEntrySlongArray(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)
@@ -6490,6 +6783,12 @@
err = TIFFReadDirEntryLong8Array(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)
@@ -6519,6 +6818,12 @@
err = TIFFReadDirEntrySlong8Array(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)
@@ -6548,6 +6853,12 @@
err = TIFFReadDirEntryFloatArray(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)
@@ -6579,6 +6890,12 @@
err = TIFFReadDirEntryDoubleArray(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)
@@ -6601,16 +6918,39 @@
err = TIFFReadDirEntryByteArray(tif, dp, &data);
if (err == TIFFReadDirEntryErrOk)
{
+ if (!EvaluateIFDdatasizeReading(tif, dp))
+ {
+ if (data != 0)
+ _TIFFfreeExt(tif, data);
+ return 0;
+ }
int m;
if (data != 0 && dp->tdir_count > 0 &&
data[dp->tdir_count - 1] != '\0')
{
- TIFFWarningExtR(
- tif, module,
- "ASCII value for tag \"%s\" does not end in null "
- "byte. Forcing it to be null",
- fip->field_name);
- data[dp->tdir_count - 1] = '\0';
+ TIFFWarningExtR(tif, module,
+ "ASCII value for ASCII array tag "
+ "\"%s\" does not end 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);
+ if (o == NULL)
+ {
+ if (data != NULL)
+ _TIFFfreeExt(tif, data);
+ return (0);
+ }
+ if (dp->tdir_count > 0)
+ {
+ _TIFFmemcpy(o, data, (uint32_t)dp->tdir_count);
+ }
+ o[(uint32_t)dp->tdir_count] = 0;
+ dp->tdir_count++; /* Increment for added null. */
+ if (data != 0)
+ _TIFFfreeExt(tif, data);
+ data = o;
}
m = TIFFSetField(tif, dp->tdir_tag,
(uint16_t)(dp->tdir_count), data);
@@ -6634,6 +6974,12 @@
err = TIFFReadDirEntryByteArray(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,
(uint16_t)(dp->tdir_count), data);
@@ -6657,6 +7003,12 @@
err = TIFFReadDirEntrySbyteArray(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,
(uint16_t)(dp->tdir_count), data);
@@ -6680,6 +7032,12 @@
err = TIFFReadDirEntryShortArray(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,
(uint16_t)(dp->tdir_count), data);
@@ -6703,6 +7061,12 @@
err = TIFFReadDirEntrySshortArray(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,
(uint16_t)(dp->tdir_count), data);
@@ -6726,6 +7090,12 @@
err = TIFFReadDirEntryLongArray(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,
(uint16_t)(dp->tdir_count), data);
@@ -6749,6 +7119,12 @@
err = TIFFReadDirEntrySlongArray(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,
(uint16_t)(dp->tdir_count), data);
@@ -6772,6 +7148,12 @@
err = TIFFReadDirEntryLong8Array(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,
(uint16_t)(dp->tdir_count), data);
@@ -6795,6 +7177,12 @@
err = TIFFReadDirEntrySlong8Array(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,
(uint16_t)(dp->tdir_count), data);
@@ -6818,6 +7206,12 @@
err = TIFFReadDirEntryFloatArray(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,
(uint16_t)(dp->tdir_count), data);
@@ -6841,6 +7235,12 @@
err = TIFFReadDirEntryDoubleArray(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,
(uint16_t)(dp->tdir_count), data);
@@ -6864,6 +7264,12 @@
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,
(uint16_t)(dp->tdir_count), data);
@@ -6883,15 +7289,39 @@
err = TIFFReadDirEntryByteArray(tif, dp, &data);
if (err == TIFFReadDirEntryErrOk)
{
+ if (!EvaluateIFDdatasizeReading(tif, dp))
+ {
+ if (data != 0)
+ _TIFFfreeExt(tif, data);
+ return 0;
+ }
int m;
if (data != 0 && dp->tdir_count > 0 &&
data[dp->tdir_count - 1] != '\0')
{
- TIFFWarningExtR(tif, module,
- "ASCII value for tag \"%s\" does not end "
- "in null byte. Forcing it to be null",
- fip->field_name);
- data[dp->tdir_count - 1] = '\0';
+ TIFFWarningExtR(
+ tif, module,
+ "ASCII value for ASCII array tag \"%s\" does not end "
+ "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);
+ if (o == NULL)
+ {
+ if (data != NULL)
+ _TIFFfreeExt(tif, data);
+ return (0);
+ }
+ if (dp->tdir_count > 0)
+ {
+ _TIFFmemcpy(o, data, (uint32_t)dp->tdir_count);
+ }
+ o[(uint32_t)dp->tdir_count] = 0;
+ dp->tdir_count++; /* Increment for added null. */
+ if (data != 0)
+ _TIFFfreeExt(tif, data);
+ data = o;
}
m = TIFFSetField(tif, dp->tdir_tag, (uint32_t)(dp->tdir_count),
data);
@@ -6935,6 +7365,12 @@
}
if (err == TIFFReadDirEntryErrOk)
{
+ if (!EvaluateIFDdatasizeReading(tif, dp))
+ {
+ if (data != 0)
+ _TIFFfreeExt(tif, data);
+ return 0;
+ }
int m;
m = TIFFSetField(tif, dp->tdir_tag, count, data);
if (data != 0)
@@ -6952,6 +7388,12 @@
err = TIFFReadDirEntrySbyteArray(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, (uint32_t)(dp->tdir_count),
data);
@@ -6970,6 +7412,12 @@
err = TIFFReadDirEntryShortArray(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, (uint32_t)(dp->tdir_count),
data);
@@ -6988,6 +7436,12 @@
err = TIFFReadDirEntrySshortArray(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, (uint32_t)(dp->tdir_count),
data);
@@ -7006,6 +7460,12 @@
err = TIFFReadDirEntryLongArray(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, (uint32_t)(dp->tdir_count),
data);
@@ -7024,6 +7484,12 @@
err = TIFFReadDirEntrySlongArray(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, (uint32_t)(dp->tdir_count),
data);
@@ -7042,6 +7508,12 @@
err = TIFFReadDirEntryLong8Array(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, (uint32_t)(dp->tdir_count),
data);
@@ -7060,6 +7532,12 @@
err = TIFFReadDirEntrySlong8Array(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, (uint32_t)(dp->tdir_count),
data);
@@ -7078,6 +7556,12 @@
err = TIFFReadDirEntryFloatArray(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, (uint32_t)(dp->tdir_count),
data);
@@ -7096,6 +7580,12 @@
err = TIFFReadDirEntryDoubleArray(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, (uint32_t)(dp->tdir_count),
data);
@@ -7114,6 +7604,12 @@
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, (uint32_t)(dp->tdir_count),
data);
@@ -7172,6 +7668,25 @@
return (0);
}
+ const uint64_t allocsize = (uint64_t)nstrips * sizeof(uint64_t);
+ if (allocsize > 100 * 1024 * 1024)
+ {
+ /* Before allocating a huge amount of memory for corrupted files,
+ * check if size of requested memory is not greater than file size.
+ */
+ const uint64_t filesize = TIFFGetFileSize(tif);
+ if (allocsize > filesize)
+ {
+ TIFFWarningExtR(
+ tif, module,
+ "Requested memory size for StripArray of %" PRIu64
+ " is greater than filesize %" PRIu64
+ ". Memory not allocated",
+ allocsize, filesize);
+ _TIFFfreeExt(tif, data);
+ return (0);
+ }
+ }
resizeddata = (uint64_t *)_TIFFCheckMalloc(
tif, nstrips, sizeof(uint64_t), "for strip array");
if (resizeddata == 0)
@@ -7271,6 +7786,26 @@
}
bytecount = last_offset + last_bytecount - offset;
+ /* Before allocating a huge amount of memory for corrupted files, check if
+ * size of StripByteCount and StripOffset tags is not greater than
+ * file size.
+ */
+ const uint64_t allocsize = (uint64_t)nstrips * sizeof(uint64_t) * 2;
+ if (allocsize > 100 * 1024 * 1024)
+ {
+ const uint64_t filesize = TIFFGetFileSize(tif);
+ if (allocsize > filesize)
+ {
+ TIFFWarningExtR(tif, "allocChoppedUpStripArrays",
+ "Requested memory size for StripByteCount and "
+ "StripOffsets %" PRIu64
+ " is greater than filesize %" PRIu64
+ ". Memory not allocated",
+ allocsize, filesize);
+ return;
+ }
+ }
+
newcounts =
(uint64_t *)_TIFFCheckMalloc(tif, nstrips, sizeof(uint64_t),
"for chopped \"StripByteCounts\" array");
@@ -7371,7 +7906,7 @@
/*
* never increase the number of rows per strip
*/
- if (rowsperstrip >= td->td_rowsperstrip)
+ if (rowsperstrip >= td->td_rowsperstrip || rowsperstrip == 0)
return;
nstrips = TIFFhowmany_32(td->td_imagelength, rowsperstrip);
if (nstrips == 0)
@@ -7467,6 +8002,8 @@
stripbytes = rowblocksperstrip * rowblockbytes;
assert(stripbytes <= 0x7FFFFFFFUL);
+ if (rowsperstrip == 0)
+ return;
nstrips = TIFFhowmany_32(td->td_imagelength, rowsperstrip);
if (nstrips == 0)
return;
diff --git a/third_party/libtiff/tif_dirwrite.c b/third_party/libtiff/tif_dirwrite.c
index d8844bb..facdeaf 100644
--- a/third_party/libtiff/tif_dirwrite.c
+++ b/third_party/libtiff/tif_dirwrite.c
@@ -303,12 +303,14 @@
}
/*
- * Similar to TIFFWriteDirectory(), but if the directory has already
+ * Similar to TIFFWriteDirectorySec(), but if the directory has already
* been written once, it is relocated to the end of the file, in case it
* has changed in size. Note that this will result in the loss of the
* previously used directory space.
*/
-int TIFFRewriteDirectory(TIFF *tif)
+
+static int TIFFRewriteDirectorySec(TIFF *tif, int isimage, int imagedone,
+ uint64_t *pdiroff)
{
static const char module[] = "TIFFRewriteDirectory";
@@ -464,10 +466,20 @@
}
/*
- * Now use TIFFWriteDirectory() normally.
+ * Now use TIFFWriteDirectorySec() normally.
*/
+ return TIFFWriteDirectorySec(tif, isimage, imagedone, pdiroff);
+} /*-- TIFFRewriteDirectorySec() --*/
- return TIFFWriteDirectory(tif);
+/*
+ * Similar to TIFFWriteDirectory(), but if the directory has already
+ * been written once, it is relocated to the end of the file, in case it
+ * has changed in size. Note that this will result in the loss of the
+ * previously used directory space.
+ */
+int TIFFRewriteDirectory(TIFF *tif)
+{
+ return TIFFRewriteDirectorySec(tif, TRUE, TRUE, NULL);
}
static int TIFFWriteDirectorySec(TIFF *tif, int isimage, int imagedone,
@@ -542,7 +554,12 @@
dirsize = 0;
while (1)
{
+ /* The first loop only determines "ndir" and uses TIFFLinkDirectory() to
+ * set the offset at which the IFD is to be written to the file.
+ * The second loop writes IFD entries to the file. */
ndir = 0;
+ if (dir == NULL)
+ tif->tif_dir.td_dirdatasize_write = 0;
if (isimage)
{
if (TIFFFieldSet(tif, FIELD_IMAGEDIMENSIONS))
@@ -852,7 +869,7 @@
if ((o->field_bit >= FIELD_CODEC) &&
(TIFFFieldSet(tif, o->field_bit)))
{
- switch (o->get_field_type)
+ switch (o->set_field_type)
{
case TIFF_SETGET_ASCII:
{
@@ -1085,8 +1102,18 @@
break;
}
}
+ /* "break" if IFD has been written above in second pass.*/
if (dir != NULL)
break;
+
+ /* Evaluate IFD data size: Finally, add the size of the IFD tag entries
+ * themselves. */
+ if (!(tif->tif_flags & TIFF_BIGTIFF))
+ tif->tif_dir.td_dirdatasize_write += 2 + ndir * 12 + 4;
+ else
+ tif->tif_dir.td_dirdatasize_write += 8 + ndir * 20 + 8;
+
+ /* Setup a new directory within first pass. */
dir = _TIFFmallocExt(tif, ndir * sizeof(TIFFDirEntry));
if (dir == NULL)
{
@@ -1095,18 +1122,58 @@
}
if (isimage)
{
- if ((tif->tif_diroff == 0) && (!TIFFLinkDirectory(tif)))
- goto bad;
+ /* Check, weather the IFD to be written is new or an already written
+ * IFD can be overwritten or needs to be re-written to a different
+ * location in the file because the IFD is extended with additional
+ * tags or the IFD data size is increased.
+ * - tif_diroff == 0, if a new directory has to be linked.
+ * - tif_diroff != 0, IFD has been re-read from file and will be
+ * overwritten or re-written.
+ */
+ if (tif->tif_diroff == 0)
+ {
+ if (!TIFFLinkDirectory(tif))
+ goto bad;
+ }
+ else if (tif->tif_dir.td_dirdatasize_write >
+ tif->tif_dir.td_dirdatasize_read)
+ {
+ if (dir != NULL)
+ {
+ _TIFFfreeExt(tif, dir);
+ dir = NULL;
+ }
+ if (!TIFFRewriteDirectorySec(tif, isimage, imagedone, pdiroff))
+ goto bad;
+ return (1);
+ }
}
else
- tif->tif_diroff =
- (TIFFSeekFile(tif, 0, SEEK_END) + 1) & (~((toff_t)1));
+ {
+ /* For !isimage, which means custom-IFD like EXIFIFD or
+ * checkpointing an IFD, determine whether to overwrite or append at
+ * the end of the file.
+ */
+ if (!((tif->tif_dir.td_dirdatasize_read > 0) &&
+ (tif->tif_dir.td_dirdatasize_write <=
+ tif->tif_dir.td_dirdatasize_read)))
+ {
+ /* Append at end of file and increment to an even offset. */
+ tif->tif_diroff =
+ (TIFFSeekFile(tif, 0, SEEK_END) + 1) & (~((toff_t)1));
+ }
+ }
+ /* Return IFD offset */
if (pdiroff != NULL)
*pdiroff = tif->tif_diroff;
if (!(tif->tif_flags & TIFF_BIGTIFF))
dirsize = 2 + ndir * 12 + 4;
else
dirsize = 8 + ndir * 20 + 8;
+ /* Append IFD data stright after the IFD tag entries.
+ * Data that does not fit into an IFD tag entry is written to the file
+ * in the second pass of the while loop. That offset is stored in "dir".
+ */
tif->tif_dataoff = tif->tif_diroff + dirsize;
if (!(tif->tif_flags & TIFF_BIGTIFF))
tif->tif_dataoff = (uint32_t)tif->tif_dataoff;
@@ -1118,16 +1185,12 @@
}
if (tif->tif_dataoff & 1)
tif->tif_dataoff++;
- if (isimage)
- {
- if (tif->tif_curdir == TIFF_NON_EXISTENT_DIR_NUMBER)
- tif->tif_curdir = 0;
- else
- tif->tif_curdir++;
- }
- }
+ } /* while() */
if (isimage)
{
+ /* For SubIFDs remember offset of SubIFD tag within main IFD.
+ * However, might be already done in TIFFWriteDirectoryTagSubifd() if
+ * there are more than one SubIFD. */
if (TIFFFieldSet(tif, FIELD_SUBIFD) && (tif->tif_subifdoff == 0))
{
uint32_t na;
@@ -1148,6 +1211,8 @@
tif->tif_subifdoff = tif->tif_diroff + 8 + na * 20 + 12;
}
}
+ /* Copy/swab IFD entries from "dir" into "dirmem",
+ * which is then written to file. */
dirmem = _TIFFmallocExt(tif, dirsize);
if (dirmem == NULL)
{
@@ -1227,7 +1292,8 @@
dir = NULL;
if (!SeekOK(tif, tif->tif_diroff))
{
- TIFFErrorExtR(tif, module, "IO error writing directory");
+ TIFFErrorExtR(tif, module,
+ "IO error writing directory at seek to offset");
goto bad;
}
if (!WriteOK(tif, dirmem, (tmsize_t)dirsize))
@@ -1236,18 +1302,83 @@
goto bad;
}
_TIFFfreeExt(tif, dirmem);
+
+ /* Increment tif_curdir if IFD wasn't already written to file and no error
+ * occurred during IFD writing above. */
+ if (isimage && !tif->tif_dir.td_iswrittentofile)
+ {
+ if (!((tif->tif_flags & TIFF_INSUBIFD) &&
+ !(TIFFFieldSet(tif, FIELD_SUBIFD))))
+ {
+ /*-- Normal main-IFD case --*/
+ if (tif->tif_curdircount != TIFF_NON_EXISTENT_DIR_NUMBER)
+ {
+ tif->tif_curdir = tif->tif_curdircount;
+ }
+ else
+ {
+ /*ToDo SU: NEW_IFD_CURDIR_INCREMENTING: Delete this
+ * unexpected case after some testing time. */
+ /* Attention: tif->tif_curdircount is already set within
+ * TIFFNumberOfDirectories() */
+ tif->tif_curdircount = TIFFNumberOfDirectories(tif);
+ tif->tif_curdir = tif->tif_curdircount;
+ TIFFErrorExtR(
+ tif, module,
+ "tif_curdircount is TIFF_NON_EXISTENT_DIR_NUMBER, "
+ "not expected !! Line %d",
+ __LINE__);
+ goto bad;
+ }
+ }
+ else
+ {
+ /*-- SubIFD case -- */
+ /* tif_curdir is always set to 0 for all SubIFDs. */
+ tif->tif_curdir = 0;
+ }
+ }
+ /* Increment tif_curdircount only if main-IFD of an image was not already
+ * present on file. */
+ /* Check in combination with (... && !(TIFFFieldSet(tif, FIELD_SUBIFD)))
+ * is necessary here because TIFF_INSUBIFD was already set above for the
+ * next SubIFD when this main-IFD (with FIELD_SUBIFD) is currently being
+ * written. */
+ if (isimage && !tif->tif_dir.td_iswrittentofile &&
+ !((tif->tif_flags & TIFF_INSUBIFD) &&
+ !(TIFFFieldSet(tif, FIELD_SUBIFD))))
+ tif->tif_curdircount++;
+
+ tif->tif_dir.td_iswrittentofile = TRUE;
+
+ /* Reset SubIFD writing stage after last SubIFD has been written. */
+ if (imagedone && (tif->tif_flags & TIFF_INSUBIFD) && tif->tif_nsubifd == 0)
+ tif->tif_flags &= ~TIFF_INSUBIFD;
+
+ /* Add or update this directory to the IFD list. */
+ if (!_TIFFCheckDirNumberAndOffset(tif, tif->tif_curdir, tif->tif_diroff))
+ {
+ TIFFErrorExtR(tif, module,
+ "Starting directory %u at offset 0x%" PRIx64 " (%" PRIu64
+ ") might cause an IFD loop",
+ tif->tif_curdir, tif->tif_diroff, tif->tif_diroff);
+ }
+
if (imagedone)
{
TIFFFreeDirectory(tif);
tif->tif_flags &= ~TIFF_DIRTYDIRECT;
tif->tif_flags &= ~TIFF_DIRTYSTRIP;
(*tif->tif_cleanup)(tif);
- /*
- * Reset directory-related state for subsequent
- * directories.
- */
+ /* Reset directory-related state for subsequent directories. */
TIFFCreateDirectory(tif);
}
+ else
+ {
+ /* IFD is only checkpointed to file (or a custom IFD like EXIF is
+ * written), thus set IFD data size written to file. */
+ tif->tif_dir.td_dirdatasize_read = tif->tif_dir.td_dirdatasize_write;
+ }
return (1);
bad:
if (dir != NULL)
@@ -1401,11 +1532,6 @@
TIFFDirEntry *dir, uint16_t tag,
uint32_t count, char *value)
{
- if (dir == NULL)
- {
- (*ndir)++;
- return (1);
- }
return (
TIFFWriteDirectoryTagCheckedAscii(tif, ndir, dir, tag, count, value));
}
@@ -1414,11 +1540,6 @@
TIFFDirEntry *dir, uint16_t tag,
uint32_t count, uint8_t *value)
{
- if (dir == NULL)
- {
- (*ndir)++;
- return (1);
- }
return (TIFFWriteDirectoryTagCheckedUndefinedArray(tif, ndir, dir, tag,
count, value));
}
@@ -1427,11 +1548,6 @@
TIFFDirEntry *dir, uint16_t tag,
uint32_t count, uint8_t *value)
{
- if (dir == NULL)
- {
- (*ndir)++;
- return (1);
- }
return (TIFFWriteDirectoryTagCheckedByteArray(tif, ndir, dir, tag, count,
value));
}
@@ -1440,11 +1556,6 @@
TIFFDirEntry *dir, uint16_t tag,
uint32_t count, int8_t *value)
{
- if (dir == NULL)
- {
- (*ndir)++;
- return (1);
- }
return (TIFFWriteDirectoryTagCheckedSbyteArray(tif, ndir, dir, tag, count,
value));
}
@@ -1453,11 +1564,6 @@
TIFFDirEntry *dir, uint16_t tag,
uint16_t value)
{
- if (dir == NULL)
- {
- (*ndir)++;
- return (1);
- }
return (TIFFWriteDirectoryTagCheckedShort(tif, ndir, dir, tag, value));
}
@@ -1465,11 +1571,6 @@
TIFFDirEntry *dir, uint16_t tag,
uint32_t count, uint16_t *value)
{
- if (dir == NULL)
- {
- (*ndir)++;
- return (1);
- }
return (TIFFWriteDirectoryTagCheckedShortArray(tif, ndir, dir, tag, count,
value));
}
@@ -1485,8 +1586,9 @@
int o;
if (dir == NULL)
{
- (*ndir)++;
- return (1);
+ /* only evaluate IFD data size and inc. ndir */
+ return (TIFFWriteDirectoryTagCheckedShortArray(
+ tif, ndir, dir, tag, tif->tif_dir.td_samplesperpixel, NULL));
}
m = _TIFFmallocExt(tif, tif->tif_dir.td_samplesperpixel * sizeof(uint16_t));
if (m == NULL)
@@ -1506,11 +1608,6 @@
TIFFDirEntry *dir, uint16_t tag,
uint32_t count, int16_t *value)
{
- if (dir == NULL)
- {
- (*ndir)++;
- return (1);
- }
return (TIFFWriteDirectoryTagCheckedSshortArray(tif, ndir, dir, tag, count,
value));
}
@@ -1519,11 +1616,6 @@
TIFFDirEntry *dir, uint16_t tag,
uint32_t value)
{
- if (dir == NULL)
- {
- (*ndir)++;
- return (1);
- }
return (TIFFWriteDirectoryTagCheckedLong(tif, ndir, dir, tag, value));
}
@@ -1531,11 +1623,6 @@
TIFFDirEntry *dir, uint16_t tag,
uint32_t count, uint32_t *value)
{
- if (dir == NULL)
- {
- (*ndir)++;
- return (1);
- }
return (TIFFWriteDirectoryTagCheckedLongArray(tif, ndir, dir, tag, count,
value));
}
@@ -1544,11 +1631,6 @@
TIFFDirEntry *dir, uint16_t tag,
uint32_t count, int32_t *value)
{
- if (dir == NULL)
- {
- (*ndir)++;
- return (1);
- }
return (TIFFWriteDirectoryTagCheckedSlongArray(tif, ndir, dir, tag, count,
value));
}
@@ -1572,8 +1654,9 @@
/* is this just a counting pass? */
if (dir == NULL)
{
- (*ndir)++;
- return (1);
+ /* 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. */
@@ -1632,8 +1715,9 @@
/* is this just a counting pass? */
if (dir == NULL)
{
- (*ndir)++;
- return (1);
+ /* 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)
@@ -1686,11 +1770,6 @@
TIFFDirEntry *dir, uint16_t tag,
double value)
{
- if (dir == NULL)
- {
- (*ndir)++;
- return (1);
- }
return (TIFFWriteDirectoryTagCheckedRational(tif, ndir, dir, tag, value));
}
@@ -1698,11 +1777,6 @@
TIFFDirEntry *dir, uint16_t tag,
uint32_t count, float *value)
{
- if (dir == NULL)
- {
- (*ndir)++;
- return (1);
- }
return (TIFFWriteDirectoryTagCheckedRationalArray(tif, ndir, dir, tag,
count, value));
}
@@ -1711,11 +1785,6 @@
TIFFDirEntry *dir, uint16_t tag,
uint32_t count, float *value)
{
- if (dir == NULL)
- {
- (*ndir)++;
- return (1);
- }
return (TIFFWriteDirectoryTagCheckedSrationalArray(tif, ndir, dir, tag,
count, value));
}
@@ -1727,11 +1796,6 @@
uint32_t count,
double *value)
{
- if (dir == NULL)
- {
- (*ndir)++;
- return (1);
- }
return (TIFFWriteDirectoryTagCheckedRationalDoubleArray(tif, ndir, dir, tag,
count, value));
}
@@ -1742,11 +1806,6 @@
uint32_t count,
double *value)
{
- if (dir == NULL)
- {
- (*ndir)++;
- return (1);
- }
return (TIFFWriteDirectoryTagCheckedSrationalDoubleArray(
tif, ndir, dir, tag, count, value));
}
@@ -1755,11 +1814,6 @@
TIFFDirEntry *dir, uint16_t tag,
uint32_t count, float *value)
{
- if (dir == NULL)
- {
- (*ndir)++;
- return (1);
- }
return (TIFFWriteDirectoryTagCheckedFloatArray(tif, ndir, dir, tag, count,
value));
}
@@ -1768,11 +1822,6 @@
TIFFDirEntry *dir, uint16_t tag,
uint32_t count, double *value)
{
- if (dir == NULL)
- {
- (*ndir)++;
- return (1);
- }
return (TIFFWriteDirectoryTagCheckedDoubleArray(tif, ndir, dir, tag, count,
value));
}
@@ -1781,11 +1830,6 @@
TIFFDirEntry *dir, uint16_t tag,
uint32_t count, uint32_t *value)
{
- if (dir == NULL)
- {
- (*ndir)++;
- return (1);
- }
return (TIFFWriteDirectoryTagCheckedIfdArray(tif, ndir, dir, tag, count,
value));
}
@@ -1794,11 +1838,6 @@
TIFFDirEntry *dir, uint16_t tag,
uint32_t value)
{
- if (dir == NULL)
- {
- (*ndir)++;
- return (1);
- }
if (value <= 0xFFFF)
return (TIFFWriteDirectoryTagCheckedShort(tif, ndir, dir, tag,
(uint16_t)value));
@@ -1824,7 +1863,7 @@
compression == COMPRESSION_WEBP || compression == COMPRESSION_JXL)
{
/* For a few select compression types, we assume that in the worst */
- /* case the compressed size will be 10 times the uncompressed size */
+ /* case the compressed size will be 10 times the uncompressed size. */
/* This is overly pessismistic ! */
return strile_size >= uncompressed_threshold / 10;
}
@@ -1856,15 +1895,16 @@
int o;
int write_aslong4;
- /* is this just a counting pass? */
- if (dir == NULL)
- {
- (*ndir)++;
- return (1);
- }
-
if (tif->tif_dir.td_deferstrilearraywriting)
{
+ if (dir == NULL)
+ {
+ /* This is just a counting pass to count IFD entries.
+ * For deferstrilearraywriting no extra bytes will be written
+ * into IFD space. */
+ (*ndir)++;
+ return 1;
+ }
return TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_NOTYPE, 0, 0,
NULL);
}
@@ -1872,12 +1912,10 @@
if (tif->tif_flags & TIFF_BIGTIFF)
{
int write_aslong8 = 1;
- /* In the case of ByteCounts array, we may be able to write them on */
- /* LONG if the strip/tilesize is not too big. */
- /* Also do that for count > 1 in the case someone would want to create
- */
- /* a single-strip file with a growing height, in which case using */
- /* LONG8 will be safer. */
+ /* In the case of ByteCounts array, we may be able to write them on LONG
+ * if the strip/tilesize is not too big. Also do that for count > 1 in
+ * the case someone would want to create a single-strip file with a
+ * growing height, in which case using LONG8 will be safer. */
if (count > 1 && tag == TIFFTAG_STRIPBYTECOUNTS)
{
write_aslong8 = WriteAsLong8(tif, TIFFStripSize64(tif));
@@ -1989,13 +2027,6 @@
uint32_t *q;
int o;
- /* is this just a counting pass? */
- if (dir == NULL)
- {
- (*ndir)++;
- return (1);
- }
-
/* We always write IFD8 for BigTIFF, no checking needed. */
if (tif->tif_flags & TIFF_BIGTIFF)
return TIFFWriteDirectoryTagCheckedIfd8Array(tif, ndir, dir, tag, count,
@@ -2032,6 +2063,26 @@
return (o);
}
+/*
+ * Auxiliary function to determine the IFD data size to be written to the file.
+ * The IFD data size is finally the size of the IFD tag entries plus the IFD
+ * data that is written directly after the IFD tag entries.
+ */
+static void EvaluateIFDdatasizeWrite(TIFF *tif, uint32_t count,
+ uint32_t typesize, uint32_t *ndir)
+{
+ uint64_t datalength = (uint64_t)count * typesize;
+ if (datalength > ((tif->tif_flags & TIFF_BIGTIFF) ? 0x8U : 0x4U))
+ {
+ /* LibTIFF increments write address to an even offset, thus datalength
+ * written is also incremented. */
+ if (datalength & 1)
+ datalength++;
+ tif->tif_dir.td_dirdatasize_write += datalength;
+ }
+ (*ndir)++;
+}
+
static int TIFFWriteDirectoryTagColormap(TIFF *tif, uint32_t *ndir,
TIFFDirEntry *dir)
{
@@ -2039,12 +2090,13 @@
uint32_t m;
uint16_t *n;
int o;
- if (dir == NULL)
- {
- (*ndir)++;
- return (1);
- }
m = (1 << tif->tif_dir.td_bitspersample);
+ if (dir == NULL) /* Just evaluate IFD data size and increment ndir. */
+ {
+ EvaluateIFDdatasizeWrite(tif, 3 * m, sizeof(uint16_t), ndir);
+ return 1;
+ }
+
n = _TIFFmallocExt(tif, 3 * m * sizeof(uint16_t));
if (n == NULL)
{
@@ -2068,11 +2120,6 @@
uint16_t n;
uint16_t *o;
int p;
- if (dir == NULL)
- {
- (*ndir)++;
- return (1);
- }
/* TIFFTAG_TRANSFERFUNCTION expects (1 or 3) pointer to arrays with
* (1 << BitsPerSample) * uint16_t values.
*/
@@ -2086,9 +2133,9 @@
{
if (tif->tif_dir.td_transferfunction[i] == NULL)
{
- TIFFWarningExtR(
- tif, module,
- "Too few TransferFunctions provided. Tag not written to file");
+ TIFFWarningExtR(tif, module,
+ "Too few TransferFunctions provided. Tag "
+ "not written to file");
return (1); /* Not an error; only tag is not written. */
}
}
@@ -2108,6 +2155,12 @@
m * sizeof(uint16_t)))
n = 1;
}
+ if (dir == NULL) /* Just evaluate IFD data size and increment ndir. */
+ {
+ EvaluateIFDdatasizeWrite(tif, n * m, 2, ndir);
+ return 1;
+ }
+
o = _TIFFmallocExt(tif, n * m * sizeof(uint16_t));
if (o == NULL)
{
@@ -2136,11 +2189,6 @@
int n;
if (tif->tif_dir.td_nsubifd == 0)
return (1);
- if (dir == NULL)
- {
- (*ndir)++;
- return (1);
- }
m = tif->tif_dataoff;
if (!(tif->tif_flags & TIFF_BIGTIFF))
{
@@ -2178,6 +2226,12 @@
n = TIFFWriteDirectoryTagCheckedIfd8Array(
tif, ndir, dir, TIFFTAG_SUBIFD, tif->tif_dir.td_nsubifd,
tif->tif_dir.td_subifd);
+
+ if (dir == NULL)
+ /* Just have evaluated IFD data size and incremented ndir
+ * above in sub-functions. */
+ return (n);
+
if (!n)
return (0);
/*
@@ -2202,6 +2256,11 @@
uint32_t count, char *value)
{
assert(sizeof(char) == 1);
+ if (dir == NULL) /* Just evaluate IFD data size and increment ndir. */
+ {
+ EvaluateIFDdatasizeWrite(tif, count, 1, ndir);
+ return 1;
+ }
return (TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_ASCII, count,
count, value));
}
@@ -2213,6 +2272,11 @@
uint8_t *value)
{
assert(sizeof(uint8_t) == 1);
+ if (dir == NULL) /* Just evaluate IFD data size and increment ndir. */
+ {
+ EvaluateIFDdatasizeWrite(tif, count, 1, ndir);
+ return 1;
+ }
return (TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_UNDEFINED,
count, count, value));
}
@@ -2223,6 +2287,11 @@
uint8_t *value)
{
assert(sizeof(uint8_t) == 1);
+ if (dir == NULL) /* Just evaluate IFD data size and increment ndir. */
+ {
+ EvaluateIFDdatasizeWrite(tif, count, 1, ndir);
+ return 1;
+ }
return (TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_BYTE, count,
count, value));
}
@@ -2233,6 +2302,11 @@
int8_t *value)
{
assert(sizeof(int8_t) == 1);
+ if (dir == NULL) /* Just evaluate IFD data size and increment ndir. */
+ {
+ EvaluateIFDdatasizeWrite(tif, count, 1, ndir);
+ return 1;
+ }
return (TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_SBYTE, count,
count, value));
}
@@ -2243,6 +2317,12 @@
{
uint16_t m;
assert(sizeof(uint16_t) == 2);
+ if (dir == NULL)
+ {
+ /* No additional data to IFD data size just increment ndir. */
+ (*ndir)++;
+ return 1;
+ }
m = value;
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabShort(&m);
@@ -2257,6 +2337,11 @@
{
assert(count < 0x80000000);
assert(sizeof(uint16_t) == 2);
+ if (dir == NULL) /* Just evaluate IFD data size and increment ndir. */
+ {
+ EvaluateIFDdatasizeWrite(tif, count, 2, ndir);
+ return 1;
+ }
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabArrayOfShort(value, count);
return (TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_SHORT, count,
@@ -2270,6 +2355,11 @@
{
assert(count < 0x80000000);
assert(sizeof(int16_t) == 2);
+ if (dir == NULL) /* Just evaluate IFD data size and increment ndir. */
+ {
+ EvaluateIFDdatasizeWrite(tif, count, 2, ndir);
+ return 1;
+ }
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabArrayOfShort((uint16_t *)value, count);
return (TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_SSHORT, count,
@@ -2282,6 +2372,12 @@
{
uint32_t m;
assert(sizeof(uint32_t) == 4);
+ if (dir == NULL)
+ {
+ /* No additional data to IFD data size just increment ndir. */
+ (*ndir)++;
+ return 1;
+ }
m = value;
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabLong(&m);
@@ -2296,6 +2392,11 @@
{
assert(count < 0x40000000);
assert(sizeof(uint32_t) == 4);
+ if (dir == NULL) /* Just evaluate IFD data size and increment ndir. */
+ {
+ EvaluateIFDdatasizeWrite(tif, count, 4, ndir);
+ return 1;
+ }
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabArrayOfLong(value, count);
return (TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_LONG, count,
@@ -2309,6 +2410,11 @@
{
assert(count < 0x40000000);
assert(sizeof(int32_t) == 4);
+ if (dir == NULL) /* Just evaluate IFD data size and increment ndir. */
+ {
+ EvaluateIFDdatasizeWrite(tif, count, 4, ndir);
+ return 1;
+ }
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabArrayOfLong((uint32_t *)value, count);
return (TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_SLONG, count,
@@ -2328,6 +2434,11 @@
"LONG8 not allowed for ClassicTIFF");
return (0);
}
+ if (dir == NULL) /* Just evaluate IFD data size and increment ndir. */
+ {
+ EvaluateIFDdatasizeWrite(tif, count, 8, ndir);
+ return 1;
+ }
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabArrayOfLong8(value, count);
return (TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_LONG8, count,
@@ -2347,6 +2458,11 @@
"SLONG8 not allowed for ClassicTIFF");
return (0);
}
+ if (dir == NULL) /* Just evaluate IFD data size and increment ndir. */
+ {
+ EvaluateIFDdatasizeWrite(tif, count, 8, ndir);
+ return 1;
+ }
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabArrayOfLong8((uint64_t *)value, count);
return (TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_SLONG8, count,
@@ -2370,16 +2486,17 @@
TIFFErrorExtR(tif, module, "Not-a-number value is illegal");
return 0;
}
- /*--Rational2Double: New function also used for non-custom rational tags.
- * However, could be omitted here, because
- * TIFFWriteDirectoryTagCheckedRational() is not used by code for custom
- * tags, only by code for named-tiff-tags like FIELD_RESOLUTION and
- * FIELD_POSITION */
- else
+
+ if (dir == NULL) /* Just evaluate IFD data size and increment ndir. */
{
- DoubleToRational(value, &m[0], &m[1]);
+ tif->tif_dir.td_dirdatasize_write +=
+ (tif->tif_flags & TIFF_BIGTIFF) ? 0 : 0x8U;
+ (*ndir)++;
+ return 1;
}
+ DoubleToRational(value, &m[0], &m[1]);
+
if (tif->tif_flags & TIFF_SWAB)
{
TIFFSwabLong(&m[0]);
@@ -2402,6 +2519,11 @@
uint32_t nc;
int o;
assert(sizeof(uint32_t) == 4);
+ if (dir == NULL) /* Just evaluate IFD data size and increment ndir. */
+ {
+ EvaluateIFDdatasizeWrite(tif, count * 2, sizeof(uint32_t), ndir);
+ return 1;
+ }
m = _TIFFmallocExt(tif, count * 2 * sizeof(uint32_t));
if (m == NULL)
{
@@ -2433,6 +2555,11 @@
uint32_t nc;
int o;
assert(sizeof(int32_t) == 4);
+ if (dir == NULL) /* Just evaluate IFD data size and increment ndir. */
+ {
+ EvaluateIFDdatasizeWrite(tif, count * 2, sizeof(int32_t), ndir);
+ return 1;
+ }
m = _TIFFmallocExt(tif, count * 2 * sizeof(int32_t));
if (m == NULL)
{
@@ -2465,6 +2592,11 @@
uint32_t nc;
int o;
assert(sizeof(uint32_t) == 4);
+ if (dir == NULL) /* Just evaluate IFD data size and increment ndir. */
+ {
+ EvaluateIFDdatasizeWrite(tif, count * 2, sizeof(uint32_t), ndir);
+ return 1;
+ }
m = _TIFFmallocExt(tif, count * 2 * sizeof(uint32_t));
if (m == NULL)
{
@@ -2495,6 +2627,11 @@
uint32_t nc;
int o;
assert(sizeof(int32_t) == 4);
+ if (dir == NULL) /* Just evaluate IFD data size and increment ndir. */
+ {
+ EvaluateIFDdatasizeWrite(tif, count * 2, sizeof(int32_t), ndir);
+ return 1;
+ }
m = _TIFFmallocExt(tif, count * 2 * sizeof(int32_t));
if (m == NULL)
{
@@ -2816,6 +2953,11 @@
{
assert(count < 0x40000000);
assert(sizeof(float) == 4);
+ if (dir == NULL) /* Just evaluate IFD data size and increment ndir. */
+ {
+ EvaluateIFDdatasizeWrite(tif, count, 4, ndir);
+ return 1;
+ }
TIFFCvtNativeToIEEEFloat(tif, count, &value);
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabArrayOfFloat(value, count);
@@ -2830,6 +2972,11 @@
{
assert(count < 0x20000000);
assert(sizeof(double) == 8);
+ if (dir == NULL) /* Just evaluate IFD data size and increment ndir. */
+ {
+ EvaluateIFDdatasizeWrite(tif, count, 8, ndir);
+ return 1;
+ }
TIFFCvtNativeToIEEEDouble(tif, count, &value);
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabArrayOfDouble(value, count);
@@ -2843,6 +2990,11 @@
{
assert(count < 0x40000000);
assert(sizeof(uint32_t) == 4);
+ if (dir == NULL) /* Just evaluate IFD data size and increment ndir. */
+ {
+ EvaluateIFDdatasizeWrite(tif, count, 4, ndir);
+ return 1;
+ }
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabArrayOfLong(value, count);
return (TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_IFD, count,
@@ -2857,6 +3009,11 @@
assert(count < 0x20000000);
assert(sizeof(uint64_t) == 8);
assert(tif->tif_flags & TIFF_BIGTIFF);
+ if (dir == NULL) /* Just evaluate IFD data size and increment ndir. */
+ {
+ EvaluateIFDdatasizeWrite(tif, count, 8, ndir);
+ return 1;
+ }
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabArrayOfLong8(value, count);
return (TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_IFD8, count,
@@ -2973,15 +3130,15 @@
"Error writing SubIFD directory link");
return (0);
}
+
/*
* Advance to the next SubIFD or, if this is
- * the last one configured, revert back to the
- * normal directory linkage.
+ * the last one configured, reverting back to the
+ * normal directory linkage is done in TIFFWriteDirectorySec()
+ * by tif->tif_flags &= ~TIFF_INSUBIFD;.
*/
if (--tif->tif_nsubifd)
tif->tif_subifdoff += 4;
- else
- tif->tif_flags &= ~TIFF_INSUBIFD;
return (1);
}
else
@@ -2997,19 +3154,23 @@
"Error writing SubIFD directory link");
return (0);
}
+
/*
* Advance to the next SubIFD or, if this is
- * the last one configured, revert back to the
- * normal directory linkage.
+ * the last one configured, reverting back to the
+ * normal directory linkage is done in TIFFWriteDirectorySec()
+ * by tif->tif_flags &= ~TIFF_INSUBIFD;.
*/
if (--tif->tif_nsubifd)
tif->tif_subifdoff += 8;
- else
- tif->tif_flags &= ~TIFF_INSUBIFD;
return (1);
}
}
+ /*
+ * Handle main-IFDs
+ */
+ tdir_t ndir = 1; /* count current number of main-IFDs */
if (!(tif->tif_flags & TIFF_BIGTIFF))
{
uint32_t m;
@@ -3030,18 +3191,26 @@
TIFFErrorExtR(tif, tif->tif_name, "Error writing TIFF header");
return (0);
}
+ if (!tif->tif_dir.td_iswrittentofile)
+ tif->tif_curdircount = 0;
return (1);
}
/*
* Not the first directory, search to the last and append.
*/
- if (tif->tif_lastdiroff != 0)
+ tdir_t dirn = 0;
+ if (tif->tif_lastdiroff != 0 &&
+ _TIFFGetDirNumberFromOffset(tif, tif->tif_lastdiroff, &dirn))
{
+ /* Start searching from the lastely written IFD. Thus get its IFD
+ * number. */
nextdir = (uint32_t)tif->tif_lastdiroff;
+ ndir = dirn + 1;
}
else
{
nextdir = tif->tif_header.classic.tiff_diroff;
+ ndir = 1; /* start searching from the first IFD */
}
while (1)
@@ -3076,10 +3245,12 @@
break;
}
nextdir = nextnextdir;
+ ndir++;
}
}
else
{
+ /*- BigTIFF -*/
uint64_t m;
uint64_t nextdir;
m = tif->tif_diroff;
@@ -3098,18 +3269,26 @@
TIFFErrorExtR(tif, tif->tif_name, "Error writing TIFF header");
return (0);
}
+ if (!tif->tif_dir.td_iswrittentofile)
+ tif->tif_curdircount = 0;
return (1);
}
/*
* Not the first directory, search to the last and append.
*/
- if (tif->tif_lastdiroff != 0)
+ tdir_t dirn = 0;
+ if (tif->tif_lastdiroff != 0 &&
+ _TIFFGetDirNumberFromOffset(tif, tif->tif_lastdiroff, &dirn))
{
+ /* Start searching from the lastely written IFD. Thus get its IFD
+ * number. */
nextdir = tif->tif_lastdiroff;
+ ndir = dirn + 1;
}
else
{
nextdir = tif->tif_header.big.tiff_diroff;
+ ndir = 1; /* start searching from the first IFD */
}
while (1)
{
@@ -3126,9 +3305,9 @@
TIFFSwabLong8(&dircount64);
if (dircount64 > 0xFFFF)
{
- TIFFErrorExtR(
- tif, module,
- "Sanity check on tag count failed, likely corrupt TIFF");
+ TIFFErrorExtR(tif, module,
+ "Sanity check on tag count failed, "
+ "likely corrupt TIFF");
return (0);
}
dircount = (uint16_t)dircount64;
@@ -3152,8 +3331,20 @@
break;
}
nextdir = nextnextdir;
+ ndir++;
}
}
+ /* Offset of next IFD is written to file.
+ * Update number of main-IFDs in file.
+ * However, tif_curdircount shall count only newly written main-IFDs with
+ * entries and not only number of linked offsets! Thus, tif_curdircount is
+ * incremented at the end of TIFFWriteDirectorySec().
+ * TIFF_NON_EXISTENT_DIR_NUMBER means 'dont know number of IFDs'
+ * 0 means 'empty file opened for writing, but no IFD written yet' */
+ if (!tif->tif_dir.td_iswrittentofile && !(tif->tif_flags & TIFF_INSUBIFD))
+ {
+ tif->tif_curdircount = ndir;
+ }
return (1);
}
@@ -3197,9 +3388,9 @@
/* -------------------------------------------------------------------- */
if (isMapped(tif))
{
- TIFFErrorExtR(
- tif, module,
- "Memory mapped files not currently supported for this operation.");
+ TIFFErrorExtR(tif, module,
+ "Memory mapped files not currently supported for "
+ "this operation.");
return 0;
}
diff --git a/third_party/libtiff/tif_fax3.c b/third_party/libtiff/tif_fax3.c
index a3c645c..01a7847 100644
--- a/third_party/libtiff/tif_fax3.c
+++ b/third_party/libtiff/tif_fax3.c
@@ -41,6 +41,14 @@
#include "t4.h"
#include <stdio.h>
+#ifndef EOF_REACHED_COUNT_THRESHOLD
+/* Arbitrary threshold to avoid corrupted single-strip files with extremely
+ * large imageheight to cause apparently endless looping, such as in
+ * https://gitlab.com/libtiff/libtiff/-/issues/583
+ */
+#define EOF_REACHED_COUNT_THRESHOLD 8192
+#endif
+
/*
* Compression+decompression state blocks are
* derived from this ``base state'' block.
@@ -77,6 +85,8 @@
uint32_t data; /* current i/o byte/word */
int bit; /* current i/o bit in byte */
int EOLcnt; /* count of EOL codes recognized */
+ int eofReachedCount; /* number of times decode has been called with
+ EOF already reached */
TIFFFaxFillFunc fill; /* fill routine */
uint32_t *runs; /* b&w runs for current/previous row */
uint32_t nruns; /* size of the refruns / curruns arrays */
@@ -120,6 +130,7 @@
int EOLcnt; /* # EOL codes recognized */ \
const unsigned char *bitmap = sp->bitmap; /* input data bit reverser */ \
const TIFFFaxTabEnt *TabEnt
+
#define DECLARE_STATE_2D(tif, sp, mod) \
DECLARE_STATE(tif, sp, mod); \
int b1; /* next change on prev line */ \
@@ -162,6 +173,7 @@
sp->bit = 0; /* force initial read */
sp->data = 0;
sp->EOLcnt = 0; /* force initial scan for EOL */
+ sp->eofReachedCount = 0;
/*
* Decoder assumes lsb-to-msb bit order. Note that we select
* this here rather than in Fax3SetupState so that viewers can
@@ -232,7 +244,12 @@
line, isTiled(tif) ? "tile" : "strip",
(isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip), a0);
}
-#define prematureEOF(a0) Fax3PrematureEOF(module, tif, sp->line, a0)
+#define prematureEOF(a0) \
+ do \
+ { \
+ Fax3PrematureEOF(module, tif, sp->line, a0); \
+ ++sp->eofReachedCount; \
+ } while (0)
#define Nop
@@ -252,6 +269,14 @@
TIFFErrorExtR(tif, module, "Fractional scanlines cannot be read");
return (-1);
}
+ if (sp->eofReachedCount >= EOF_REACHED_COUNT_THRESHOLD)
+ {
+ TIFFErrorExtR(
+ tif, module,
+ "End of file has already been reached %d times within that strip",
+ sp->eofReachedCount);
+ return (-1);
+ }
CACHE_STATE(tif, sp);
thisrun = sp->curruns;
while (occ > 0)
@@ -302,6 +327,14 @@
TIFFErrorExtR(tif, module, "Fractional scanlines cannot be read");
return (-1);
}
+ if (sp->eofReachedCount >= EOF_REACHED_COUNT_THRESHOLD)
+ {
+ TIFFErrorExtR(
+ tif, module,
+ "End of file has already been reached %d times within that strip",
+ sp->eofReachedCount);
+ return (-1);
+ }
CACHE_STATE(tif, sp);
while (occ > 0)
{
@@ -536,7 +569,11 @@
TIFFroundup and TIFFSafeMultiply return zero on integer overflow
*/
- dsp->runs = (uint32_t *)NULL;
+ if (dsp->runs != NULL)
+ {
+ _TIFFfreeExt(tif, dsp->runs);
+ dsp->runs = (uint32_t *)NULL;
+ }
dsp->nruns = TIFFroundup_32(rowpixels + 1, 32);
if (needsRefLine)
{
@@ -578,6 +615,10 @@
* is referenced. The reference line must
* be initialized to be ``white'' (done elsewhere).
*/
+ if (esp->refline != NULL)
+ {
+ _TIFFfreeExt(tif, esp->refline);
+ }
esp->refline = (unsigned char *)_TIFFmallocExt(tif, rowbytes);
if (esp->refline == NULL)
{
@@ -1514,7 +1555,16 @@
TIFFErrorExtR(tif, module, "Fractional scanlines cannot be read");
return (-1);
}
+ if (sp->eofReachedCount >= EOF_REACHED_COUNT_THRESHOLD)
+ {
+ TIFFErrorExtR(
+ tif, module,
+ "End of file has already been reached %d times within that strip",
+ sp->eofReachedCount);
+ return (-1);
+ }
CACHE_STATE(tif, sp);
+ int start = sp->line;
while (occ > 0)
{
a0 = 0;
@@ -1563,7 +1613,9 @@
}
(*sp->fill)(buf, thisrun, pa, lastx);
UNCACHE_STATE(tif, sp);
- return (sp->line ? 1 : -1); /* don't error on badly-terminated strips */
+ return (sp->line != start
+ ? 1
+ : -1); /* don't error on badly-terminated strips */
}
UNCACHE_STATE(tif, sp);
return (1);
diff --git a/third_party/libtiff/tif_getimage.c b/third_party/libtiff/tif_getimage.c
index f5a05e5..3ee0626 100644
--- a/third_party/libtiff/tif_getimage.c
+++ b/third_party/libtiff/tif_getimage.c
@@ -761,6 +761,12 @@
toskew = -(int32_t)(tw - w);
}
+ if (tw == 0 || th == 0)
+ {
+ TIFFErrorExtR(tif, TIFFFileName(tif), "tile width or height is zero");
+ return (0);
+ }
+
/*
* Leftmost tile is clipped on left side if col_offset > 0.
*/
@@ -936,6 +942,12 @@
break;
}
+ if (tw == 0 || th == 0)
+ {
+ TIFFErrorExtR(tif, TIFFFileName(tif), "tile width or height is zero");
+ return (0);
+ }
+
/*
* Leftmost tile is clipped on left side if col_offset > 0.
*/
@@ -1118,6 +1130,11 @@
}
TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
+ if (rowsperstrip == 0)
+ {
+ TIFFErrorExtR(tif, TIFFFileName(tif), "rowsperstrip is zero");
+ return (0);
+ }
scanline = TIFFScanlineSize(tif);
fromskew = (w < imagewidth ? imagewidth - w : 0);
@@ -1242,6 +1259,12 @@
}
TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
+ if (rowsperstrip == 0)
+ {
+ TIFFErrorExtR(tif, TIFFFileName(tif), "rowsperstrip is zero");
+ return (0);
+ }
+
scanline = TIFFScanlineSize(tif);
fromskew = (w < imagewidth ? imagewidth - w : 0);
for (row = 0; row < h; row += nrow)
@@ -3239,6 +3262,13 @@
}
TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
+
+ if (rowsperstrip == 0)
+ {
+ TIFFErrorExtR(tif, TIFFFileName(tif), "rowsperstrip is zero");
+ return (0);
+ }
+
if ((row % rowsperstrip) != 0)
{
TIFFErrorExtR(
@@ -3250,6 +3280,13 @@
if (TIFFRGBAImageOK(tif, emsg) &&
TIFFRGBAImageBegin(&img, tif, stop_on_error, emsg))
{
+ if (row >= img.height)
+ {
+ TIFFErrorExtR(tif, TIFFFileName(tif),
+ "Invalid row passed to TIFFReadRGBAStrip().");
+ TIFFRGBAImageEnd(&img);
+ return (0);
+ }
img.row_offset = row;
img.col_offset = 0;
@@ -3308,6 +3345,13 @@
TIFFGetFieldDefaulted(tif, TIFFTAG_TILEWIDTH, &tile_xsize);
TIFFGetFieldDefaulted(tif, TIFFTAG_TILELENGTH, &tile_ysize);
+ if (tile_xsize == 0 || tile_ysize == 0)
+ {
+ TIFFErrorExtR(tif, TIFFFileName(tif),
+ "tile_xsize or tile_ysize is zero");
+ return (0);
+ }
+
if ((col % tile_xsize) != 0 || (row % tile_ysize) != 0)
{
TIFFErrorExtR(tif, TIFFFileName(tif),
@@ -3327,6 +3371,14 @@
return (0);
}
+ if (col >= img.width || row >= img.height)
+ {
+ TIFFErrorExtR(tif, TIFFFileName(tif),
+ "Invalid row/col passed to TIFFReadRGBATile().");
+ TIFFRGBAImageEnd(&img);
+ return (0);
+ }
+
/*
* The TIFFRGBAImageGet() function doesn't allow us to get off the
* edge of the image, even to fill an otherwise valid tile. So we
diff --git a/third_party/libtiff/tif_hash_set.c b/third_party/libtiff/tif_hash_set.c
index cec22ab..9be488e 100644
--- a/third_party/libtiff/tif_hash_set.c
+++ b/third_party/libtiff/tif_hash_set.c
@@ -146,7 +146,7 @@
set->fnEqualFunc = fnEqualFunc ? fnEqualFunc : TIFFHashSetEqualPointer;
set->fnFreeEltFunc = fnFreeEltFunc;
set->nSize = 0;
- set->tabList = (TIFFList **)(calloc(sizeof(TIFFList *), 53));
+ set->tabList = (TIFFList **)(calloc(53, sizeof(TIFFList *)));
if (set->tabList == NULL)
{
free(set);
@@ -367,7 +367,7 @@
{
int nNewAllocatedSize = anPrimes[set->nIndiceAllocatedSize];
TIFFList **newTabList =
- (TIFFList **)(calloc(sizeof(TIFFList *), nNewAllocatedSize));
+ (TIFFList **)(calloc(nNewAllocatedSize, sizeof(TIFFList *)));
if (newTabList == NULL)
return false;
#ifdef HASH_DEBUG
diff --git a/third_party/libtiff/tif_jpeg.c b/third_party/libtiff/tif_jpeg.c
index a7dbde7..8eb2f74 100644
--- a/third_party/libtiff/tif_jpeg.c
+++ b/third_party/libtiff/tif_jpeg.c
@@ -73,43 +73,6 @@
int scheme, int is_encode);
int TIFFJPEGIsFullStripRequired_12(TIFF *tif);
-/* We undefine FAR to avoid conflict with JPEG definition */
-
-#ifdef FAR
-#undef FAR
-#endif
-
-/*
- Libjpeg's jmorecfg.h defines INT16 and INT32, but only if XMD_H is
- not defined. Unfortunately, the MinGW and Borland compilers include
- a typedef for INT32, which causes a conflict. MSVC does not include
- a conflicting typedef given the headers which are included.
-*/
-#if defined(__BORLANDC__) || defined(__MINGW32__)
-#define XMD_H 1
-#endif
-
-/*
- The windows RPCNDR.H file defines boolean, but defines it with the
- unsigned char size. You should compile JPEG library using appropriate
- definitions in jconfig.h header, but many users compile library in wrong
- way. That causes errors of the following type:
-
- "JPEGLib: JPEG parameter struct mismatch: library thinks size is 432,
- caller expects 464"
-
- For such users we will fix the problem here. See install.doc file from
- the JPEG library distribution for details.
-*/
-
-/* Define "boolean" as unsigned char, not int, per Windows custom. */
-#if defined(__WIN32__) && !defined(__MINGW32__)
-#ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */
-typedef unsigned char boolean;
-#endif
-#define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */
-#endif
-
#if defined(USE_SYSTEM_LIBJPEG)
#include <jerror.h>
#include <jpeglib.h>
@@ -133,18 +96,18 @@
* 16bit value?
*/
-/* HAVE_JPEGTURBO_DUAL_MODE_8_12 is defined for libjpeg-turbo >= 2.2 which
+/* HAVE_JPEGTURBO_DUAL_MODE_8_12 is defined for libjpeg-turbo >= 3.0 which
* adds a dual-mode 8/12 bit API in the same library.
*/
#if defined(HAVE_JPEGTURBO_DUAL_MODE_8_12)
#define JPEG_DUAL_MODE_8_12
/* Start by undefining BITS_IN_JSAMPLE which is always set to 8 in libjpeg-turbo
- * >= 2.2 Cf
+ * >= 3.0 Cf
* https://github.com/libjpeg-turbo/libjpeg-turbo/commit/8b9bc4b9635a2a047fb23ebe70c9acd728d3f99b
*/
#undef BITS_IN_JSAMPLE
-/* libjpeg-turbo >= 2.2 adds J12xxxx datatypes for the 12-bit mode. */
+/* libjpeg-turbo >= 3.0 adds J12xxxx datatypes for the 12-bit mode. */
#if defined(FROM_TIF_JPEG_12)
#define BITS_IN_JSAMPLE 12
#define TIFF_JSAMPLE J12SAMPLE
@@ -190,9 +153,20 @@
#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
/*
* State block for each open TIFF file using
@@ -1249,6 +1223,12 @@
* 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);
}
@@ -1479,7 +1459,10 @@
sp->src.bytes_in_buffer = (size_t)tif->tif_rawcc;
if (sp->bytesperline == 0)
+ {
+ memset(buf, 0, (size_t)cc);
return 0;
+ }
nrows = cc / sp->bytesperline;
if (cc % sp->bytesperline)
@@ -1500,7 +1483,10 @@
JSAMPROW bufptr = (JSAMPROW)buf;
if (TIFFjpeg_read_scanlines(sp, &bufptr, 1) != 1)
+ {
+ memset(buf, 0, (size_t)cc);
return (0);
+ }
++tif->tif_row;
buf += sp->bytesperline;
@@ -1534,7 +1520,10 @@
sp->src.bytes_in_buffer = (size_t)tif->tif_rawcc;
if (sp->bytesperline == 0)
+ {
+ memset(buf, 0, (size_t)cc);
return 0;
+ }
nrows = cc / sp->bytesperline;
if (cc % sp->bytesperline)
@@ -1570,7 +1559,10 @@
* for 12bit data, which we need to repack.
*/
if (TIFFjpeg_read_scanlines(sp, &line_work_buf, 1) != 1)
+ {
+ memset(buf, 0, (size_t)cc);
return (0);
+ }
if (sp->cinfo.d.data_precision == 12)
{
@@ -2198,6 +2190,12 @@
/* 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);
}
diff --git a/third_party/libtiff/tif_luv.c b/third_party/libtiff/tif_luv.c
index 021756d..d196535 100644
--- a/third_party/libtiff/tif_luv.c
+++ b/third_party/libtiff/tif_luv.c
@@ -951,7 +951,8 @@
int
uv_encode(double u, double v, int em) /* encode (u',v') coordinates */
{
- register int vi, ui;
+ unsigned int vi;
+ int ui;
/* check for NaN */
if (u != u || v != v)
@@ -980,8 +981,9 @@
int
uv_decode(double *up, double *vp, int c) /* decode (u',v') index */
{
- int upper, lower;
- register int ui, vi;
+ unsigned int upper, lower;
+ int ui;
+ unsigned int vi;
if (c < 0 || c >= UV_NDIVS)
return (-1);
diff --git a/third_party/libtiff/tif_lzw.c b/third_party/libtiff/tif_lzw.c
index d631fa1..4baf78e 100644
--- a/third_party/libtiff/tif_lzw.c
+++ b/third_party/libtiff/tif_lzw.c
@@ -161,8 +161,8 @@
} LZWCodecState;
#define LZWState(tif) ((LZWBaseState *)(tif)->tif_data)
-#define DecoderState(tif) ((LZWCodecState *)LZWState(tif))
-#define EncoderState(tif) ((LZWCodecState *)LZWState(tif))
+#define LZWDecoderState(tif) ((LZWCodecState *)LZWState(tif))
+#define LZWEncoderState(tif) ((LZWCodecState *)LZWState(tif))
static int LZWDecode(TIFF *tif, uint8_t *op0, tmsize_t occ0, uint16_t s);
#ifdef LZW_COMPAT
@@ -183,7 +183,7 @@
static int LZWSetupDecode(TIFF *tif)
{
static const char module[] = "LZWSetupDecode";
- LZWCodecState *sp = DecoderState(tif);
+ LZWCodecState *sp = LZWDecoderState(tif);
int code;
if (sp == NULL)
@@ -199,7 +199,7 @@
return (0);
}
- sp = DecoderState(tif);
+ sp = LZWDecoderState(tif);
sp->dec_codetab = NULL;
sp->dec_decode = NULL;
@@ -245,7 +245,7 @@
static int LZWPreDecode(TIFF *tif, uint16_t s)
{
static const char module[] = "LZWPreDecode";
- LZWCodecState *sp = DecoderState(tif);
+ LZWCodecState *sp = LZWDecoderState(tif);
(void)s;
assert(sp != NULL);
@@ -329,10 +329,7 @@
#ifdef WORDS_BIGENDIAN
#define GetNextData(nextdata, bp) memcpy(&nextdata, bp, sizeof(nextdata))
#elif SIZEOF_WORDTYPE == 8
-#if defined(__GNUC__) && defined(__x86_64__)
-#define GetNextData(nextdata, bp) \
- nextdata = __builtin_bswap64(*(uint64_t *)(bp))
-#elif defined(_M_X64)
+#if defined(_M_X64)
#define GetNextData(nextdata, bp) nextdata = _byteswap_uint64(*(uint64_t *)(bp))
#elif defined(__GNUC__)
#define GetNextData(nextdata, bp) \
@@ -346,10 +343,7 @@
(((uint64_t)bp[6]) << 8) | (((uint64_t)bp[7]))
#endif
#elif SIZEOF_WORDTYPE == 4
-#if defined(__GNUC__) && defined(__i386__)
-#define GetNextData(nextdata, bp) \
- nextdata = __builtin_bswap32(*(uint32_t *)(bp))
-#elif defined(_M_X86)
+#if defined(_M_X86)
#define GetNextData(nextdata, bp) \
nextdata = _byteswap_ulong(*(unsigned long *)(bp))
#elif defined(__GNUC__)
@@ -409,7 +403,7 @@
static int LZWDecode(TIFF *tif, uint8_t *op0, tmsize_t occ0, uint16_t s)
{
static const char module[] = "LZWDecode";
- LZWCodecState *sp = DecoderState(tif);
+ LZWCodecState *sp = LZWDecoderState(tif);
uint8_t *op = (uint8_t *)op0;
tmsize_t occ = occ0;
uint8_t *bp;
@@ -423,6 +417,7 @@
if (sp->read_error)
{
+ memset(op, 0, (size_t)occ);
TIFFErrorExtR(tif, module,
"LZWDecode: Scanline %" PRIu32 " cannot be read due to "
"previous error",
@@ -737,6 +732,7 @@
if (occ > 0)
{
+ memset(op, 0, (size_t)occ);
TIFFErrorExtR(tif, module,
"Not enough data at scanline %" PRIu32 " (short %" PRIu64
" bytes)",
@@ -746,12 +742,14 @@
return (1);
no_eoi:
+ memset(op, 0, (size_t)occ);
sp->read_error = 1;
TIFFErrorExtR(tif, module,
"LZWDecode: Strip %" PRIu32 " not terminated with EOI code",
tif->tif_curstrip);
return 0;
error_code:
+ memset(op, 0, (size_t)occ);
sp->read_error = 1;
TIFFErrorExtR(tif, tif->tif_name, "Using code not yet in table");
return 0;
@@ -800,7 +798,7 @@
static int LZWDecodeCompat(TIFF *tif, uint8_t *op0, tmsize_t occ0, uint16_t s)
{
static const char module[] = "LZWDecodeCompat";
- LZWCodecState *sp = DecoderState(tif);
+ LZWCodecState *sp = LZWDecoderState(tif);
uint8_t *op = (uint8_t *)op0;
tmsize_t occ = occ0;
uint8_t *tp;
@@ -1026,7 +1024,7 @@
static int LZWSetupEncode(TIFF *tif)
{
static const char module[] = "LZWSetupEncode";
- LZWCodecState *sp = EncoderState(tif);
+ LZWCodecState *sp = LZWEncoderState(tif);
assert(sp != NULL);
sp->enc_hashtab = (hash_t *)_TIFFmallocExt(tif, HSIZE * sizeof(hash_t));
@@ -1043,7 +1041,7 @@
*/
static int LZWPreEncode(TIFF *tif, uint16_t s)
{
- LZWCodecState *sp = EncoderState(tif);
+ LZWCodecState *sp = LZWEncoderState(tif);
(void)s;
assert(sp != NULL);
@@ -1114,7 +1112,7 @@
*/
static int LZWEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
{
- register LZWCodecState *sp = EncoderState(tif);
+ register LZWCodecState *sp = LZWEncoderState(tif);
register long fcode;
register hash_t *hp;
register int h, c;
@@ -1299,7 +1297,7 @@
*/
static int LZWPostEncode(TIFF *tif)
{
- register LZWCodecState *sp = EncoderState(tif);
+ register LZWCodecState *sp = LZWEncoderState(tif);
uint8_t *op = tif->tif_rawcp;
long nextbits = sp->lzw_nextbits;
WordType nextdata = sp->lzw_nextdata;
@@ -1381,11 +1379,11 @@
assert(tif->tif_data != 0);
- if (DecoderState(tif)->dec_codetab)
- _TIFFfreeExt(tif, DecoderState(tif)->dec_codetab);
+ if (LZWDecoderState(tif)->dec_codetab)
+ _TIFFfreeExt(tif, LZWDecoderState(tif)->dec_codetab);
- if (EncoderState(tif)->enc_hashtab)
- _TIFFfreeExt(tif, EncoderState(tif)->enc_hashtab);
+ if (LZWEncoderState(tif)->enc_hashtab)
+ _TIFFfreeExt(tif, LZWEncoderState(tif)->enc_hashtab);
_TIFFfreeExt(tif, tif->tif_data);
tif->tif_data = NULL;
@@ -1404,9 +1402,9 @@
tif->tif_data = (uint8_t *)_TIFFmallocExt(tif, sizeof(LZWCodecState));
if (tif->tif_data == NULL)
goto bad;
- DecoderState(tif)->dec_codetab = NULL;
- DecoderState(tif)->dec_decode = NULL;
- EncoderState(tif)->enc_hashtab = NULL;
+ LZWDecoderState(tif)->dec_codetab = NULL;
+ LZWDecoderState(tif)->dec_decode = NULL;
+ LZWEncoderState(tif)->enc_hashtab = NULL;
LZWState(tif)->rw_mode = tif->tif_mode;
/*
diff --git a/third_party/libtiff/tif_open.c b/third_party/libtiff/tif_open.c
index 23fcf81..59a07be 100644
--- a/third_party/libtiff/tif_open.c
+++ b/third_party/libtiff/tif_open.c
@@ -25,7 +25,13 @@
/*
* TIFF Library.
*/
+
+#ifdef TIFF_DO_NOT_USE_NON_EXT_ALLOC_FUNCTIONS
+#undef TIFF_DO_NOT_USE_NON_EXT_ALLOC_FUNCTIONS
+#endif
+
#include "tiffiop.h"
+#include <assert.h>
#include <limits.h>
/*
@@ -81,8 +87,9 @@
void TIFFOpenOptionsFree(TIFFOpenOptions *opts) { _TIFFfree(opts); }
/** Define a limit in bytes for a single memory allocation done by libtiff.
- * If max_single_mem_alloc is set to 0, no other limit that the underlying
- * _TIFFmalloc() will be applied, which is the default.
+ * If max_single_mem_alloc is set to 0, which is the default, no other limit
+ * that the underlying _TIFFmalloc() or
+ * TIFFOpenOptionsSetMaxCumulatedMemAlloc() will be applied.
*/
void TIFFOpenOptionsSetMaxSingleMemAlloc(TIFFOpenOptions *opts,
tmsize_t max_single_mem_alloc)
@@ -90,6 +97,18 @@
opts->max_single_mem_alloc = max_single_mem_alloc;
}
+/** Define a limit in bytes for the cumulated memory allocations done by libtiff
+ * on a given TIFF handle.
+ * If max_cumulated_mem_alloc is set to 0, which is the default, no other limit
+ * that the underlying _TIFFmalloc() or
+ * TIFFOpenOptionsSetMaxSingleMemAlloc() will be applied.
+ */
+void TIFFOpenOptionsSetMaxCumulatedMemAlloc(TIFFOpenOptions *opts,
+ tmsize_t max_cumulated_mem_alloc)
+{
+ opts->max_cumulated_mem_alloc = max_cumulated_mem_alloc;
+}
+
void TIFFOpenOptionsSetErrorHandlerExtR(TIFFOpenOptions *opts,
TIFFErrorHandlerExtR handler,
void *errorhandler_user_data)
@@ -117,6 +136,30 @@
(uint64_t)s, (uint64_t)tif->tif_max_single_mem_alloc);
}
+static void _TIFFEmitErrorAboveMaxCumulatedMemAlloc(TIFF *tif,
+ const char *pszFunction,
+ tmsize_t s)
+{
+ TIFFErrorExtR(tif, pszFunction,
+ "Cumulated memory allocation of %" PRIu64 " + %" PRIu64
+ " bytes is beyond the %" PRIu64
+ " cumulated byte limit defined in open options",
+ (uint64_t)tif->tif_cur_cumulated_mem_alloc, (uint64_t)s,
+ (uint64_t)tif->tif_max_cumulated_mem_alloc);
+}
+
+/* When allocating memory, we write at the beginning of the buffer it size.
+ * This allows us to keep track of the total memory allocated when we
+ * malloc/calloc/realloc and free. In theory we need just SIZEOF_SIZE_T bytes
+ * for that, but on x86_64, allocations of more than 16 bytes are aligned on
+ * 16 bytes. Hence using 2 * SIZEOF_SIZE_T.
+ * It is critical that _TIFFmallocExt/_TIFFcallocExt/_TIFFreallocExt are
+ * paired with _TIFFfreeExt.
+ * CMakeLists.txt defines TIFF_DO_NOT_USE_NON_EXT_ALLOC_FUNCTIONS, which in
+ * turn disables the definition of the non Ext version in tiffio.h
+ */
+#define LEADING_AREA_TO_STORE_ALLOC_SIZE (2 * SIZEOF_SIZE_T)
+
/** malloc() version that takes into account memory-specific open options */
void *_TIFFmallocExt(TIFF *tif, tmsize_t s)
{
@@ -126,16 +169,32 @@
_TIFFEmitErrorAboveMaxSingleMemAlloc(tif, "_TIFFmallocExt", s);
return NULL;
}
+ if (tif != NULL && tif->tif_max_cumulated_mem_alloc > 0)
+ {
+ if (s > tif->tif_max_cumulated_mem_alloc -
+ tif->tif_cur_cumulated_mem_alloc ||
+ s > TIFF_TMSIZE_T_MAX - LEADING_AREA_TO_STORE_ALLOC_SIZE)
+ {
+ _TIFFEmitErrorAboveMaxCumulatedMemAlloc(tif, "_TIFFmallocExt", s);
+ return NULL;
+ }
+ void *ptr = _TIFFmalloc(LEADING_AREA_TO_STORE_ALLOC_SIZE + s);
+ if (!ptr)
+ return NULL;
+ tif->tif_cur_cumulated_mem_alloc += s;
+ memcpy(ptr, &s, sizeof(s));
+ return (char *)ptr + LEADING_AREA_TO_STORE_ALLOC_SIZE;
+ }
return _TIFFmalloc(s);
}
/** calloc() version that takes into account memory-specific open options */
void *_TIFFcallocExt(TIFF *tif, tmsize_t nmemb, tmsize_t siz)
{
+ if (nmemb <= 0 || siz <= 0 || nmemb > TIFF_TMSIZE_T_MAX / siz)
+ return NULL;
if (tif != NULL && tif->tif_max_single_mem_alloc > 0)
{
- if (nmemb <= 0 || siz <= 0 || nmemb > TIFF_TMSIZE_T_MAX / siz)
- return NULL;
if (nmemb * siz > tif->tif_max_single_mem_alloc)
{
_TIFFEmitErrorAboveMaxSingleMemAlloc(tif, "_TIFFcallocExt",
@@ -143,6 +202,23 @@
return NULL;
}
}
+ if (tif != NULL && tif->tif_max_cumulated_mem_alloc > 0)
+ {
+ const tmsize_t s = nmemb * siz;
+ if (s > tif->tif_max_cumulated_mem_alloc -
+ tif->tif_cur_cumulated_mem_alloc ||
+ s > TIFF_TMSIZE_T_MAX - LEADING_AREA_TO_STORE_ALLOC_SIZE)
+ {
+ _TIFFEmitErrorAboveMaxCumulatedMemAlloc(tif, "_TIFFcallocExt", s);
+ return NULL;
+ }
+ void *ptr = _TIFFcalloc(LEADING_AREA_TO_STORE_ALLOC_SIZE + s, 1);
+ if (!ptr)
+ return NULL;
+ tif->tif_cur_cumulated_mem_alloc += s;
+ memcpy(ptr, &s, sizeof(s));
+ return (char *)ptr + LEADING_AREA_TO_STORE_ALLOC_SIZE;
+ }
return _TIFFcalloc(nmemb, siz);
}
@@ -155,13 +231,49 @@
_TIFFEmitErrorAboveMaxSingleMemAlloc(tif, "_TIFFreallocExt", s);
return NULL;
}
+ if (tif != NULL && tif->tif_max_cumulated_mem_alloc > 0)
+ {
+ void *oldPtr = p;
+ tmsize_t oldSize = 0;
+ if (p)
+ {
+ oldPtr = (char *)p - LEADING_AREA_TO_STORE_ALLOC_SIZE;
+ memcpy(&oldSize, oldPtr, sizeof(oldSize));
+ assert(oldSize <= tif->tif_cur_cumulated_mem_alloc);
+ }
+ if (s > oldSize &&
+ (s > tif->tif_max_cumulated_mem_alloc -
+ (tif->tif_cur_cumulated_mem_alloc - oldSize) ||
+ s > TIFF_TMSIZE_T_MAX - LEADING_AREA_TO_STORE_ALLOC_SIZE))
+ {
+ _TIFFEmitErrorAboveMaxCumulatedMemAlloc(tif, "_TIFFreallocExt",
+ s - oldSize);
+ return NULL;
+ }
+ void *newPtr =
+ _TIFFrealloc(oldPtr, LEADING_AREA_TO_STORE_ALLOC_SIZE + s);
+ if (newPtr == NULL)
+ return NULL;
+ tif->tif_cur_cumulated_mem_alloc -= oldSize;
+ tif->tif_cur_cumulated_mem_alloc += s;
+ memcpy(newPtr, &s, sizeof(s));
+ return (char *)newPtr + LEADING_AREA_TO_STORE_ALLOC_SIZE;
+ }
return _TIFFrealloc(p, s);
}
/** free() version that takes into account memory-specific open options */
void _TIFFfreeExt(TIFF *tif, void *p)
{
- (void)tif;
+ if (p != NULL && tif != NULL && tif->tif_max_cumulated_mem_alloc > 0)
+ {
+ void *oldPtr = (char *)p - LEADING_AREA_TO_STORE_ALLOC_SIZE;
+ tmsize_t oldSize;
+ memcpy(&oldSize, oldPtr, sizeof(oldSize));
+ assert(oldSize <= tif->tif_cur_cumulated_mem_alloc);
+ tif->tif_cur_cumulated_mem_alloc -= oldSize;
+ p = oldPtr;
+ }
_TIFFfree(p);
}
@@ -231,6 +343,17 @@
(uint64_t)opts->max_single_mem_alloc);
goto bad2;
}
+ if (opts && opts->max_cumulated_mem_alloc > 0 &&
+ size_to_alloc > opts->max_cumulated_mem_alloc)
+ {
+ _TIFFErrorEarly(opts, clientdata, module,
+ "%s: Memory allocation of %" PRIu64
+ " bytes is beyond the %" PRIu64
+ " cumulated byte limit defined in open options",
+ name, (uint64_t)size_to_alloc,
+ (uint64_t)opts->max_cumulated_mem_alloc);
+ goto bad2;
+ }
tif = (TIFF *)_TIFFmallocExt(NULL, size_to_alloc);
if (tif == NULL)
{
@@ -243,6 +366,7 @@
strcpy(tif->tif_name, name);
tif->tif_mode = m & ~(O_CREAT | O_TRUNC);
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 */
@@ -261,6 +385,7 @@
tif->tif_warnhandler = opts->warnhandler;
tif->tif_warnhandler_user_data = opts->warnhandler_user_data;
tif->tif_max_single_mem_alloc = opts->max_single_mem_alloc;
+ tif->tif_max_cumulated_mem_alloc = opts->max_cumulated_mem_alloc;
}
if (!readproc || !writeproc || !seekproc || !closeproc || !sizeproc)
@@ -423,9 +548,9 @@
TIFFErrorExtR(tif, name, "Cannot read TIFF header");
goto bad;
}
-/*
- * Setup header and write.
- */
+ /*
+ * Setup header and write.
+ */
#ifdef WORDS_BIGENDIAN
tif->tif_header.common.tiff_magic =
(tif->tif_flags & TIFF_SWAB) ? TIFF_LITTLEENDIAN : TIFF_BIGENDIAN;
@@ -433,13 +558,17 @@
tif->tif_header.common.tiff_magic =
(tif->tif_flags & TIFF_SWAB) ? TIFF_BIGENDIAN : TIFF_LITTLEENDIAN;
#endif
+ TIFFHeaderUnion tif_header_swapped;
if (!(tif->tif_flags & TIFF_BIGTIFF))
{
tif->tif_header.common.tiff_version = TIFF_VERSION_CLASSIC;
tif->tif_header.classic.tiff_diroff = 0;
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabShort(&tif->tif_header.common.tiff_version);
tif->tif_header_size = sizeof(TIFFHeaderClassic);
+ /* Swapped copy for writing */
+ _TIFFmemcpy(&tif_header_swapped, &tif->tif_header,
+ sizeof(TIFFHeaderUnion));
+ if (tif->tif_flags & TIFF_SWAB)
+ TIFFSwabShort(&tif_header_swapped.common.tiff_version);
}
else
{
@@ -447,12 +576,15 @@
tif->tif_header.big.tiff_offsetsize = 8;
tif->tif_header.big.tiff_unused = 0;
tif->tif_header.big.tiff_diroff = 0;
+ tif->tif_header_size = sizeof(TIFFHeaderBig);
+ /* Swapped copy for writing */
+ _TIFFmemcpy(&tif_header_swapped, &tif->tif_header,
+ sizeof(TIFFHeaderUnion));
if (tif->tif_flags & TIFF_SWAB)
{
- TIFFSwabShort(&tif->tif_header.common.tiff_version);
- TIFFSwabShort(&tif->tif_header.big.tiff_offsetsize);
+ TIFFSwabShort(&tif_header_swapped.common.tiff_version);
+ TIFFSwabShort(&tif_header_swapped.big.tiff_offsetsize);
}
- tif->tif_header_size = sizeof(TIFFHeaderBig);
}
/*
* The doc for "fopen" for some STD_C_LIBs says that if you
@@ -462,27 +594,13 @@
* on Solaris.
*/
TIFFSeekFile(tif, 0, SEEK_SET);
- if (!WriteOK(tif, &tif->tif_header, (tmsize_t)(tif->tif_header_size)))
+ if (!WriteOK(tif, &tif_header_swapped,
+ (tmsize_t)(tif->tif_header_size)))
{
TIFFErrorExtR(tif, name, "Error writing TIFF header");
goto bad;
}
/*
- * Setup the byte order handling.
- */
- if (tif->tif_header.common.tiff_magic == TIFF_BIGENDIAN)
- {
-#ifndef WORDS_BIGENDIAN
- tif->tif_flags |= TIFF_SWAB;
-#endif
- }
- else
- {
-#ifdef WORDS_BIGENDIAN
- tif->tif_flags |= TIFF_SWAB;
-#endif
- }
- /*
* Setup default directory.
*/
if (!TIFFDefaultDirectory(tif))
@@ -490,10 +608,14 @@
tif->tif_diroff = 0;
tif->tif_lastdiroff = 0;
tif->tif_setdirectory_force_absolute = FALSE;
+ /* tif_curdircount = 0 means 'empty file opened for writing, but no IFD
+ * written yet' */
+ tif->tif_curdircount = 0;
return (tif);
}
+
/*
- * Setup the byte order handling.
+ * Setup the byte order handling according to the opened file for reading.
*/
if (tif->tif_header.common.tiff_magic != TIFF_BIGENDIAN &&
tif->tif_header.common.tiff_magic != TIFF_LITTLEENDIAN
@@ -619,9 +741,17 @@
* example, it may be broken) and want to proceed to other
* directories. I this case we use the TIFF_HEADERONLY flag to open
* file and return immediately after reading TIFF header.
+ * However, the pointer to TIFFSetField() and TIFFGetField()
+ * (i.e. tif->tif_tagmethods.vsetfield and
+ * tif->tif_tagmethods.vgetfield) need to be initialized, which is
+ * done in TIFFDefaultDirectory().
*/
if (tif->tif_flags & TIFF_HEADERONLY)
+ {
+ if (!TIFFDefaultDirectory(tif))
+ goto bad;
return (tif);
+ }
/*
* Setup initial directory.
@@ -764,10 +894,7 @@
/*
* Return nonzero if given file is BigTIFF style.
*/
-int TIFFIsBigTIFF(TIFF *tif)
-{
- return (tif->tif_header.common.tiff_version == TIFF_VERSION_BIG);
-}
+int TIFFIsBigTIFF(TIFF *tif) { return ((tif->tif_flags & TIFF_BIGTIFF) != 0); }
/*
* Return pointer to file read method.
diff --git a/third_party/libtiff/tif_packbits.c b/third_party/libtiff/tif_packbits.c
index 62849f8..1ae50cb 100644
--- a/third_party/libtiff/tif_packbits.c
+++ b/third_party/libtiff/tif_packbits.c
@@ -300,6 +300,7 @@
tif->tif_rawcc = cc;
if (occ > 0)
{
+ memset(op, 0, (size_t)occ);
TIFFErrorExtR(tif, module, "Not enough data for scanline %" PRIu32,
tif->tif_row);
return (0);
diff --git a/third_party/libtiff/tif_pixarlog.c b/third_party/libtiff/tif_pixarlog.c
index 2e22b33..b4c4c9c 100644
--- a/third_party/libtiff/tif_pixarlog.c
+++ b/third_party/libtiff/tif_pixarlog.c
@@ -670,8 +670,8 @@
return 1;
}
-#define DecoderState(tif) ((PixarLogState *)(tif)->tif_data)
-#define EncoderState(tif) ((PixarLogState *)(tif)->tif_data)
+#define PixarLogDecoderState(tif) ((PixarLogState *)(tif)->tif_data)
+#define PixarLogEncoderState(tif) ((PixarLogState *)(tif)->tif_data)
static int PixarLogEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s);
static int PixarLogDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s);
@@ -740,7 +740,7 @@
{
static const char module[] = "PixarLogSetupDecode";
TIFFDirectory *td = &tif->tif_dir;
- PixarLogState *sp = DecoderState(tif);
+ PixarLogState *sp = PixarLogDecoderState(tif);
tmsize_t tbuf_size;
uint32_t strip_height;
@@ -813,7 +813,7 @@
static int PixarLogPreDecode(TIFF *tif, uint16_t s)
{
static const char module[] = "PixarLogPreDecode";
- PixarLogState *sp = DecoderState(tif);
+ PixarLogState *sp = PixarLogDecoderState(tif);
(void)s;
assert(sp != NULL);
@@ -835,7 +835,7 @@
{
static const char module[] = "PixarLogDecode";
TIFFDirectory *td = &tif->tif_dir;
- PixarLogState *sp = DecoderState(tif);
+ PixarLogState *sp = PixarLogDecoderState(tif);
tmsize_t i;
tmsize_t nsamples;
int llen;
@@ -859,6 +859,7 @@
TIFFErrorExtR(tif, module,
"%" PRIu16 " bit input not supported in PixarLog",
td->td_bitspersample);
+ memset(op, 0, (size_t)occ);
return 0;
}
@@ -879,12 +880,14 @@
if (sp->stream.avail_out != nsamples * sizeof(uint16_t))
{
TIFFErrorExtR(tif, module, "ZLib cannot deal with buffers this size");
+ memset(op, 0, (size_t)occ);
return (0);
}
/* Check that we will not fill more than what was allocated */
if (sp->tbuf_size < 0 || sp->stream.avail_out > (uInt) sp->tbuf_size)
{
TIFFErrorExtR(tif, module, "sp->stream.avail_out > sp->tbuf_size");
+ memset(op, 0, (size_t)occ);
return (0);
}
do
@@ -899,12 +902,14 @@
TIFFErrorExtR(
tif, module, "Decoding error at scanline %" PRIu32 ", %s",
tif->tif_row, sp->stream.msg ? sp->stream.msg : "(null)");
+ memset(op, 0, (size_t)occ);
return (0);
}
if (state != Z_OK)
{
TIFFErrorExtR(tif, module, "ZLib error: %s",
sp->stream.msg ? sp->stream.msg : "(null)");
+ memset(op, 0, (size_t)occ);
return (0);
}
} while (sp->stream.avail_out > 0);
@@ -916,6 +921,7 @@
"Not enough data at scanline %" PRIu32
" (short %u bytes)",
tif->tif_row, sp->stream.avail_out);
+ memset(op, 0, (size_t)occ);
return (0);
}
@@ -977,6 +983,7 @@
default:
TIFFErrorExtR(tif, module, "Unsupported bits/sample: %" PRIu16,
td->td_bitspersample);
+ memset(op, 0, (size_t)occ);
return (0);
}
}
@@ -988,7 +995,7 @@
{
static const char module[] = "PixarLogSetupEncode";
TIFFDirectory *td = &tif->tif_dir;
- PixarLogState *sp = EncoderState(tif);
+ PixarLogState *sp = PixarLogEncoderState(tif);
tmsize_t tbuf_size;
assert(sp != NULL);
@@ -1038,7 +1045,7 @@
static int PixarLogPreEncode(TIFF *tif, uint16_t s)
{
static const char module[] = "PixarLogPreEncode";
- PixarLogState *sp = EncoderState(tif);
+ PixarLogState *sp = PixarLogEncoderState(tif);
(void)s;
assert(sp != NULL);
@@ -1294,7 +1301,7 @@
{
static const char module[] = "PixarLogEncode";
TIFFDirectory *td = &tif->tif_dir;
- PixarLogState *sp = EncoderState(tif);
+ PixarLogState *sp = PixarLogEncoderState(tif);
tmsize_t i;
tmsize_t n;
int llen;
@@ -1401,7 +1408,7 @@
static int PixarLogPostEncode(TIFF *tif)
{
static const char module[] = "PixarLogPostEncode";
- PixarLogState *sp = EncoderState(tif);
+ PixarLogState *sp = PixarLogEncoderState(tif);
int state;
sp->stream.avail_in = 0;
diff --git a/third_party/libtiff/tif_read.c b/third_party/libtiff/tif_read.c
index 4fec839..7efab59 100644
--- a/third_party/libtiff/tif_read.c
+++ b/third_party/libtiff/tif_read.c
@@ -105,8 +105,8 @@
TIFFErrorExtR(tif, module, "Invalid buffer size");
return 0;
}
- new_rawdata =
- (uint8_t *)_TIFFrealloc(tif->tif_rawdata, tif->tif_rawdatasize);
+ new_rawdata = (uint8_t *)_TIFFreallocExt(tif, tif->tif_rawdata,
+ tif->tif_rawdatasize);
if (new_rawdata == 0)
{
TIFFErrorExtR(tif, module,
@@ -464,6 +464,10 @@
if (e)
(*tif->tif_postdecode)(tif, (uint8_t *)buf, tif->tif_scanlinesize);
}
+ else
+ {
+ memset(buf, 0, (size_t)tif->tif_scanlinesize);
+ }
return (e > 0 ? 1 : -1);
}
@@ -495,6 +499,11 @@
rowsperstrip = td->td_rowsperstrip;
if (rowsperstrip > td->td_imagelength)
rowsperstrip = td->td_imagelength;
+ if (rowsperstrip == 0)
+ {
+ TIFFErrorExtR(tif, module, "rowsperstrip is zero");
+ return ((tmsize_t)(-1));
+ }
stripsperplane =
TIFFhowmany_32_maxuint_compat(td->td_imagelength, rowsperstrip);
stripinplane = (strip % stripsperplane);
@@ -544,7 +553,10 @@
if ((size != (tmsize_t)(-1)) && (size < stripsize))
stripsize = size;
if (!TIFFFillStrip(tif, strip))
+ {
+ memset(buf, 0, (size_t)stripsize);
return ((tmsize_t)(-1));
+ }
if ((*tif->tif_decodestrip)(tif, buf, stripsize, plane) <= 0)
return ((tmsize_t)(-1));
(*tif->tif_postdecode)(tif, buf, stripsize);
@@ -962,9 +974,13 @@
size = tilesize;
else if (size > tilesize)
size = tilesize;
- if (TIFFFillTile(tif, tile) &&
- (*tif->tif_decodetile)(tif, (uint8_t *)buf, size,
- (uint16_t)(tile / td->td_stripsperimage)))
+ if (!TIFFFillTile(tif, tile))
+ {
+ memset(buf, 0, (size_t)size);
+ return ((tmsize_t)(-1));
+ }
+ else if ((*tif->tif_decodetile)(tif, (uint8_t *)buf, size,
+ (uint16_t)(tile / td->td_stripsperimage)))
{
(*tif->tif_postdecode)(tif, (uint8_t *)buf, size);
return (size);
@@ -1449,6 +1465,11 @@
tif->tif_flags |= TIFF_CODERSETUP;
}
tif->tif_curtile = tile;
+ if (td->td_tilewidth == 0)
+ {
+ TIFFErrorExtR(tif, module, "Zero tilewidth");
+ return 0;
+ }
howmany32 = TIFFhowmany_32(td->td_imagewidth, td->td_tilewidth);
if (howmany32 == 0)
{
@@ -1545,9 +1566,14 @@
if (TIFFIsTiled(tif))
{
- if (!TIFFStartTile(tif, strile) ||
- !(*tif->tif_decodetile)(tif, (uint8_t *)outbuf, outsize,
- (uint16_t)(strile / td->td_stripsperimage)))
+ if (!TIFFStartTile(tif, strile))
+ {
+ ret = 0;
+ memset(outbuf, 0, (size_t)outsize);
+ }
+ else if (!(*tif->tif_decodetile)(
+ tif, (uint8_t *)outbuf, outsize,
+ (uint16_t)(strile / td->td_stripsperimage)))
{
ret = 0;
}
@@ -1558,14 +1584,27 @@
uint32_t stripsperplane;
if (rowsperstrip > td->td_imagelength)
rowsperstrip = td->td_imagelength;
- stripsperplane =
- TIFFhowmany_32_maxuint_compat(td->td_imagelength, rowsperstrip);
- if (!TIFFStartStrip(tif, strile) ||
- !(*tif->tif_decodestrip)(tif, (uint8_t *)outbuf, outsize,
- (uint16_t)(strile / stripsperplane)))
+ if (rowsperstrip == 0)
{
+ TIFFErrorExtR(tif, module, "rowsperstrip is zero");
ret = 0;
}
+ else
+ {
+ stripsperplane =
+ TIFFhowmany_32_maxuint_compat(td->td_imagelength, rowsperstrip);
+ if (!TIFFStartStrip(tif, strile))
+ {
+ ret = 0;
+ memset(outbuf, 0, (size_t)outsize);
+ }
+ else if (!(*tif->tif_decodestrip)(
+ tif, (uint8_t *)outbuf, outsize,
+ (uint16_t)(strile / stripsperplane)))
+ {
+ ret = 0;
+ }
+ }
}
if (ret)
{
diff --git a/third_party/libtiff/tif_strip.c b/third_party/libtiff/tif_strip.c
index 820a254..4dbcf37 100644
--- a/third_party/libtiff/tif_strip.c
+++ b/third_party/libtiff/tif_strip.c
@@ -38,6 +38,11 @@
TIFFDirectory *td = &tif->tif_dir;
uint32_t strip;
+ if (td->td_rowsperstrip == 0)
+ {
+ TIFFErrorExtR(tif, module, "Cannot compute strip: RowsPerStrip is zero");
+ return 0;
+ }
strip = row / td->td_rowsperstrip;
if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
{
@@ -61,6 +66,11 @@
TIFFDirectory *td = &tif->tif_dir;
uint32_t nstrips;
+ if (td->td_rowsperstrip == 0)
+ {
+ TIFFWarningExtR(tif, "TIFFNumberOfStrips", "RowsPerStrip is zero");
+ return 0;
+ }
nstrips = (td->td_rowsperstrip == (uint32_t)-1
? 1
: TIFFhowmany_32(td->td_imagelength, td->td_rowsperstrip));
@@ -107,7 +117,8 @@
if ((ycbcrsubsampling[0] != 1 && ycbcrsubsampling[0] != 2 &&
ycbcrsubsampling[0] != 4) ||
(ycbcrsubsampling[1] != 1 && ycbcrsubsampling[1] != 2 &&
- ycbcrsubsampling[1] != 4))
+ ycbcrsubsampling[1] != 4) ||
+ (ycbcrsubsampling[0] == 0 || ycbcrsubsampling[1] == 0))
{
TIFFErrorExtR(tif, module, "Invalid YCbCr subsampling (%dx%d)",
ycbcrsubsampling[0], ycbcrsubsampling[1]);
@@ -267,7 +278,8 @@
if (((ycbcrsubsampling[0] != 1) && (ycbcrsubsampling[0] != 2) &&
(ycbcrsubsampling[0] != 4)) ||
((ycbcrsubsampling[1] != 1) && (ycbcrsubsampling[1] != 2) &&
- (ycbcrsubsampling[1] != 4)))
+ (ycbcrsubsampling[1] != 4)) ||
+ ((ycbcrsubsampling[0] == 0) || (ycbcrsubsampling[1] == 0)))
{
TIFFErrorExtR(tif, module, "Invalid YCbCr subsampling");
return 0;
@@ -287,7 +299,25 @@
else
{
uint64_t scanline_samples;
- scanline_samples = _TIFFMultiply64(tif, td->td_imagewidth,
+ uint32_t scanline_width = td->td_imagewidth;
+
+#if 0
+ // Tries to fix https://gitlab.com/libtiff/libtiff/-/merge_requests/564
+ // but causes regression when decoding legit files with tiffcp -c none
+ // Cf https://gitlab.com/libtiff/libtiff/-/merge_requests/644
+ if (td->td_photometric == PHOTOMETRIC_YCBCR)
+ {
+ uint16_t subsampling_hor;
+ uint16_t ignored;
+ TIFFGetFieldDefaulted(tif, TIFFTAG_YCBCRSUBSAMPLING,
+ &subsampling_hor, &ignored);
+ if (subsampling_hor > 1) // roundup width for YCbCr
+ scanline_width =
+ TIFFroundup_32(scanline_width, subsampling_hor);
+ }
+#endif
+
+ scanline_samples = _TIFFMultiply64(tif, scanline_width,
td->td_samplesperpixel, module);
scanline_size =
TIFFhowmany_64(_TIFFMultiply64(tif, scanline_samples,
diff --git a/third_party/libtiff/tif_thunder.c b/third_party/libtiff/tif_thunder.c
index 1f97362..bac0607 100644
--- a/third_party/libtiff/tif_thunder.c
+++ b/third_party/libtiff/tif_thunder.c
@@ -82,13 +82,14 @@
return (1);
}
-static int ThunderDecode(TIFF *tif, uint8_t *op, tmsize_t maxpixels)
+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 int lastpixel;
tmsize_t npixels;
+ uint8_t *op = op0;
bp = (unsigned char *)tif->tif_rawcp;
cc = tif->tif_rawcc;
@@ -107,6 +108,8 @@
* Replicate the last pixel n times,
* where n is the lower-order 6 bits.
*/
+ if (n == 0)
+ break;
if (npixels & 1)
{
op[0] |= lastpixel;
@@ -117,11 +120,10 @@
else
lastpixel |= lastpixel << 4;
npixels += n;
- if (npixels < maxpixels)
- {
- for (; n > 0; n -= 2)
- *op++ = (uint8_t)lastpixel;
- }
+ if (npixels > maxpixels)
+ break;
+ for (; n > 0; n -= 2)
+ *op++ = (uint8_t)lastpixel;
if (n == -1)
*--op &= 0xf0;
lastpixel &= 0xf;
@@ -154,6 +156,8 @@
tif->tif_rawcc = cc;
if (npixels != maxpixels)
{
+ uint8_t *op_end = op0 + (maxpixels + 1) / 2;
+ memset(op, 0, (size_t)(op_end - op));
TIFFErrorExtR(tif, module,
"%s data at scanline %lu (%" PRIu64 " != %" PRIu64 ")",
npixels < maxpixels ? "Not enough" : "Too much",
diff --git a/third_party/libtiff/tiffconf.h b/third_party/libtiff/tiffconf.h
index 289f175..beba8b8 100644
--- a/third_party/libtiff/tiffconf.h
+++ b/third_party/libtiff/tiffconf.h
@@ -175,11 +175,7 @@
/* Native cpu byte order: 1 if big-endian (Motorola) or 0 if little-endian
(Intel) */
-#if _FX_ENDIAN_ == _FX_BIG_ENDIAN_
-# define HOST_BIGENDIAN 1
-#else
-# define HOST_BIGENDIAN 0
-#endif
+#define HOST_BIGENDIAN 0
/* Support CCITT Group 3 & 4 algorithms */
#define CCITT_SUPPORT 1
@@ -213,7 +209,7 @@
/* #undef ZIP_SUPPORT */
/* Support strip chopping (whether or not to convert single-strip uncompressed
- images to mutiple strips of ~8Kb to reduce memory usage) */
+ images to multiple strips of ~8Kb to reduce memory usage) */
#define STRIPCHOP_DEFAULT TIFF_STRIPCHOP
/* Enable SubIFD tag (330) support */
diff --git a/third_party/libtiff/tiffio.h b/third_party/libtiff/tiffio.h
index 2046054..225f3c1 100644
--- a/third_party/libtiff/tiffio.h
+++ b/third_party/libtiff/tiffio.h
@@ -77,10 +77,6 @@
typedef tmsize_t tsize_t; /* i/o size in bytes */
typedef void *tdata_t; /* image data ref */
-#if !defined(__WIN32__) && (defined(_WIN32) || defined(WIN32))
-#define __WIN32__
-#endif
-
/*
* On windows you should define USE_WIN32_FILEIO if you are using tif_win32.c
* or AVOID_WIN32_FILEIO if you are using something else (like tif_unix.c).
@@ -88,7 +84,7 @@
* By default tif_unix.c is assumed.
*/
-#if defined(_WINDOWS) || defined(__WIN32__) || defined(_Windows)
+#if defined(_WIN32)
#if !defined(__CYGWIN) && !defined(AVOID_WIN32_FILEIO) && \
!defined(USE_WIN32_FILEIO)
#define AVOID_WIN32_FILEIO
@@ -98,11 +94,11 @@
#if defined(USE_WIN32_FILEIO)
#define VC_EXTRALEAN
#include <windows.h>
-#ifdef __WIN32__
+#ifdef _WIN32
DECLARE_HANDLE(thandle_t); /* Win32 file handle */
#else
typedef HFILE thandle_t; /* client data handle */
-#endif /* __WIN32__ */
+#endif /* _WIN32 */
#else
typedef void *thandle_t; /* client data handle */
#endif /* USE_WIN32_FILEIO */
@@ -311,14 +307,15 @@
/*
* Auxiliary functions.
*/
-
+#ifndef TIFF_DO_NOT_USE_NON_EXT_ALLOC_FUNCTIONS
extern void *_TIFFmalloc(tmsize_t s);
extern void *_TIFFcalloc(tmsize_t nmemb, tmsize_t siz);
extern void *_TIFFrealloc(void *p, tmsize_t s);
+ extern void _TIFFfree(void *p);
+#endif
extern void _TIFFmemset(void *p, int v, tmsize_t c);
extern void _TIFFmemcpy(void *d, const void *s, tmsize_t c);
extern int _TIFFmemcmp(const void *p1, const void *p2, tmsize_t c);
- extern void _TIFFfree(void *p);
/*
** Stuff, related to tag handling and creating custom tags.
@@ -508,6 +505,9 @@
TIFFOpenOptionsSetMaxSingleMemAlloc(TIFFOpenOptions *opts,
tmsize_t max_single_mem_alloc);
extern void
+ TIFFOpenOptionsSetMaxCumulatedMemAlloc(TIFFOpenOptions *opts,
+ tmsize_t max_cumulated_mem_alloc);
+ extern void
TIFFOpenOptionsSetErrorHandlerExtR(TIFFOpenOptions *opts,
TIFFErrorHandlerExtR handler,
void *errorhandler_user_data);
@@ -518,11 +518,11 @@
extern TIFF *TIFFOpen(const char *, const char *);
extern TIFF *TIFFOpenExt(const char *, const char *, TIFFOpenOptions *opts);
-#ifdef __WIN32__
+#ifdef _WIN32
extern TIFF *TIFFOpenW(const wchar_t *, const char *);
extern TIFF *TIFFOpenWExt(const wchar_t *, const char *,
TIFFOpenOptions *opts);
-#endif /* __WIN32__ */
+#endif /* _WIN32 */
extern TIFF *TIFFFdOpen(int, const char *, const char *);
extern TIFF *TIFFFdOpenExt(int, const char *, const char *,
TIFFOpenOptions *opts);
diff --git a/third_party/libtiff/tiffiop.h b/third_party/libtiff/tiffiop.h
index a7cc12b..d861fd5 100644
--- a/third_party/libtiff/tiffiop.h
+++ b/third_party/libtiff/tiffiop.h
@@ -102,6 +102,13 @@
};
typedef struct TIFFOffsetAndDirNumber TIFFOffsetAndDirNumber;
+typedef union
+{
+ TIFFHeaderCommon common;
+ TIFFHeaderClassic classic;
+ TIFFHeaderBig big;
+} TIFFHeaderUnion;
+
struct tiff
{
char *tif_name; /* name of open file */
@@ -153,20 +160,35 @@
TIFFDirectory tif_dir; /* internal rep of current directory */
TIFFDirectory
tif_customdir; /* custom IFDs are separated from the main ones */
- union
- {
- TIFFHeaderCommon common;
- TIFFHeaderClassic classic;
- TIFFHeaderBig big;
- } tif_header;
- uint16_t tif_header_size; /* file's header block and its length */
- uint32_t tif_row; /* current scanline */
- tdir_t tif_curdir; /* current directory (index) */
+ 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".
+ * tif_curdir is set to:
+ * a) TIFF_NON_EXISTENT_DIR_NUMBER if there is no IFD in the file
+ * or the state is unknown,
+ * or the last read (i.e. TIFFFetchDirectory()) failed,
+ * or a custom directory was written.
+ * b) IFD index of last IFD written in the file. In this case the
+ * active IFD is a new (empty) one and tif_diroff is zero.
+ * If writing fails, tif_curdir is not changed.
+ * c) IFD index of IFD read from file into memory (=active IFD),
+ * even if IFD is corrupt and TIFFReadDirectory() returns 0.
+ * Then tif_diroff contains the offset of the IFD in the file.
+ * d) IFD index 0, whenever a custom directory or an unchained SubIFD
+ * was read. */
+ tdir_t tif_curdir; /* current directory (index) */
+ /* tif_curdircount: number of directories (main-IFDs) in file:
+ * - 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() */
- uint64_t tif_dataoff; /* current offset for writing dir */
+ uint64_t tif_dataoff; /* current offset for writing dir (IFD) */
/* SubIFD support */
uint16_t tif_nsubifd; /* remaining subifds to write */
uint64_t tif_subifdoff; /* offset for patching SubIFD link */
@@ -233,7 +255,9 @@
void *tif_errorhandler_user_data;
TIFFErrorHandlerExtR tif_warnhandler;
void *tif_warnhandler_user_data;
- tmsize_t tif_max_single_mem_alloc; /* in bytes. 0 for unlimited */
+ tmsize_t tif_max_single_mem_alloc; /* in bytes. 0 for unlimited */
+ tmsize_t tif_max_cumulated_mem_alloc; /* in bytes. 0 for unlimited */
+ tmsize_t tif_cur_cumulated_mem_alloc; /* in bytes */
};
struct TIFFOpenOptions
@@ -243,6 +267,7 @@
TIFFErrorHandlerExtR warnhandler; /* may be NULL */
void *warnhandler_user_data; /* may be NULL */
tmsize_t max_single_mem_alloc; /* in bytes. 0 for unlimited */
+ tmsize_t max_cumulated_mem_alloc; /* in bytes. 0 for unlimited */
};
#define isPseudoTag(t) (t > 0xffff) /* is tag value normal or pseudo */
@@ -331,7 +356,7 @@
#define ftell(stream, offset, whence) ftello(stream, offset, whence)
#endif
#endif
-#if defined(__WIN32__) && !(defined(_MSC_VER) && _MSC_VER < 1400) && \
+#if defined(_WIN32) && \
!(defined(__MSVCRT_VERSION__) && __MSVCRT_VERSION__ < 0x800)
typedef unsigned int TIFFIOSize_t;
#define _TIFF_lseek_f(fildes, offset, whence) \
@@ -437,9 +462,6 @@
extern void *_TIFFCheckRealloc(TIFF *, void *, tmsize_t, tmsize_t,
const char *);
- extern double _TIFFUInt64ToDouble(uint64_t);
- extern float _TIFFUInt64ToFloat(uint64_t);
-
extern float _TIFFClampDoubleToFloat(double);
extern uint32_t _TIFFClampDoubleToUInt32(double);
diff --git a/third_party/libtiff/tiffvers.h b/third_party/libtiff/tiffvers.h
index 5741347..3ded6ac 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.6.0\nCopyright (c) 1988-1996 Sam Leffler\nCopyright (c) 1991-1996 Silicon Graphics, Inc."
+#define TIFFLIB_VERSION_STR "LIBTIFF, Version 4.7.0\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,11 +11,11 @@
* version checking should be done based on the
* string returned by TIFFGetVersion.
*/
-#define TIFFLIB_VERSION 20230908
+#define TIFFLIB_VERSION 20240911
/* The following defines have been added in 4.5.0 */
#define TIFFLIB_MAJOR_VERSION 4
-#define TIFFLIB_MINOR_VERSION 6
+#define TIFFLIB_MINOR_VERSION 7
#define TIFFLIB_MICRO_VERSION 0
/* Macro added in 4.5.0. Returns TRUE if the current libtiff version is