File tiff-4.7.0-bsc1243503.patch of Package tiff
From 634bce6706702b248730fe007f844e761b362618 Mon Sep 17 00:00:00 2001
From: Su Laus <sulau@freenet.de>
Date: Sat, 26 Oct 2024 22:56:26 +0000
Subject: [PATCH] Issue #532: Updating TIFFMergeFieldInfo() with
read_count=write_count=0 for FIELD_IGNORE.
Updating TIFFMergeFieldInfo() with read_count=write_count=0 for FIELD_IGNORE.
Improving handling when field_name = NULL.
Closes #532
There was a regression in v4.7.0 related to re-opened issue https://gitlab.com/libtiff/libtiff/-/issues/532#note_2134433038 and following discussion.
---
libtiff/tif_dirinfo.c | 38 ++++++---
test/test_signed_tags.c | 183 ++++++++++++++++++++++++++++++++++++++--
2 files changed, 201 insertions(+), 20 deletions(-)
diff --git a/libtiff/tif_dirinfo.c b/libtiff/tif_dirinfo.c
index 432e6e1e4..fc065d197 100644
--- a/libtiff/tif_dirinfo.c
+++ b/libtiff/tif_dirinfo.c
@@ -1198,15 +1198,27 @@ int TIFFMergeFieldInfo(TIFF *tif, const TIFFFieldInfo info[], uint32_t n)
{
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)
+ info[i].field_writecount < TIFF_VARIABLE2)
{
/* 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.");
+ TIFFErrorExtR(
+ tif, module,
+ "The value of field_readcount %d and field_writecount %d "
+ "must be greater than or equal to -3.",
+ info[i].field_readcount, info[i].field_writecount);
+ return -1;
+ }
+ if ((info[i].field_readcount == 0 || info[i].field_writecount == 0) &&
+ info[i].field_bit != FIELD_IGNORE)
+ {
+ /* The fields (field_readcount) and (field_writecount) may only
+ be zero for pseudo_tags or ignored tags. */
+ TIFFErrorExtR(
+ tif, module,
+ "The value of field_readcount %d and field_writecount %d "
+ "may only be zero for field_bit = 0 (i.e. ignored tags).",
+ info[i].field_readcount, info[i].field_writecount);
return -1;
}
tp->field_readcount = info[i].field_readcount;
@@ -1222,14 +1234,18 @@ int TIFFMergeFieldInfo(TIFF *tif, const TIFFFieldInfo info[], uint32_t n)
tp->field_bit = info[i].field_bit;
tp->field_oktochange = info[i].field_oktochange;
tp->field_passcount = info[i].field_passcount;
+ /* Define an empty static string to be passed as field_name where a NULL
+ * pointer is passed in. Otherwise, this will lead to buffer overflow
+ * furtheron. */
if (info[i].field_name == NULL)
{
- TIFFErrorExtR(tif, module,
- "Field_name of %d.th allocation tag %d is NULL", i,
- info[i].field_tag);
- return -1;
+ static const char *string_static_empty = "";
+ tp->field_name = (char *)string_static_empty;
+ }
+ else
+ {
+ tp->field_name = info[i].field_name;
}
- tp->field_name = info[i].field_name;
tp->field_subfields = NULL;
tp++;
}
diff --git a/test/test_signed_tags.c b/test/test_signed_tags.c
index df0e2a48a..0eb886568 100644
--- a/test/test_signed_tags.c
+++ b/test/test_signed_tags.c
@@ -5,15 +5,15 @@
* 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
+ * the author 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.
+ * permission of the author.
*
* 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
+ * IN NO EVENT SHALL THE AUTHOR 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
@@ -21,7 +21,21 @@
* OF THIS SOFTWARE.
*/
+/* =========== Purpose ===============================================
+ * Tests the following points:
+ * - Handling of signed tags
+ * - Definition of additional, user-defined tags
+ * - Specification of field name strings or with field_name = NULL
+ * - Prevent reading anonymous tags by specifying them as FIELD_IGNORE
+ * (see https://gitlab.com/libtiff/libtiff/-/issues/532)
+ * - Immediate clearing of the memory for the definition of the additional tags
+ * (allocate memory for TIFFFieldInfo structure and free that memory
+ * immediately after calling TIFFMergeFieldInfo().
+ */
+
+#include <memory.h> /* necessary for linux compiler (memset) */
#include <stdio.h>
+#include <stdlib.h> /* necessary for linux compiler */
#include "tif_config.h" /* necessary for linux compiler to get HAVE_UNISTD_H */
#ifdef HAVE_UNISTD_H
@@ -36,6 +50,8 @@
#define N(a) (sizeof(a) / sizeof(a[0]))
+#define FIELD_IGNORE 0 /* same as FIELD_PSEUDO */
+
enum
{
SINT8 = 65100,
@@ -54,6 +70,7 @@ enum
C32_SINT16,
C32_SINT32,
C32_SINT64,
+ C32_SINT64NULL,
};
static const TIFFFieldInfo tiff_field_info[] = {
@@ -81,17 +98,34 @@ static const TIFFFieldInfo tiff_field_info[] = {
"C32_SINT32"},
{C32_SINT64, TIFF_VARIABLE2, TIFF_VARIABLE2, TIFF_SLONG8, FIELD_CUSTOM, 0,
1, "C32_SINT64"},
+ /* Test field_name=NULL in static const array, which is now possible because
+ * handled within TIFFMergeFieldInfo(). */
+ {C32_SINT64NULL, TIFF_VARIABLE2, TIFF_VARIABLE2, TIFF_SLONG8, FIELD_CUSTOM,
+ 0, 1, NULL},
};
+/* Global parameter for the field array to be passed to extender, which can be
+ * changed during runtime. */
+static TIFFFieldInfo *p_tiff_field_info = (TIFFFieldInfo *)tiff_field_info;
+static uint32_t N_tiff_field_info =
+ sizeof(tiff_field_info) / sizeof(tiff_field_info[0]);
+
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)
+ if (p_tiff_field_info != NULL)
{
- (*parent)(tif);
+ TIFFMergeFieldInfo(tif, p_tiff_field_info, N_tiff_field_info);
+ if (parent)
+ {
+ (*parent)(tif);
+ }
+ }
+ else
+ {
+ TIFFErrorExtR(tif, "field_info_extender",
+ "Pointer to tiff_field_info array is NULL.");
}
}
@@ -187,6 +221,12 @@ static int writeTestTiff(const char *szFileName, int isBigTiff)
fprintf(stdout, "Error writing C32_SINT64: ret=%d\n", ret);
GOTOFAILURE;
}
+ ret = TIFFSetField(tif, C32_SINT64NULL, N(s64), &s64);
+ if (ret != 1)
+ {
+ fprintf(stdout, "Error writing C32_SINT64NULL: ret=%d\n", ret);
+ GOTOFAILURE;
+ }
}
TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, 1);
@@ -506,20 +546,145 @@ failure:
TIFFClose(tif);
return (retcode);
}
+/*-- readTestTiff() --*/
+
+static int readTestTiff_ignore_some_tags(const char *szFileName)
+{
+ int ret;
+ int8_t s8l;
+ int16_t s16l;
+ int32_t s32l;
+ int retcode = FAULT_RETURN;
+
+ /* There is a use case, where LibTIFF shall be prevented from reading
+ * unknown tags that are present in the file as anonymous tags. This can be
+ * achieved by defining these tags with ".field_bit = FIELD_IGNORE". */
+
+ /* Copy const array to be manipulated and freed just after TIFFMergeFields()
+ * within the "extender()" called by TIFFOpen(). */
+ TIFFFieldInfo *tiff_field_info2;
+ tiff_field_info2 = (TIFFFieldInfo *)malloc(sizeof(tiff_field_info));
+ if (tiff_field_info2 == (TIFFFieldInfo *)NULL)
+ {
+ fprintf(stdout,
+ "Can't allocate memoy for tiff_field_info2 structure.\n");
+ return (FAULT_RETURN);
+ }
+ memcpy(tiff_field_info2, tiff_field_info, sizeof(tiff_field_info));
+ /* Switch field array for extender callback. */
+ p_tiff_field_info = tiff_field_info2;
+
+ /*-- Adapt tiff_field_info array for ignoring unknown tags to LibTIFF, which
+ * have been written to file before. --*/
+ /* a.) Just set field_bit to FIELD_IGNORE = 0 */
+ tiff_field_info2[2].field_bit = FIELD_IGNORE;
+ /* b.) Usecase with all field array infos zero but the tag value. */
+ ttag_t tag = tiff_field_info2[4].field_tag;
+ memset(&tiff_field_info2[4], 0, sizeof(tiff_field_info2[4]));
+ tiff_field_info2[4].field_tag = tag;
+
+ fprintf(stdout, "\n-- Reading file with unknown tags to be ignored ...\n");
+ TIFF *tif = TIFFOpen(szFileName, "r");
+
+ /* tiff_field_info2 should not be needed anymore, as long as the still
+ * active extender() is not called again. Therefore, the extender callback
+ * should be disabled by resetting it to the saved one. */
+ free(tiff_field_info2);
+ tiff_field_info2 = NULL;
+ TIFFSetTagExtender(parent);
+
+ if (!tif)
+ {
+ fprintf(stdout, "Can't open test TIFF file %s.\n", szFileName);
+ return (FAULT_RETURN);
+ }
+
+ /* Read the first two known tags for testing */
+ ret = TIFFGetField(tif, SINT8, &s8l);
+ if (ret != 1)
+ {
+ fprintf(stdout, "Error reading SINT8: ret=%d\n", ret);
+ GOTOFAILURE
+ }
+ else
+ {
+ if (s8l != s8[idxSingle])
+ {
+ fprintf(stdout,
+ "Read value of SINT8 %d differs from set value %d\n", s8l,
+ s8[idxSingle]);
+ GOTOFAILURE
+ }
+ }
+ ret = TIFFGetField(tif, SINT16, &s16l);
+ if (ret != 1)
+ {
+ fprintf(stdout, "Error reading SINT16: ret=%d\n", ret);
+ GOTOFAILURE
+ }
+ else
+ {
+ if (s16l != s16[idxSingle])
+ {
+ fprintf(stdout,
+ "Read value of SINT16 %d differs from set value %d\n",
+ s16l, s16[idxSingle]);
+ GOTOFAILURE
+ }
+ }
+
+ /* The two ignored tags shall not be present. */
+ ret = TIFFGetField(tif, tiff_field_info[2].field_tag, &s32l);
+ if (ret != 0)
+ {
+ fprintf(stdout,
+ "Error: Tag %d, set to be ignored, has been read from file.\n",
+ tiff_field_info[2].field_tag);
+ GOTOFAILURE
+ }
+
+ ret = TIFFGetField(tif, tiff_field_info[4].field_tag, &s32l);
+ if (ret != 0)
+ {
+ fprintf(stdout,
+ "Error: Tag %d, set to be ignored, has been read from file.\n",
+ tiff_field_info[4].field_tag);
+ GOTOFAILURE
+ }
+
+ retcode = OK_RETURN;
+failure:
+
+ fprintf(stdout,
+ "-- End of test for ignored unknown tags. Closing TIFF file. --\n");
+ TIFFClose(tif);
+ return (retcode);
+}
+/*-- readTestTiff_ignore_some_tags() --*/
int main(void)
{
+ /*-- Signed tags test --*/
parent = TIFFSetTagExtender(&extender);
if (writeTestTiff("temp.tif", 0) != OK_RETURN)
return (-1);
if (readTestTiff("temp.tif", 0) != OK_RETURN)
return (-1);
- unlink("temp.tif");
+
if (writeTestTiff("tempBig.tif", 1) != OK_RETURN)
return (-1);
if (readTestTiff("tempBig.tif", 1) != OK_RETURN)
return (-1);
unlink("tempBig.tif");
- fprintf(stdout, "---------- Test finished OK -----------\n");
+ fprintf(stdout, "---------- Signed tag test finished OK -----------\n");
+
+ /*-- Adapt tiff_field_info array for ignoring unknown tags to LibTIFF, which
+ * have been written to file. --*/
+ if (readTestTiff_ignore_some_tags("temp.tif") != OK_RETURN)
+ return (-1);
+ unlink("temp.tif");
+ fprintf(stdout,
+ "---------- Ignoring unknown tag test finished OK -----------\n");
+
return 0;
}
--
GitLab