summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/libtiff/libtiff/tif_dirread.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/libtiff/libtiff/tif_dirread.c')
-rw-r--r--src/3rdparty/libtiff/libtiff/tif_dirread.c873
1 files changed, 757 insertions, 116 deletions
diff --git a/src/3rdparty/libtiff/libtiff/tif_dirread.c b/src/3rdparty/libtiff/libtiff/tif_dirread.c
index d84147a..32653f0 100644
--- a/src/3rdparty/libtiff/libtiff/tif_dirread.c
+++ b/src/3rdparty/libtiff/libtiff/tif_dirread.c
@@ -38,6 +38,7 @@
#include "tiffiop.h"
#include <float.h>
#include <stdlib.h>
+#include <string.h>
#define FAILED_FII ((uint32_t) -1)
@@ -61,9 +62,13 @@ enum TIFFReadDirEntryErr {
};
static enum TIFFReadDirEntryErr TIFFReadDirEntryByte(TIFF* tif, TIFFDirEntry* direntry, uint8_t* value);
+static enum TIFFReadDirEntryErr TIFFReadDirEntrySbyte(TIFF * tif, TIFFDirEntry * direntry, int8_t * value);
static enum TIFFReadDirEntryErr TIFFReadDirEntryShort(TIFF* tif, TIFFDirEntry* direntry, uint16_t* value);
+static enum TIFFReadDirEntryErr TIFFReadDirEntrySshort(TIFF * tif, TIFFDirEntry * direntry, int16_t * value);
static enum TIFFReadDirEntryErr TIFFReadDirEntryLong(TIFF* tif, TIFFDirEntry* direntry, uint32_t* value);
+static enum TIFFReadDirEntryErr TIFFReadDirEntrySlong(TIFF * tif, TIFFDirEntry * direntry, int32_t * value);
static enum TIFFReadDirEntryErr TIFFReadDirEntryLong8(TIFF* tif, TIFFDirEntry* direntry, uint64_t* value);
+static enum TIFFReadDirEntryErr TIFFReadDirEntrySlong8(TIFF * tif, TIFFDirEntry * direntry, int64_t * value);
static enum TIFFReadDirEntryErr TIFFReadDirEntryFloat(TIFF* tif, TIFFDirEntry* direntry, float* value);
static enum TIFFReadDirEntryErr TIFFReadDirEntryDouble(TIFF* tif, TIFFDirEntry* direntry, double* value);
static enum TIFFReadDirEntryErr TIFFReadDirEntryIfd8(TIFF* tif, TIFFDirEntry* direntry, uint64_t* value);
@@ -285,6 +290,98 @@ static enum TIFFReadDirEntryErr TIFFReadDirEntryByte(TIFF* tif, TIFFDirEntry* di
}
}
+static enum TIFFReadDirEntryErr TIFFReadDirEntrySbyte(TIFF *tif, TIFFDirEntry *direntry, int8_t *value)
+{
+ enum TIFFReadDirEntryErr err;
+ if (direntry->tdir_count != 1)
+ return(TIFFReadDirEntryErrCount);
+ switch (direntry->tdir_type)
+ {
+ case TIFF_BYTE:
+ case TIFF_UNDEFINED: /* Support to read TIFF_UNDEFINED with field_readcount==1 */
+ {
+ uint8_t m;
+ TIFFReadDirEntryCheckedByte(tif,direntry,&m);
+ err=TIFFReadDirEntryCheckRangeSbyteByte(m);
+ if (err!=TIFFReadDirEntryErrOk)
+ return(err);
+ *value=(int8_t)m;
+ return(TIFFReadDirEntryErrOk);
+ }
+ case TIFF_SBYTE:
+ {
+ TIFFReadDirEntryCheckedSbyte(tif, direntry, value);
+ return(TIFFReadDirEntryErrOk);
+ }
+ case TIFF_SHORT:
+ {
+ uint16_t m;
+ TIFFReadDirEntryCheckedShort(tif, direntry, &m);
+ err = TIFFReadDirEntryCheckRangeSbyteShort(m);
+ if (err != TIFFReadDirEntryErrOk)
+ return(err);
+ *value = (int8_t)m;
+ return(TIFFReadDirEntryErrOk);
+ }
+ case TIFF_SSHORT:
+ {
+ int16_t m;
+ TIFFReadDirEntryCheckedSshort(tif, direntry, &m);
+ err = TIFFReadDirEntryCheckRangeSbyteSshort(m);
+ if (err != TIFFReadDirEntryErrOk)
+ return(err);
+ *value = (int8_t)m;
+ return(TIFFReadDirEntryErrOk);
+ }
+ case TIFF_LONG:
+ {
+ uint32_t m;
+ TIFFReadDirEntryCheckedLong(tif, direntry, &m);
+ err = TIFFReadDirEntryCheckRangeSbyteLong(m);
+ if (err != TIFFReadDirEntryErrOk)
+ return(err);
+ *value = (int8_t)m;
+ return(TIFFReadDirEntryErrOk);
+ }
+ case TIFF_SLONG:
+ {
+ int32_t m;
+ TIFFReadDirEntryCheckedSlong(tif, direntry, &m);
+ err = TIFFReadDirEntryCheckRangeSbyteSlong(m);
+ if (err != TIFFReadDirEntryErrOk)
+ return(err);
+ *value = (int8_t)m;
+ return(TIFFReadDirEntryErrOk);
+ }
+ case TIFF_LONG8:
+ {
+ uint64_t m;
+ err = TIFFReadDirEntryCheckedLong8(tif, direntry, &m);
+ if (err != TIFFReadDirEntryErrOk)
+ return(err);
+ err = TIFFReadDirEntryCheckRangeSbyteLong8(m);
+ if (err != TIFFReadDirEntryErrOk)
+ return(err);
+ *value = (int8_t)m;
+ return(TIFFReadDirEntryErrOk);
+ }
+ case TIFF_SLONG8:
+ {
+ int64_t m;
+ err = TIFFReadDirEntryCheckedSlong8(tif, direntry, &m);
+ if (err != TIFFReadDirEntryErrOk)
+ return(err);
+ err = TIFFReadDirEntryCheckRangeSbyteSlong8(m);
+ if (err != TIFFReadDirEntryErrOk)
+ return(err);
+ *value = (int8_t)m;
+ return(TIFFReadDirEntryErrOk);
+ }
+ default:
+ return(TIFFReadDirEntryErrType);
+ }
+} /*-- TIFFReadDirEntrySbyte() --*/
+
static enum TIFFReadDirEntryErr TIFFReadDirEntryShort(TIFF* tif, TIFFDirEntry* direntry, uint16_t* value)
{
enum TIFFReadDirEntryErr err;
@@ -369,7 +466,91 @@ static enum TIFFReadDirEntryErr TIFFReadDirEntryShort(TIFF* tif, TIFFDirEntry* d
default:
return(TIFFReadDirEntryErrType);
}
-}
+} /*-- TIFFReadDirEntryShort() --*/
+
+static enum TIFFReadDirEntryErr TIFFReadDirEntrySshort(TIFF *tif, TIFFDirEntry *direntry, int16_t *value)
+{
+ enum TIFFReadDirEntryErr err;
+ if (direntry->tdir_count != 1)
+ return(TIFFReadDirEntryErrCount);
+ switch (direntry->tdir_type)
+ {
+ case TIFF_BYTE:
+ {
+ uint8_t m;
+ TIFFReadDirEntryCheckedByte(tif, direntry, &m);
+ *value = (int16_t)m;
+ return(TIFFReadDirEntryErrOk);
+ }
+ case TIFF_SBYTE:
+ {
+ int8_t m;
+ TIFFReadDirEntryCheckedSbyte(tif, direntry, &m);
+ *value = (int16_t)m;
+ return(TIFFReadDirEntryErrOk);
+ }
+ case TIFF_SHORT:
+ {
+ uint16_t m;
+ TIFFReadDirEntryCheckedShort(tif, direntry, &m);
+ err = TIFFReadDirEntryCheckRangeSshortShort(m);
+ if (err != TIFFReadDirEntryErrOk)
+ return(err);
+ *value = (uint16_t)m;
+ return(TIFFReadDirEntryErrOk);
+ }
+ case TIFF_SSHORT:
+ TIFFReadDirEntryCheckedSshort(tif, direntry, value);
+ return(TIFFReadDirEntryErrOk);
+ case TIFF_LONG:
+ {
+ uint32_t m;
+ TIFFReadDirEntryCheckedLong(tif, direntry, &m);
+ err = TIFFReadDirEntryCheckRangeSshortLong(m);
+ if (err != TIFFReadDirEntryErrOk)
+ return(err);
+ *value = (int16_t)m;
+ return(TIFFReadDirEntryErrOk);
+ }
+ case TIFF_SLONG:
+ {
+ int32_t m;
+ TIFFReadDirEntryCheckedSlong(tif, direntry, &m);
+ err = TIFFReadDirEntryCheckRangeSshortSlong(m);
+ if (err != TIFFReadDirEntryErrOk)
+ return(err);
+ *value = (int16_t)m;
+ return(TIFFReadDirEntryErrOk);
+ }
+ case TIFF_LONG8:
+ {
+ uint64_t m;
+ err = TIFFReadDirEntryCheckedLong8(tif, direntry, &m);
+ if (err != TIFFReadDirEntryErrOk)
+ return(err);
+ err = TIFFReadDirEntryCheckRangeSshortLong8(m);
+ if (err != TIFFReadDirEntryErrOk)
+ return(err);
+ *value = (int16_t)m;
+ return(TIFFReadDirEntryErrOk);
+ }
+ case TIFF_SLONG8:
+ {
+ int64_t m;
+ err = TIFFReadDirEntryCheckedSlong8(tif, direntry, &m);
+ if (err != TIFFReadDirEntryErrOk)
+ return(err);
+ err = TIFFReadDirEntryCheckRangeSshortSlong8(m);
+ if (err != TIFFReadDirEntryErrOk)
+ return(err);
+ *value = (int16_t)m;
+ return(TIFFReadDirEntryErrOk);
+ }
+ default:
+ return(TIFFReadDirEntryErrType);
+ }
+} /*-- TIFFReadDirEntrySshort() --*/
+
static enum TIFFReadDirEntryErr TIFFReadDirEntryLong(TIFF* tif, TIFFDirEntry* direntry, uint32_t* value)
{
@@ -452,7 +633,84 @@ static enum TIFFReadDirEntryErr TIFFReadDirEntryLong(TIFF* tif, TIFFDirEntry* di
default:
return(TIFFReadDirEntryErrType);
}
-}
+} /*-- TIFFReadDirEntryLong() --*/
+
+static enum TIFFReadDirEntryErr TIFFReadDirEntrySlong(TIFF *tif, TIFFDirEntry *direntry, int32_t *value)
+{
+ enum TIFFReadDirEntryErr err;
+ if (direntry->tdir_count != 1)
+ return(TIFFReadDirEntryErrCount);
+ switch (direntry->tdir_type)
+ {
+ case TIFF_BYTE:
+ {
+ uint8_t m;
+ TIFFReadDirEntryCheckedByte(tif, direntry, &m);
+ *value = (int32_t)m;
+ return(TIFFReadDirEntryErrOk);
+ }
+ case TIFF_SBYTE:
+ {
+ int8_t m;
+ TIFFReadDirEntryCheckedSbyte(tif, direntry, &m);
+ *value = (int32_t)m;
+ return(TIFFReadDirEntryErrOk);
+ }
+ case TIFF_SHORT:
+ {
+ uint16_t m;
+ TIFFReadDirEntryCheckedShort(tif, direntry, &m);
+ *value = (int32_t)m;
+ return(TIFFReadDirEntryErrOk);
+ }
+ case TIFF_SSHORT:
+ {
+ int16_t m;
+ TIFFReadDirEntryCheckedSshort(tif, direntry, &m);
+ *value = (int32_t)m;
+ return(TIFFReadDirEntryErrOk);
+ }
+ case TIFF_LONG:
+ {
+ uint32_t m;
+ TIFFReadDirEntryCheckedLong(tif, direntry, &m);
+ err = TIFFReadDirEntryCheckRangeSlongLong(m);
+ if (err != TIFFReadDirEntryErrOk)
+ return(err);
+ *value = (int32_t)m;
+ return(TIFFReadDirEntryErrOk);
+ }
+ case TIFF_SLONG:
+ TIFFReadDirEntryCheckedSlong(tif, direntry, value);
+ return(TIFFReadDirEntryErrOk);
+ case TIFF_LONG8:
+ {
+ uint64_t m;
+ err = TIFFReadDirEntryCheckedLong8(tif, direntry, &m);
+ if (err != TIFFReadDirEntryErrOk)
+ return(err);
+ err = TIFFReadDirEntryCheckRangeSlongLong8(m);
+ if (err != TIFFReadDirEntryErrOk)
+ return(err);
+ *value = (int32_t)m;
+ return(TIFFReadDirEntryErrOk);
+ }
+ case TIFF_SLONG8:
+ {
+ int64_t m;
+ err = TIFFReadDirEntryCheckedSlong8(tif, direntry, &m);
+ if (err != TIFFReadDirEntryErrOk)
+ return(err);
+ err = TIFFReadDirEntryCheckRangeSlongSlong8(m);
+ if (err != TIFFReadDirEntryErrOk)
+ return(err);
+ *value = (int32_t)m;
+ return(TIFFReadDirEntryErrOk);
+ }
+ default:
+ return(TIFFReadDirEntryErrType);
+ }
+} /*-- TIFFReadDirEntrySlong() --*/
static enum TIFFReadDirEntryErr TIFFReadDirEntryLong8(TIFF* tif, TIFFDirEntry* direntry, uint64_t* value)
{
@@ -530,7 +788,77 @@ static enum TIFFReadDirEntryErr TIFFReadDirEntryLong8(TIFF* tif, TIFFDirEntry* d
default:
return(TIFFReadDirEntryErrType);
}
-}
+} /*-- TIFFReadDirEntryLong8() --*/
+
+static enum TIFFReadDirEntryErr TIFFReadDirEntrySlong8(TIFF *tif, TIFFDirEntry *direntry, int64_t *value)
+{
+ enum TIFFReadDirEntryErr err;
+ if (direntry->tdir_count != 1)
+ return(TIFFReadDirEntryErrCount);
+ switch (direntry->tdir_type)
+ {
+ case TIFF_BYTE:
+ {
+ uint8_t m;
+ TIFFReadDirEntryCheckedByte(tif, direntry, &m);
+ *value = (int64_t)m;
+ return(TIFFReadDirEntryErrOk);
+ }
+ case TIFF_SBYTE:
+ {
+ int8_t m;
+ TIFFReadDirEntryCheckedSbyte(tif, direntry, &m);
+ *value = (int64_t)m;
+ return(TIFFReadDirEntryErrOk);
+ }
+ case TIFF_SHORT:
+ {
+ uint16_t m;
+ TIFFReadDirEntryCheckedShort(tif, direntry, &m);
+ *value = (int64_t)m;
+ return(TIFFReadDirEntryErrOk);
+ }
+ case TIFF_SSHORT:
+ {
+ int16_t m;
+ TIFFReadDirEntryCheckedSshort(tif, direntry, &m);
+ *value = (int64_t)m;
+ return(TIFFReadDirEntryErrOk);
+ }
+ case TIFF_LONG:
+ {
+ uint32_t m;
+ TIFFReadDirEntryCheckedLong(tif, direntry, &m);
+ *value = (int64_t)m;
+ return(TIFFReadDirEntryErrOk);
+ }
+ case TIFF_SLONG:
+ {
+ int32_t m;
+ TIFFReadDirEntryCheckedSlong(tif, direntry, &m);
+ *value = (int64_t)m;
+ return(TIFFReadDirEntryErrOk);
+ }
+ case TIFF_LONG8:
+ {
+ uint64_t m;
+ err = TIFFReadDirEntryCheckedLong8(tif, direntry, &m);
+ if (err != TIFFReadDirEntryErrOk)
+ return(err);
+ err = TIFFReadDirEntryCheckRangeSlong8Long8(m);
+ if (err != TIFFReadDirEntryErrOk)
+ return(err);
+ *value = (int64_t)m;
+ return(TIFFReadDirEntryErrOk);
+ }
+ case TIFF_SLONG8:
+ err = TIFFReadDirEntryCheckedSlong8(tif, direntry, value);
+ return(err);
+ default:
+ return(TIFFReadDirEntryErrType);
+ }
+} /*-- TIFFReadDirEntrySlong8() --*/
+
static enum TIFFReadDirEntryErr TIFFReadDirEntryFloat(TIFF* tif, TIFFDirEntry* direntry, float* value)
{
@@ -826,6 +1154,10 @@ static enum TIFFReadDirEntryErr TIFFReadDirEntryDataAndRealloc(
return TIFFReadDirEntryErrOk;
}
+/* Caution: if raising that value, make sure int32 / uint32 overflows can't occur
+ * elsewhere */
+#define MAX_SIZE_TAG_DATA 2147483647U
+
static enum TIFFReadDirEntryErr TIFFReadDirEntryArrayWithLimit(
TIFF* tif, TIFFDirEntry* direntry, uint32_t* count, uint32_t desttypesize,
void** value, uint64_t maxcount)
@@ -858,9 +1190,9 @@ static enum TIFFReadDirEntryErr TIFFReadDirEntryArrayWithLimit(
* in either the current data type or the dest data type. This also
* avoids problems with overflow of tmsize_t on 32bit systems.
*/
- if ((uint64_t)(2147483647 / typesize) < target_count64)
+ if ((uint64_t)(MAX_SIZE_TAG_DATA / typesize) < target_count64)
return(TIFFReadDirEntryErrSizesan);
- if ((uint64_t)(2147483647 / desttypesize) < target_count64)
+ if ((uint64_t)(MAX_SIZE_TAG_DATA / desttypesize) < target_count64)
return(TIFFReadDirEntryErrSizesan);
*count=(uint32_t)target_count64;
@@ -3794,50 +4126,7 @@ TIFFReadDirectory(TIFF* tif)
MissingRequired(tif,"ImageLength");
goto bad;
}
- /*
- * Setup appropriate structures (by strip or by tile)
- */
- if (!TIFFFieldSet(tif, FIELD_TILEDIMENSIONS)) {
- tif->tif_dir.td_nstrips = TIFFNumberOfStrips(tif);
- tif->tif_dir.td_tilewidth = tif->tif_dir.td_imagewidth;
- tif->tif_dir.td_tilelength = tif->tif_dir.td_rowsperstrip;
- tif->tif_dir.td_tiledepth = tif->tif_dir.td_imagedepth;
- tif->tif_flags &= ~TIFF_ISTILED;
- } else {
- tif->tif_dir.td_nstrips = TIFFNumberOfTiles(tif);
- tif->tif_flags |= TIFF_ISTILED;
- }
- if (!tif->tif_dir.td_nstrips) {
- TIFFErrorExt(tif->tif_clientdata, module,
- "Cannot handle zero number of %s",
- isTiled(tif) ? "tiles" : "strips");
- goto bad;
- }
- tif->tif_dir.td_stripsperimage = tif->tif_dir.td_nstrips;
- if (tif->tif_dir.td_planarconfig == PLANARCONFIG_SEPARATE)
- tif->tif_dir.td_stripsperimage /= tif->tif_dir.td_samplesperpixel;
- if (!TIFFFieldSet(tif, FIELD_STRIPOFFSETS)) {
-#ifdef OJPEG_SUPPORT
- if ((tif->tif_dir.td_compression==COMPRESSION_OJPEG) &&
- (isTiled(tif)==0) &&
- (tif->tif_dir.td_nstrips==1)) {
- /*
- * XXX: OJPEG hack.
- * If a) compression is OJPEG, b) it's not a tiled TIFF,
- * and c) the number of strips is 1,
- * then we tolerate the absence of stripoffsets tag,
- * because, presumably, all required data is in the
- * JpegInterchangeFormat stream.
- */
- TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS);
- } else
-#endif
- {
- MissingRequired(tif,
- isTiled(tif) ? "TileOffsets" : "StripOffsets");
- goto bad;
- }
- }
+
/*
* Second pass: extract other information.
*/
@@ -4042,41 +4331,6 @@ TIFFReadDirectory(TIFF* tif)
} /* -- if (!dp->tdir_ignore) */
} /* -- for-loop -- */
- if( tif->tif_mode == O_RDWR &&
- tif->tif_dir.td_stripoffset_entry.tdir_tag != 0 &&
- tif->tif_dir.td_stripoffset_entry.tdir_count == 0 &&
- tif->tif_dir.td_stripoffset_entry.tdir_type == 0 &&
- tif->tif_dir.td_stripoffset_entry.tdir_offset.toff_long8 == 0 &&
- tif->tif_dir.td_stripbytecount_entry.tdir_tag != 0 &&
- tif->tif_dir.td_stripbytecount_entry.tdir_count == 0 &&
- tif->tif_dir.td_stripbytecount_entry.tdir_type == 0 &&
- tif->tif_dir.td_stripbytecount_entry.tdir_offset.toff_long8 == 0 )
- {
- /* Directory typically created with TIFFDeferStrileArrayWriting() */
- TIFFSetupStrips(tif);
- }
- else if( !(tif->tif_flags&TIFF_DEFERSTRILELOAD) )
- {
- if( tif->tif_dir.td_stripoffset_entry.tdir_tag != 0 )
- {
- if (!TIFFFetchStripThing(tif,&(tif->tif_dir.td_stripoffset_entry),
- tif->tif_dir.td_nstrips,
- &tif->tif_dir.td_stripoffset_p))
- {
- goto bad;
- }
- }
- if( tif->tif_dir.td_stripbytecount_entry.tdir_tag != 0 )
- {
- if (!TIFFFetchStripThing(tif,&(tif->tif_dir.td_stripbytecount_entry),
- tif->tif_dir.td_nstrips,
- &tif->tif_dir.td_stripbytecount_p))
- {
- goto bad;
- }
- }
- }
-
/*
* OJPEG hack:
* - If a) compression is OJPEG, and b) photometric tag is missing,
@@ -4148,6 +4402,88 @@ TIFFReadDirectory(TIFF* tif)
}
/*
+ * Setup appropriate structures (by strip or by tile)
+ * We do that only after the above OJPEG hack which alters SamplesPerPixel
+ * and thus influences the number of strips in the separate planarconfig.
+ */
+ if (!TIFFFieldSet(tif, FIELD_TILEDIMENSIONS)) {
+ tif->tif_dir.td_nstrips = TIFFNumberOfStrips(tif);
+ tif->tif_dir.td_tilewidth = tif->tif_dir.td_imagewidth;
+ tif->tif_dir.td_tilelength = tif->tif_dir.td_rowsperstrip;
+ tif->tif_dir.td_tiledepth = tif->tif_dir.td_imagedepth;
+ tif->tif_flags &= ~TIFF_ISTILED;
+ } else {
+ tif->tif_dir.td_nstrips = TIFFNumberOfTiles(tif);
+ tif->tif_flags |= TIFF_ISTILED;
+ }
+ if (!tif->tif_dir.td_nstrips) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "Cannot handle zero number of %s",
+ isTiled(tif) ? "tiles" : "strips");
+ goto bad;
+ }
+ tif->tif_dir.td_stripsperimage = tif->tif_dir.td_nstrips;
+ if (tif->tif_dir.td_planarconfig == PLANARCONFIG_SEPARATE)
+ tif->tif_dir.td_stripsperimage /= tif->tif_dir.td_samplesperpixel;
+ if (!TIFFFieldSet(tif, FIELD_STRIPOFFSETS)) {
+#ifdef OJPEG_SUPPORT
+ if ((tif->tif_dir.td_compression==COMPRESSION_OJPEG) &&
+ (isTiled(tif)==0) &&
+ (tif->tif_dir.td_nstrips==1)) {
+ /*
+ * XXX: OJPEG hack.
+ * If a) compression is OJPEG, b) it's not a tiled TIFF,
+ * and c) the number of strips is 1,
+ * then we tolerate the absence of stripoffsets tag,
+ * because, presumably, all required data is in the
+ * JpegInterchangeFormat stream.
+ */
+ TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS);
+ } else
+#endif
+ {
+ MissingRequired(tif,
+ isTiled(tif) ? "TileOffsets" : "StripOffsets");
+ goto bad;
+ }
+ }
+
+ if( tif->tif_mode == O_RDWR &&
+ tif->tif_dir.td_stripoffset_entry.tdir_tag != 0 &&
+ tif->tif_dir.td_stripoffset_entry.tdir_count == 0 &&
+ tif->tif_dir.td_stripoffset_entry.tdir_type == 0 &&
+ tif->tif_dir.td_stripoffset_entry.tdir_offset.toff_long8 == 0 &&
+ tif->tif_dir.td_stripbytecount_entry.tdir_tag != 0 &&
+ tif->tif_dir.td_stripbytecount_entry.tdir_count == 0 &&
+ tif->tif_dir.td_stripbytecount_entry.tdir_type == 0 &&
+ tif->tif_dir.td_stripbytecount_entry.tdir_offset.toff_long8 == 0 )
+ {
+ /* Directory typically created with TIFFDeferStrileArrayWriting() */
+ TIFFSetupStrips(tif);
+ }
+ else if( !(tif->tif_flags&TIFF_DEFERSTRILELOAD) )
+ {
+ if( tif->tif_dir.td_stripoffset_entry.tdir_tag != 0 )
+ {
+ if (!TIFFFetchStripThing(tif,&(tif->tif_dir.td_stripoffset_entry),
+ tif->tif_dir.td_nstrips,
+ &tif->tif_dir.td_stripoffset_p))
+ {
+ goto bad;
+ }
+ }
+ if( tif->tif_dir.td_stripbytecount_entry.tdir_tag != 0 )
+ {
+ if (!TIFFFetchStripThing(tif,&(tif->tif_dir.td_stripbytecount_entry),
+ tif->tif_dir.td_nstrips,
+ &tif->tif_dir.td_stripbytecount_p))
+ {
+ goto bad;
+ }
+ }
+ }
+
+ /*
* Make sure all non-color channels are extrasamples.
* If it's not the case, define them as such.
*/
@@ -4173,7 +4509,8 @@ TIFFReadDirectory(TIFF* tif)
goto bad;
}
- memcpy(new_sampleinfo, tif->tif_dir.td_sampleinfo, old_extrasamples * sizeof(uint16_t));
+ if (old_extrasamples > 0)
+ memcpy(new_sampleinfo, tif->tif_dir.td_sampleinfo, old_extrasamples * sizeof(uint16_t));
_TIFFsetShortArray(&tif->tif_dir.td_sampleinfo, new_sampleinfo, tif->tif_dir.td_extrasamples);
_TIFFfree(new_sampleinfo);
}
@@ -4527,7 +4864,14 @@ TIFFReadCustomDirectory(TIFF* tif, toff_t diroff,
switch (dp->tdir_tag)
{
case EXIFTAG_SUBJECTDISTANCE:
- (void)TIFFFetchSubjectDistance(tif, dp);
+ if(!TIFFFieldIsAnonymous(fip)) {
+ /* should only be called on a Exif directory */
+ /* when exifFields[] is active */
+ (void)TIFFFetchSubjectDistance(tif, dp);
+ }
+ else {
+ (void)TIFFFetchNormalTag(tif, dp, TRUE);
+ }
break;
default:
(void)TIFFFetchNormalTag(tif, dp, TRUE);
@@ -5050,18 +5394,28 @@ TIFFFetchNormalTag(TIFF* tif, TIFFDirEntry* dp, int recover)
err=TIFFReadDirEntryByteArray(tif,dp,&data);
if (err==TIFFReadDirEntryErrOk)
{
- uint32_t mb = 0;
+ size_t mb = 0;
int n;
if (data != NULL)
{
- uint8_t* ma = data;
- while (mb<(uint32_t)dp->tdir_count)
- {
- if (*ma==0)
- break;
- ma++;
- mb++;
- }
+ if (dp->tdir_count > 0 && data[dp->tdir_count - 1] == 0)
+ {
+ /* optimization: if data is known to be 0 terminated, we can use strlen() */
+ mb = strlen((const char*)data);
+ }
+ else
+ {
+ /* general case. equivalent to non-portable */
+ /* mb = strnlen((const char*)data, (uint32_t)dp->tdir_count); */
+ uint8_t* ma = data;
+ while (mb<(uint32_t)dp->tdir_count)
+ {
+ if (*ma==0)
+ break;
+ ma++;
+ mb++;
+ }
+ }
}
if (mb+1<(uint32_t)dp->tdir_count)
TIFFWarningExt(tif->tif_clientdata,module,"ASCII value for tag \"%s\" contains null byte in value; value incorrectly truncated during reading due to implementation limitations",fip->field_name);
@@ -5069,17 +5423,19 @@ TIFFFetchNormalTag(TIFF* tif, TIFFDirEntry* dp, int recover)
{
uint8_t* o;
TIFFWarningExt(tif->tif_clientdata,module,"ASCII value for tag \"%s\" does not end in null byte",fip->field_name);
- if ((uint32_t)dp->tdir_count + 1 != dp->tdir_count + 1)
- o=NULL;
- else
- o=_TIFFmalloc((uint32_t)dp->tdir_count + 1);
+ /* TIFFReadDirEntryArrayWithLimit() ensures this can't be larger than MAX_SIZE_TAG_DATA */
+ assert((uint32_t)dp->tdir_count + 1 == dp->tdir_count + 1);
+ o=_TIFFmalloc((uint32_t)dp->tdir_count + 1);
if (o==NULL)
{
if (data!=NULL)
_TIFFfree(data);
return(0);
}
- _TIFFmemcpy(o,data,(uint32_t)dp->tdir_count);
+ if (dp->tdir_count > 0 )
+ {
+ _TIFFmemcpy(o,data,(uint32_t)dp->tdir_count);
+ }
o[(uint32_t)dp->tdir_count]=0;
if (data!=0)
_TIFFfree(data);
@@ -5106,6 +5462,19 @@ TIFFFetchNormalTag(TIFF* tif, TIFFDirEntry* dp, int recover)
}
}
break;
+ case TIFF_SETGET_SINT8:
+ {
+ int8_t data = 0;
+ assert(fip->field_readcount == 1);
+ assert(fip->field_passcount == 0);
+ err = TIFFReadDirEntrySbyte(tif, dp, &data);
+ if (err == TIFFReadDirEntryErrOk)
+ {
+ if (!TIFFSetField(tif, dp->tdir_tag, data))
+ return(0);
+ }
+ }
+ break;
case TIFF_SETGET_UINT16:
{
uint16_t data;
@@ -5119,6 +5488,19 @@ TIFFFetchNormalTag(TIFF* tif, TIFFDirEntry* dp, int recover)
}
}
break;
+ case TIFF_SETGET_SINT16:
+ {
+ int16_t data;
+ assert(fip->field_readcount==1);
+ assert(fip->field_passcount==0);
+ err=TIFFReadDirEntrySshort(tif,dp,&data);
+ if (err==TIFFReadDirEntryErrOk)
+ {
+ if (!TIFFSetField(tif,dp->tdir_tag,data))
+ return(0);
+ }
+ }
+ break;
case TIFF_SETGET_UINT32:
{
uint32_t data;
@@ -5132,6 +5514,19 @@ TIFFFetchNormalTag(TIFF* tif, TIFFDirEntry* dp, int recover)
}
}
break;
+ case TIFF_SETGET_SINT32:
+ {
+ int32_t data;
+ assert(fip->field_readcount==1);
+ assert(fip->field_passcount==0);
+ err=TIFFReadDirEntrySlong(tif,dp,&data);
+ if (err==TIFFReadDirEntryErrOk)
+ {
+ if (!TIFFSetField(tif,dp->tdir_tag,data))
+ return(0);
+ }
+ }
+ break;
case TIFF_SETGET_UINT64:
{
uint64_t data;
@@ -5145,6 +5540,19 @@ TIFFFetchNormalTag(TIFF* tif, TIFFDirEntry* dp, int recover)
}
}
break;
+ case TIFF_SETGET_SINT64:
+ {
+ int64_t data;
+ assert(fip->field_readcount==1);
+ assert(fip->field_passcount==0);
+ err=TIFFReadDirEntrySlong8(tif,dp,&data);
+ if (err==TIFFReadDirEntryErrOk)
+ {
+ if (!TIFFSetField(tif,dp->tdir_tag,data))
+ return(0);
+ }
+ }
+ break;
case TIFF_SETGET_FLOAT:
{
float data;
@@ -5199,7 +5607,7 @@ TIFFFetchNormalTag(TIFF* tif, TIFFDirEntry* dp, int recover)
if (err==TIFFReadDirEntryErrOk)
{
int m;
- assert(data); /* avoid CLang static Analyzer false positive */
+ assert(data); /* avoid CLang static Analyzer false positive */
m=TIFFSetField(tif,dp->tdir_tag,data[0],data[1]);
_TIFFfree(data);
if (!m)
@@ -5214,9 +5622,9 @@ TIFFFetchNormalTag(TIFF* tif, TIFFDirEntry* dp, int recover)
assert(fip->field_passcount==0);
if (dp->tdir_count!=(uint64_t)fip->field_readcount) {
TIFFWarningExt(tif->tif_clientdata,module,
- "incorrect count for field \"%s\", expected %d, got %"PRIu64,
- fip->field_name,(int) fip->field_readcount, dp->tdir_count);
- return 0;
+ "incorrect count for field \"%s\", expected %d, got %"PRIu64,
+ fip->field_name,(int) fip->field_readcount, dp->tdir_count);
+ return(0);
}
else
{
@@ -5233,13 +5641,43 @@ TIFFFetchNormalTag(TIFF* tif, TIFFDirEntry* dp, int recover)
}
}
break;
+ case TIFF_SETGET_C0_SINT8:
+ {
+ int8_t * data;
+ assert(fip->field_readcount>=1);
+ assert(fip->field_passcount==0);
+ if (dp->tdir_count!=(uint64_t)fip->field_readcount) {
+ TIFFWarningExt(tif->tif_clientdata, module,
+ "incorrect count for field \"%s\", expected %d, got %"PRIu64,
+ fip->field_name, (int)fip->field_readcount, dp->tdir_count);
+ return(0);
+ }
+ else
+ {
+ err=TIFFReadDirEntrySbyteArray(tif,dp,&data);
+ if (err==TIFFReadDirEntryErrOk)
+ {
+ int m;
+ m=TIFFSetField(tif,dp->tdir_tag,data);
+ if (data!=0)
+ _TIFFfree(data);
+ if (!m)
+ return(0);
+ }
+ }
+ }
+ break;
case TIFF_SETGET_C0_UINT16:
{
uint16_t* data;
assert(fip->field_readcount>=1);
assert(fip->field_passcount==0);
- if (dp->tdir_count!=(uint64_t)fip->field_readcount)
- /* corrupt file */;
+ if (dp->tdir_count != (uint64_t)fip->field_readcount) {
+ TIFFWarningExt(tif->tif_clientdata, module,
+ "incorrect count for field \"%s\", expected %d, got %"PRIu64,
+ fip->field_name, (int)fip->field_readcount, dp->tdir_count);
+ return(0);
+ }
else
{
err=TIFFReadDirEntryShortArray(tif,dp,&data);
@@ -5255,13 +5693,43 @@ TIFFFetchNormalTag(TIFF* tif, TIFFDirEntry* dp, int recover)
}
}
break;
+ case TIFF_SETGET_C0_SINT16:
+ {
+ int16_t* data;
+ assert(fip->field_readcount>=1);
+ assert(fip->field_passcount==0);
+ if (dp->tdir_count != (uint64_t)fip->field_readcount) {
+ TIFFWarningExt(tif->tif_clientdata, module,
+ "incorrect count for field \"%s\", expected %d, got %"PRIu64,
+ fip->field_name, (int)fip->field_readcount, dp->tdir_count);
+ return(0);
+ }
+ else
+ {
+ err=TIFFReadDirEntrySshortArray(tif,dp,&data);
+ if (err==TIFFReadDirEntryErrOk)
+ {
+ int m;
+ m=TIFFSetField(tif,dp->tdir_tag,data);
+ if (data!=0)
+ _TIFFfree(data);
+ if (!m)
+ return(0);
+ }
+ }
+ }
+ break;
case TIFF_SETGET_C0_UINT32:
{
uint32_t* data;
assert(fip->field_readcount>=1);
assert(fip->field_passcount==0);
- if (dp->tdir_count!=(uint64_t)fip->field_readcount)
- /* corrupt file */;
+ if (dp->tdir_count != (uint64_t)fip->field_readcount) {
+ TIFFWarningExt(tif->tif_clientdata, module,
+ "incorrect count for field \"%s\", expected %d, got %"PRIu64,
+ fip->field_name, (int)fip->field_readcount, dp->tdir_count);
+ return(0);
+ }
else
{
err=TIFFReadDirEntryLongArray(tif,dp,&data);
@@ -5277,13 +5745,93 @@ TIFFFetchNormalTag(TIFF* tif, TIFFDirEntry* dp, int recover)
}
}
break;
+ case TIFF_SETGET_C0_SINT32:
+ {
+ int32_t* data;
+ assert(fip->field_readcount>=1);
+ assert(fip->field_passcount==0);
+ if (dp->tdir_count != (uint64_t)fip->field_readcount) {
+ TIFFWarningExt(tif->tif_clientdata, module,
+ "incorrect count for field \"%s\", expected %d, got %"PRIu64,
+ fip->field_name, (int)fip->field_readcount, dp->tdir_count);
+ return(0);
+ }
+ else
+ {
+ err=TIFFReadDirEntrySlongArray(tif,dp,&data);
+ if (err==TIFFReadDirEntryErrOk)
+ {
+ int m;
+ m=TIFFSetField(tif,dp->tdir_tag,data);
+ if (data!=0)
+ _TIFFfree(data);
+ if (!m)
+ return(0);
+ }
+ }
+ }
+ break;
+ case TIFF_SETGET_C0_UINT64:
+ {
+ uint64_t *data;
+ assert(fip->field_readcount >= 1);
+ assert(fip->field_passcount == 0);
+ if (dp->tdir_count != (uint64_t)fip->field_readcount) {
+ TIFFWarningExt(tif->tif_clientdata, module,
+ "incorrect count for field \"%s\", expected %d, got %"PRIu64,
+ fip->field_name, (int)fip->field_readcount, dp->tdir_count);
+ return(0);
+ } else
+ {
+ err = TIFFReadDirEntryLong8Array(tif, dp, &data);
+ if (err == TIFFReadDirEntryErrOk)
+ {
+ int m;
+ m = TIFFSetField(tif, dp->tdir_tag, data);
+ if (data != 0)
+ _TIFFfree(data);
+ if (!m)
+ return(0);
+ }
+ }
+ }
+ break;
+ case TIFF_SETGET_C0_SINT64:
+ {
+ int64_t *data;
+ assert(fip->field_readcount >= 1);
+ assert(fip->field_passcount == 0);
+ if (dp->tdir_count != (uint64_t)fip->field_readcount) {
+ TIFFWarningExt(tif->tif_clientdata, module,
+ "incorrect count for field \"%s\", expected %d, got %"PRIu64,
+ fip->field_name, (int)fip->field_readcount, dp->tdir_count);
+ return(0);
+ } else
+ {
+ err = TIFFReadDirEntrySlong8Array(tif, dp, &data);
+ if (err == TIFFReadDirEntryErrOk)
+ {
+ int m;
+ m = TIFFSetField(tif, dp->tdir_tag, data);
+ if (data != 0)
+ _TIFFfree(data);
+ if (!m)
+ return(0);
+ }
+ }
+ }
+ break;
case TIFF_SETGET_C0_FLOAT:
{
float* data;
assert(fip->field_readcount>=1);
assert(fip->field_passcount==0);
- if (dp->tdir_count!=(uint64_t)fip->field_readcount)
- /* corrupt file */;
+ if (dp->tdir_count != (uint64_t)fip->field_readcount) {
+ TIFFWarningExt(tif->tif_clientdata, module,
+ "incorrect count for field \"%s\", expected %d, got %"PRIu64,
+ fip->field_name, (int)fip->field_readcount, dp->tdir_count);
+ return(0);
+ }
else
{
err=TIFFReadDirEntryFloatArray(tif,dp,&data);
@@ -5305,8 +5853,12 @@ TIFFFetchNormalTag(TIFF* tif, TIFFDirEntry* dp, int recover)
double* data;
assert(fip->field_readcount>=1);
assert(fip->field_passcount==0);
- if (dp->tdir_count!=(uint64_t)fip->field_readcount)
- /* corrupt file */;
+ if (dp->tdir_count != (uint64_t)fip->field_readcount) {
+ TIFFWarningExt(tif->tif_clientdata, module,
+ "incorrect count for field \"%s\", expected %d, got %"PRIu64,
+ fip->field_name, (int)fip->field_readcount, dp->tdir_count);
+ return(0);
+ }
else
{
err=TIFFReadDirEntryDoubleArray(tif,dp,&data);
@@ -5371,6 +5923,28 @@ TIFFFetchNormalTag(TIFF* tif, TIFFDirEntry* dp, int recover)
}
}
break;
+ case TIFF_SETGET_C16_SINT8:
+ {
+ int8_t* data;
+ assert(fip->field_readcount==TIFF_VARIABLE);
+ assert(fip->field_passcount==1);
+ if (dp->tdir_count>0xFFFF)
+ err=TIFFReadDirEntryErrCount;
+ else
+ {
+ err=TIFFReadDirEntrySbyteArray(tif,dp,&data);
+ if (err==TIFFReadDirEntryErrOk)
+ {
+ int m;
+ m=TIFFSetField(tif,dp->tdir_tag,(uint16_t)(dp->tdir_count),data);
+ if (data!=0)
+ _TIFFfree(data);
+ if (!m)
+ return(0);
+ }
+ }
+ }
+ break;
case TIFF_SETGET_C16_UINT16:
{
uint16_t* data;
@@ -5393,6 +5967,28 @@ TIFFFetchNormalTag(TIFF* tif, TIFFDirEntry* dp, int recover)
}
}
break;
+ case TIFF_SETGET_C16_SINT16:
+ {
+ int16_t* data;
+ assert(fip->field_readcount==TIFF_VARIABLE);
+ assert(fip->field_passcount==1);
+ if (dp->tdir_count>0xFFFF)
+ err=TIFFReadDirEntryErrCount;
+ else
+ {
+ err=TIFFReadDirEntrySshortArray(tif,dp,&data);
+ if (err==TIFFReadDirEntryErrOk)
+ {
+ int m;
+ m=TIFFSetField(tif,dp->tdir_tag,(uint16_t)(dp->tdir_count),data);
+ if (data!=0)
+ _TIFFfree(data);
+ if (!m)
+ return(0);
+ }
+ }
+ }
+ break;
case TIFF_SETGET_C16_UINT32:
{
uint32_t* data;
@@ -5415,6 +6011,28 @@ TIFFFetchNormalTag(TIFF* tif, TIFFDirEntry* dp, int recover)
}
}
break;
+ case TIFF_SETGET_C16_SINT32:
+ {
+ int32_t* data;
+ assert(fip->field_readcount==TIFF_VARIABLE);
+ assert(fip->field_passcount==1);
+ if (dp->tdir_count>0xFFFF)
+ err=TIFFReadDirEntryErrCount;
+ else
+ {
+ err=TIFFReadDirEntrySlongArray(tif,dp,&data);
+ if (err==TIFFReadDirEntryErrOk)
+ {
+ int m;
+ m=TIFFSetField(tif,dp->tdir_tag,(uint16_t)(dp->tdir_count),data);
+ if (data!=0)
+ _TIFFfree(data);
+ if (!m)
+ return(0);
+ }
+ }
+ }
+ break;
case TIFF_SETGET_C16_UINT64:
{
uint64_t* data;
@@ -5437,6 +6055,28 @@ TIFFFetchNormalTag(TIFF* tif, TIFFDirEntry* dp, int recover)
}
}
break;
+ case TIFF_SETGET_C16_SINT64:
+ {
+ int64_t* data;
+ assert(fip->field_readcount==TIFF_VARIABLE);
+ assert(fip->field_passcount==1);
+ if (dp->tdir_count>0xFFFF)
+ err=TIFFReadDirEntryErrCount;
+ else
+ {
+ err=TIFFReadDirEntrySlong8Array(tif,dp,&data);
+ if (err==TIFFReadDirEntryErrOk)
+ {
+ int m;
+ m=TIFFSetField(tif,dp->tdir_tag,(uint16_t)(dp->tdir_count),data);
+ if (data!=0)
+ _TIFFfree(data);
+ if (!m)
+ return(0);
+ }
+ }
+ }
+ break;
case TIFF_SETGET_C16_FLOAT:
{
float* data;
@@ -5514,8 +6154,8 @@ TIFFFetchNormalTag(TIFF* tif, TIFFDirEntry* dp, int recover)
int m;
if( data != 0 && dp->tdir_count > 0 && data[dp->tdir_count-1] != '\0' )
{
- TIFFWarningExt(tif->tif_clientdata,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';
+ TIFFWarningExt(tif->tif_clientdata,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';
}
m=TIFFSetField(tif, dp->tdir_tag, (uint32_t)(dp->tdir_count), data);
if (data!=0)
@@ -5765,8 +6405,9 @@ TIFFFetchStripThing(TIFF* tif, TIFFDirEntry* dir, uint32_t nstrips, uint64_t** l
_TIFFfree(data);
return(0);
}
- _TIFFmemcpy(resizeddata,data, (uint32_t)dir->tdir_count * sizeof(uint64_t));
- _TIFFmemset(resizeddata+(uint32_t)dir->tdir_count, 0, (nstrips - (uint32_t)dir->tdir_count) * sizeof(uint64_t));
+ if( dir->tdir_count )
+ _TIFFmemcpy(resizeddata,data, (uint32_t)dir->tdir_count * sizeof(uint64_t));
+ _TIFFmemset(resizeddata+(uint32_t)dir->tdir_count, 0, (nstrips - (uint32_t)dir->tdir_count) * sizeof(uint64_t));
_TIFFfree(data);
data=resizeddata;
}