From f536b00b649779200ff42a240199a1887dec377b Mon Sep 17 00:00:00 2001
From: Su Laus <[EMAIL REDACTED]>
Date: Sun, 8 May 2022 19:55:53 +0000
Subject: [PATCH] Reading of signed tags added (fixes #40)
---
libtiff/tif_dirread.c | 645 ++++++++++++++++++++++++++++++++++++++--
test/CMakeLists.txt | 5 +
test/Makefile.am | 4 +-
test/test_signed_tags.c | 349 ++++++++++++++++++++++
4 files changed, 985 insertions(+), 18 deletions(-)
create mode 100644 test/test_signed_tags.c
diff --git a/libtiff/tif_dirread.c b/libtiff/tif_dirread.c
index 32972d93..32653f04 100644
--- a/libtiff/tif_dirread.c
+++ b/libtiff/tif_dirread.c
@@ -62,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);
@@ -286,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;
@@ -370,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)
{
@@ -453,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)
{
@@ -531,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)
{
@@ -5135,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;
@@ -5148,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;
@@ -5161,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;
@@ -5174,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;
@@ -5228,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)
@@ -5243,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
{
@@ -5262,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);
@@ -5284,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);
@@ -5306,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);
@@ -5334,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);
@@ -5400,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;
@@ -5422,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;
@@ -5444,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;
@@ -5466,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;
@@ -5543,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)
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 093d2edc..47e21d40 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -100,6 +100,11 @@ set(noinst_HEADERS tifftest.h)
set(simple_tests)
+add_executable(test_signed_tags ../placeholder.h)
+target_sources(test_signed_tags PRIVATE test_signed_tags.c)
+target_link_libraries(test_signed_tags PRIVATE tiff port)
+list(APPEND simple_tests test_signed_tags)
+
add_executable(ascii_tag ../placeholder.h)
target_sources(ascii_tag PRIVATE ascii_tag.c)
target_link_libraries(ascii_tag PRIVATE tiff port)
diff --git a/test/Makefile.am b/test/Makefile.am
index 6c1bae62..b5823198 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -69,7 +69,7 @@ endif
check_PROGRAMS = \
ascii_tag long_tag short_tag strip_rw rewrite custom_dir custom_dir_EXIF_231 \
rational_precision2double defer_strile_loading defer_strile_writing test_directory \
- testtypes $(JPEG_DEPENDENT_CHECK_PROG)
+ testtypes test_signed_tags $(JPEG_DEPENDENT_CHECK_PROG)
# Test scripts to execute
TESTSCRIPTS = \
@@ -206,6 +206,8 @@ IMAGES_EXTRA_DIST = \
noinst_HEADERS = tifftest.h
+test_signed_tags_SOURCES = test_signed_tags.c
+test_signed_tags_LDADD = $(LIBTIFF)
ascii_tag_SOURCES = ascii_tag.c
ascii_tag_LDADD = $(LIBTIFF)
long_tag_SOURCES = long_tag.c check_tag.c
diff --git a/test/test_signed_tags.c b/test/test_signed_tags.c
new file mode 100644
index 00000000..582ba3aa
--- /dev/null
+++ b/test/test_signed_tags.c
@@ -0,0 +1,349 @@
+/*
+ * Copyright (c) 2022, Su Laus @Su_Laus
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+
+#include <stdio.h>
+
+#include "tif_config.h" /* necessary for linux compiler to get HAVE_UNISTD_H */
+#ifdef HAVE_UNISTD_H
+# include <unistd.h> /* for unlink() on linux */
+#endif
+
+#include <tiffio.h>
+
+#define FAULT_RETURN 1
+#define OK_RETURN 0
+#define GOTOFAILURE goto failure;
+
+#define N(a) (sizeof (a) / sizeof (a[0]))
+
+
+enum {
+ SINT8 = 65100,
+ SINT16,
+ SINT32,
+ SINT64,
+ C0_SINT8,
+ C0_SINT16,
+ C0_SINT32,
+ C0_SINT64,
+ C16_SINT8,
+ C16_SINT16,
+ C16_SINT32,
+ C16_SINT64,
+ C32_SINT8,
+ C32_SINT16,
+ C32_SINT32,
+ C32_SINT64,
+};
+
+static const TIFFFieldInfo tiff_field_info[] = {
+ { SINT8, 1, 1, TIFF_SBYTE, FIELD_CUSTOM, 0, 0, "SINT8" },
+ { SINT16, 1, 1, TIFF_SSHORT, FIELD_CUSTOM, 0, 0, "SINT16" },
+ { SINT32, 1, 1, TIFF_SLONG, FIELD_CUSTOM, 0, 0, "SINT32" },
+ { SINT64, 1, 1, TIFF_SLONG8, FIELD_CUSTOM, 0, 0, "SINT64" },
+ { C0_SINT8, 6, 6, TIFF_SBYTE, FIELD_CUSTOM, 0, 0, "C0_SINT8" },
+ { C0_SINT16, 6, 6, TIFF_SSHORT, FIELD_CUSTOM, 0, 0, "C0_SINT16" },
+ { C0_SINT32, 6, 6, TIFF_SLONG, FIELD_CUSTOM, 0, 0, "C0_SINT32" },
+ { C0_SINT64, 6, 6, TIFF_SLONG8, FIELD_CUSTOM, 0, 0, "C0_SINT64" },
+ { C16_SINT8, TIFF_VARIABLE, TIFF_VARIABLE, TIFF_SBYTE, FIELD_CUSTOM, 0, 1, "C16_SINT8" },
+ { C16_SINT16, TIFF_VARIABLE, TIFF_VARIABLE, TIFF_SSHORT, FIELD_CUSTOM, 0, 1, "C16_SINT16" },
+ { C16_SINT32, TIFF_VARIABLE, TIFF_VARIABLE, TIFF_SLONG, FIELD_CUSTOM, 0, 1, "C16_SINT32" },
+ { C16_SINT64, TIFF_VARIABLE, TIFF_VARIABLE, TIFF_SLONG8, FIELD_CUSTOM, 0, 1, "C16_SINT64" },
+ { C32_SINT8, TIFF_VARIABLE2, TIFF_VARIABLE2, TIFF_SBYTE, FIELD_CUSTOM, 0, 1, "C32_SINT8" },
+ { C32_SINT16, TIFF_VARIABLE2, TIFF_VARIABLE2, TIFF_SSHORT, FIELD_CUSTOM, 0, 1, "C32_SINT16" },
+ { C32_SINT32, TIFF_VARIABLE2, TIFF_VARIABLE2, TIFF_SLONG, FIELD_CUSTOM, 0, 1, "C32_SINT32" },
+ { C32_SINT64, TIFF_VARIABLE2, TIFF_VARIABLE2, TIFF_SLONG8, FIELD_CUSTOM, 0, 1, "C32_SINT64" },
+};
+
+static TIFFExtendProc parent = NULL;
+
+static void extender(TIFF *tif)
+{
+ TIFFMergeFieldInfo(tif, tiff_field_info, sizeof(tiff_field_info) / sizeof(tiff_field_info[0]));
+ if (parent) {
+ (*parent)(tif);
+ }
+}
+
+/*-- Global test fields --*/
+int8_t s8[] = { -8, -9, -10, -11, INT8_MAX, INT8_MIN };
+int16_t s16[] = { -16, -17, -18, -19, INT16_MAX, INT16_MIN };
+int32_t s32[] = { -32, -33, -34, -35, INT32_MAX, INT32_MIN };
+int64_t s64[] = { -64, -65, -66, -67, INT64_MAX, INT64_MIN };
+
+const uint32_t idxSingle = 0;
+
+
+static int writeTestTiff(const char *szFileName, int isBigTiff)
+{
+ int ret;
+ TIFF *tif;
+ int retcode = FAULT_RETURN;
+
+ if (isBigTiff) {
+ fprintf(stdout, "\n-- Writing signed values to BigTIFF...\n");
+ ret = unlink(szFileName);
+ tif = TIFFOpen(szFileName, "w8");
+ } else {
+ fprintf(stdout, "\n-- Writing signed values to ClassicTIFF...\n");
+ unlink(szFileName);
+ tif = TIFFOpen(szFileName, "w");
+ }
+ if (!tif) {
+ fprintf(stdout, "Can't create test TIFF file %s.\n", szFileName);
+ return (FAULT_RETURN);
+ }
+
+ ret = TIFFSetField(tif, SINT8, s8[idxSingle]);
+ if (ret != 1) { fprintf(stdout, "Error writing SINT8: ret=%d\n", ret); GOTOFAILURE; }
+ ret = TIFFSetField(tif, SINT16, s16[idxSingle]);
+ if (ret != 1) { fprintf(stdout, "Error writing SINT16: ret=%d\n", ret); GOTOFAILURE; }
+ ret = TIFFSetField(tif, SINT32, s32[idxSingle]);
+ if (ret != 1) { fprintf(stdout, "Error writing SINT32: ret=%d\n", ret); GOTOFAILURE; }
+
+ TIFFSetField(tif, C0_SINT8, &s8);
+ TIFFSetField(tif, C0_SINT16, &s16);
+ TIFFSetField(tif, C0_SINT32, &s32);
+
+ TIFFSetField(tif, C16_SINT8, 6, &s8);
+ TIFFSetField(tif, C16_SINT16, 6, &s16);
+ TIFFSetField(tif, C16_SINT32, 6, &s32);
+
+ TIFFSetField(tif, C16_SINT8, 6, &s8);
+ TIFFSetField(tif, C16_SINT16, 6, &s16);
+ TIFFSetField(tif, C16_SINT32, 6, &s32);
+
+ TIFFSetField(tif, C32_SINT8, 6, &s8);
+ TIFFSetField(tif, C32_SINT16, 6, &s16);
+ TIFFSetField(tif, C32_SINT32, 6, &s32);
+
+ if (isBigTiff) {
+ ret = TIFFSetField(tif, SINT64, s64[0]);
+ if (ret != 1) { fprintf(stdout, "Error writing SINT64: ret=%d\n", ret); GOTOFAILURE; }
+ ret = TIFFSetField(tif, C0_SINT64, &s64);
+ if (ret != 1) { fprintf(stdout, "Error writing C0_SINT64: ret=%d\n", ret); GOTOFAILURE; }
+ ret = TIFFSetField(tif, C16_SINT64, N(s64), &s64);
+ if (ret != 1) { fprintf(stdout, "Error writing C16_SINT64: ret=%d\n", ret); GOTOFAILURE;}
+ ret = TIFFSetField(tif, C32_SINT64, N(s64), &s64);
+ if (ret != 1) { fprintf(stdout, "Error writing C32_SINT64: ret=%d\n", ret); GOTOFAILURE;}
+ }
+
+ TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, 1);
+ TIFFSetField(tif, TIFFTAG_IMAGELENGTH, 1);
+ TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8);
+ TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
+ TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
+ TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1);
+ TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, 1);
+ ret = (int)TIFFWriteEncodedStrip(tif, 0, "\0", 1);
+ if (ret != 1) { fprintf(stdout, "Error TIFFWriteEncodedStrip: ret=%d\n", ret); GOTOFAILURE; }
+
+ retcode = OK_RETURN;
+failure:
+ TIFFClose(tif);
+ return(retcode);
+}
+
+static int readTestTiff(const char* szFileName, in
(Patch may be truncated, please check the link at the top of this post.)