libtiff: Merge branch 'fix_#8_FreeAnonTag' into 'master'

https://github.com/libsdl-org/libtiff/commit/9752dae8febab08879fc0159e7d387cff14eb3c3

From 97574866cbab026acb1bbd735201f790091b9400 Mon Sep 17 00:00:00 2001
From: Su_Laus <[EMAIL REDACTED]>
Date: Sun, 3 Apr 2022 22:04:58 +0200
Subject: [PATCH] extra flag for anonymous (unknown) tags (fixes #8)

---
 libtiff/libtiff.def   |  2 ++
 libtiff/tif_close.c   |  5 ++++-
 libtiff/tif_dir.h     |  4 ++--
 libtiff/tif_dirinfo.c | 17 ++++++++++++++---
 libtiff/tif_dirread.c |  2 +-
 libtiff/tif_print.c   |  4 ++--
 libtiff/tiffio.h      |  1 +
 7 files changed, 26 insertions(+), 9 deletions(-)

diff --git a/libtiff/libtiff.def b/libtiff/libtiff.def
index b2d03fe7..90850fd2 100644
--- a/libtiff/libtiff.def
+++ b/libtiff/libtiff.def
@@ -29,6 +29,7 @@ EXPORTS	TIFFAccessTagMethods
 	TIFFFieldName
 	TIFFFieldPassCount
 	TIFFFieldReadCount
+	TIFFFieldIsAnonymous
 	TIFFFieldTag
 	TIFFFieldWithName
 	TIFFFieldWithTag
@@ -177,3 +178,4 @@ EXPORTS	TIFFAccessTagMethods
 	_TIFFMultiply64
 	_TIFFGetExifFields
 	_TIFFGetGpsFields
+
diff --git a/libtiff/tif_close.c b/libtiff/tif_close.c
index 576e0843..d886964f 100644
--- a/libtiff/tif_close.c
+++ b/libtiff/tif_close.c
@@ -82,7 +82,10 @@ TIFFCleanup(TIFF* tif)
 			TIFFField *fld = tif->tif_fields[i];
 			if (fld->field_name != NULL) {
 				if (fld->field_bit == FIELD_CUSTOM &&
-					strncmp("Tag ", fld->field_name, 4) == 0) {
+					/* catuion: tif_fields[i] must not be the beginning of a fields-array.
+					 *          Otherwise the following tags are also freed with the first free().
+					 */
+					TIFFFieldIsAnonymous(fld)) {
 					_TIFFfree(fld->field_name);
 					_TIFFfree(fld);
 				}
diff --git a/libtiff/tif_dir.h b/libtiff/tif_dir.h
index 1782b35d..09065648 100644
--- a/libtiff/tif_dir.h
+++ b/libtiff/tif_dir.h
@@ -282,11 +282,11 @@ struct _TIFFFieldArray {
 };
 
 struct _TIFFField {
-	uint32_t field_tag;                       /* field's tag */
+	uint32_t field_tag;                     /* field's tag */
 	short field_readcount;                  /* read count/TIFF_VARIABLE/TIFF_SPP */
 	short field_writecount;                 /* write count/TIFF_VARIABLE */
 	TIFFDataType field_type;                /* type of associated data */
-	uint32_t reserved;                        /* reserved for future extension */
+	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 */
diff --git a/libtiff/tif_dirinfo.c b/libtiff/tif_dirinfo.c
index 0bd32c3f..2f9efc6d 100644
--- a/libtiff/tif_dirinfo.c
+++ b/libtiff/tif_dirinfo.c
@@ -422,8 +422,11 @@ _TIFFSetupFields(TIFF* tif, const TIFFFieldArray* fieldarray)
 			TIFFField *fld = tif->tif_fields[i];
 			if (fld->field_name != NULL) {
 				if (fld->field_bit == FIELD_CUSTOM &&
-					strncmp("Tag ", fld->field_name, 4) == 0) {
+					TIFFFieldIsAnonymous(fld)) {
 					_TIFFfree(fld->field_name);
+					/* catuion: tif_fields[i] must not be the beginning of a fields-array. 
+					 *          Otherwise the following tags are also freed with the first free().
+					 */
 					_TIFFfree(fld);
 				}
 			}
@@ -791,6 +794,12 @@ TIFFFieldWriteCount(const TIFFField* fip)
 	return fip->field_writecount;
 }
 
+int
+TIFFFieldIsAnonymous(const TIFFField *fip)
+{
+	return fip->field_anonymous;
+}
+
 const TIFFField*
 _TIFFFindOrRegisterField(TIFF *tif, uint32_t tag, TIFFDataType dt)
 
@@ -822,7 +831,7 @@ _TIFFCreateAnonField(TIFF *tif, uint32_t tag, TIFFDataType field_type)
 	fld->field_readcount = TIFF_VARIABLE2;
 	fld->field_writecount = TIFF_VARIABLE2;
 	fld->field_type = field_type;
-	fld->reserved = 0;
+	fld->field_anonymous = 1;    /* indicate that this is an anonymous / unknown tag */
 	switch (field_type)
 	{
 		case TIFF_BYTE:
@@ -895,6 +904,8 @@ _TIFFCreateAnonField(TIFF *tif, uint32_t tag, TIFFDataType field_type)
 	/* 
 	 * note that this name is a special sign to TIFFClose() and
 	 * _TIFFSetupFields() to free the field
+	 * Update:
+	 *   This special sign is replaced by fld->field_anonymous  flag.
 	 */
 	(void) snprintf(fld->field_name, 32, "Tag %d", (int) tag);
 
@@ -1105,7 +1116,7 @@ TIFFMergeFieldInfo(TIFF* tif, const TIFFFieldInfo info[], uint32_t n)
 		tp->field_readcount = info[i].field_readcount;
 		tp->field_writecount = info[i].field_writecount;
 		tp->field_type = info[i].field_type;
-		tp->reserved = 0;
+		tp->field_anonymous = 0;
 		tp->set_field_type =
 		     _TIFFSetGetType(info[i].field_type,
 				info[i].field_readcount,
diff --git a/libtiff/tif_dirread.c b/libtiff/tif_dirread.c
index 3ed6da1d..32972d93 100644
--- a/libtiff/tif_dirread.c
+++ b/libtiff/tif_dirread.c
@@ -4537,7 +4537,7 @@ TIFFReadCustomDirectory(TIFF* tif, toff_t diroff,
 				switch (dp->tdir_tag) 
 				{
 					case EXIFTAG_SUBJECTDISTANCE:
-                        if(fip->field_name != NULL && strncmp(fip->field_name, "Tag ", 4) != 0 ) {
+                        if(!TIFFFieldIsAnonymous(fip)) {
                             /* should only be called on a Exif directory */
                             /* when exifFields[] is active */
                             (void)TIFFFetchSubjectDistance(tif, dp);
diff --git a/libtiff/tif_print.c b/libtiff/tif_print.c
index f75c4381..57fa90c1 100644
--- a/libtiff/tif_print.c
+++ b/libtiff/tif_print.c
@@ -81,7 +81,7 @@ _TIFFPrintField(FILE* fd, const TIFFField *fip,
     /* Print a user-friendly name for tags of relatively common use, but */
     /* which aren't registered by libtiff itself. */
     const char* field_name = fip->field_name;
-    if( fip->field_name != NULL && strncmp(fip->field_name, "Tag ", 4) == 0 ) {
+    if( TIFFFieldIsAnonymous(fip) ) {
         for( size_t i = 0; i < NTAGS; ++i ) {
             if( fip->field_tag == tagnames[i].tag ) {
                 field_name = tagnames[i].name;
@@ -149,7 +149,7 @@ _TIFFPrettyPrintField(TIFF* tif, const TIFFField *fip, FILE* fd, uint32_t tag,
         (void) tif;
 
 	/* do not try to pretty print auto-defined fields */
-	if (fip->field_name != NULL && strncmp(fip->field_name,"Tag ", 4) == 0) {
+	if ( TIFFFieldIsAnonymous(fip) ) {
 		return 0;
 	}
         
diff --git a/libtiff/tiffio.h b/libtiff/tiffio.h
index c6a192c5..2ad58503 100644
--- a/libtiff/tiffio.h
+++ b/libtiff/tiffio.h
@@ -328,6 +328,7 @@ extern TIFFDataType TIFFFieldDataType(const TIFFField*);
 extern int TIFFFieldPassCount(const TIFFField*);
 extern int TIFFFieldReadCount(const TIFFField*);
 extern int TIFFFieldWriteCount(const TIFFField*);
+extern int TIFFFieldIsAnonymous(const TIFFField *);
 
 typedef int (*TIFFVSetMethod)(TIFF*, uint32_t, va_list);
 typedef int (*TIFFVGetMethod)(TIFF*, uint32_t, va_list);