Skip to content

Commit 634bce6

Browse files
SuLausrouault
authored andcommitted
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.
1 parent 43eb249 commit 634bce6

File tree

2 files changed

+201
-20
lines changed

2 files changed

+201
-20
lines changed

libtiff/tif_dirinfo.c

+27-11
Original file line numberDiff line numberDiff line change
@@ -1198,15 +1198,27 @@ int TIFFMergeFieldInfo(TIFF *tif, const TIFFFieldInfo info[], uint32_t n)
11981198
{
11991199
tp->field_tag = info[i].field_tag;
12001200
if (info[i].field_readcount < TIFF_VARIABLE2 ||
1201-
info[i].field_readcount == 0 ||
1202-
info[i].field_writecount < TIFF_VARIABLE2 ||
1203-
info[i].field_writecount == 0)
1201+
info[i].field_writecount < TIFF_VARIABLE2)
12041202
{
12051203
/* The fields (field_readcount) and (field_writecount) may use the
12061204
* values TIFF_VARIABLE (-1), TIFF_SPP (-2), TIFF_VARIABLE2 (-3). */
1207-
TIFFErrorExtR(tif, module,
1208-
"The value of field_readcount and field_writecount "
1209-
"must be greater than or equal to -3 and not zero.");
1205+
TIFFErrorExtR(
1206+
tif, module,
1207+
"The value of field_readcount %d and field_writecount %d "
1208+
"must be greater than or equal to -3.",
1209+
info[i].field_readcount, info[i].field_writecount);
1210+
return -1;
1211+
}
1212+
if ((info[i].field_readcount == 0 || info[i].field_writecount == 0) &&
1213+
info[i].field_bit != FIELD_IGNORE)
1214+
{
1215+
/* The fields (field_readcount) and (field_writecount) may only
1216+
be zero for pseudo_tags or ignored tags. */
1217+
TIFFErrorExtR(
1218+
tif, module,
1219+
"The value of field_readcount %d and field_writecount %d "
1220+
"may only be zero for field_bit = 0 (i.e. ignored tags).",
1221+
info[i].field_readcount, info[i].field_writecount);
12101222
return -1;
12111223
}
12121224
tp->field_readcount = info[i].field_readcount;
@@ -1222,14 +1234,18 @@ int TIFFMergeFieldInfo(TIFF *tif, const TIFFFieldInfo info[], uint32_t n)
12221234
tp->field_bit = info[i].field_bit;
12231235
tp->field_oktochange = info[i].field_oktochange;
12241236
tp->field_passcount = info[i].field_passcount;
1237+
/* Define an empty static string to be passed as field_name where a NULL
1238+
* pointer is passed in. Otherwise, this will lead to buffer overflow
1239+
* furtheron. */
12251240
if (info[i].field_name == NULL)
12261241
{
1227-
TIFFErrorExtR(tif, module,
1228-
"Field_name of %d.th allocation tag %d is NULL", i,
1229-
info[i].field_tag);
1230-
return -1;
1242+
static const char *string_static_empty = "";
1243+
tp->field_name = (char *)string_static_empty;
1244+
}
1245+
else
1246+
{
1247+
tp->field_name = info[i].field_name;
12311248
}
1232-
tp->field_name = info[i].field_name;
12331249
tp->field_subfields = NULL;
12341250
tp++;
12351251
}

test/test_signed_tags.c

+174-9
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,37 @@
55
* its documentation for any purpose is hereby granted without fee, provided
66
* that (i) the above copyright notices and this permission notice appear in
77
* all copies of the software and related documentation, and (ii) the names of
8-
* Sam Leffler and Silicon Graphics may not be used in any advertising or
8+
* the author may not be used in any advertising or
99
* publicity relating to the software without the specific, prior written
10-
* permission of Sam Leffler and Silicon Graphics.
10+
* permission of the author.
1111
*
1212
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
1313
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
1414
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
1515
*
16-
* IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
16+
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1717
* ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
1818
* OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
1919
* WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
2020
* LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
2121
* OF THIS SOFTWARE.
2222
*/
2323

24+
/* =========== Purpose ===============================================
25+
* Tests the following points:
26+
* - Handling of signed tags
27+
* - Definition of additional, user-defined tags
28+
* - Specification of field name strings or with field_name = NULL
29+
* - Prevent reading anonymous tags by specifying them as FIELD_IGNORE
30+
* (see https://gitlab.com/libtiff/libtiff/-/issues/532)
31+
* - Immediate clearing of the memory for the definition of the additional tags
32+
* (allocate memory for TIFFFieldInfo structure and free that memory
33+
* immediately after calling TIFFMergeFieldInfo().
34+
*/
35+
36+
#include <memory.h> /* necessary for linux compiler (memset) */
2437
#include <stdio.h>
38+
#include <stdlib.h> /* necessary for linux compiler */
2539

2640
#include "tif_config.h" /* necessary for linux compiler to get HAVE_UNISTD_H */
2741
#ifdef HAVE_UNISTD_H
@@ -36,6 +50,8 @@
3650

3751
#define N(a) (sizeof(a) / sizeof(a[0]))
3852

53+
#define FIELD_IGNORE 0 /* same as FIELD_PSEUDO */
54+
3955
enum
4056
{
4157
SINT8 = 65100,
@@ -54,6 +70,7 @@ enum
5470
C32_SINT16,
5571
C32_SINT32,
5672
C32_SINT64,
73+
C32_SINT64NULL,
5774
};
5875

5976
static const TIFFFieldInfo tiff_field_info[] = {
@@ -81,17 +98,34 @@ static const TIFFFieldInfo tiff_field_info[] = {
8198
"C32_SINT32"},
8299
{C32_SINT64, TIFF_VARIABLE2, TIFF_VARIABLE2, TIFF_SLONG8, FIELD_CUSTOM, 0,
83100
1, "C32_SINT64"},
101+
/* Test field_name=NULL in static const array, which is now possible because
102+
* handled within TIFFMergeFieldInfo(). */
103+
{C32_SINT64NULL, TIFF_VARIABLE2, TIFF_VARIABLE2, TIFF_SLONG8, FIELD_CUSTOM,
104+
0, 1, NULL},
84105
};
85106

107+
/* Global parameter for the field array to be passed to extender, which can be
108+
* changed during runtime. */
109+
static TIFFFieldInfo *p_tiff_field_info = (TIFFFieldInfo *)tiff_field_info;
110+
static uint32_t N_tiff_field_info =
111+
sizeof(tiff_field_info) / sizeof(tiff_field_info[0]);
112+
86113
static TIFFExtendProc parent = NULL;
87114

88115
static void extender(TIFF *tif)
89116
{
90-
TIFFMergeFieldInfo(tif, tiff_field_info,
91-
sizeof(tiff_field_info) / sizeof(tiff_field_info[0]));
92-
if (parent)
117+
if (p_tiff_field_info != NULL)
93118
{
94-
(*parent)(tif);
119+
TIFFMergeFieldInfo(tif, p_tiff_field_info, N_tiff_field_info);
120+
if (parent)
121+
{
122+
(*parent)(tif);
123+
}
124+
}
125+
else
126+
{
127+
TIFFErrorExtR(tif, "field_info_extender",
128+
"Pointer to tiff_field_info array is NULL.");
95129
}
96130
}
97131

@@ -187,6 +221,12 @@ static int writeTestTiff(const char *szFileName, int isBigTiff)
187221
fprintf(stdout, "Error writing C32_SINT64: ret=%d\n", ret);
188222
GOTOFAILURE;
189223
}
224+
ret = TIFFSetField(tif, C32_SINT64NULL, N(s64), &s64);
225+
if (ret != 1)
226+
{
227+
fprintf(stdout, "Error writing C32_SINT64NULL: ret=%d\n", ret);
228+
GOTOFAILURE;
229+
}
190230
}
191231

192232
TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, 1);
@@ -506,20 +546,145 @@ static int readTestTiff(const char *szFileName, int isBigTiff)
506546
TIFFClose(tif);
507547
return (retcode);
508548
}
549+
/*-- readTestTiff() --*/
550+
551+
static int readTestTiff_ignore_some_tags(const char *szFileName)
552+
{
553+
int ret;
554+
int8_t s8l;
555+
int16_t s16l;
556+
int32_t s32l;
557+
int retcode = FAULT_RETURN;
558+
559+
/* There is a use case, where LibTIFF shall be prevented from reading
560+
* unknown tags that are present in the file as anonymous tags. This can be
561+
* achieved by defining these tags with ".field_bit = FIELD_IGNORE". */
562+
563+
/* Copy const array to be manipulated and freed just after TIFFMergeFields()
564+
* within the "extender()" called by TIFFOpen(). */
565+
TIFFFieldInfo *tiff_field_info2;
566+
tiff_field_info2 = (TIFFFieldInfo *)malloc(sizeof(tiff_field_info));
567+
if (tiff_field_info2 == (TIFFFieldInfo *)NULL)
568+
{
569+
fprintf(stdout,
570+
"Can't allocate memoy for tiff_field_info2 structure.\n");
571+
return (FAULT_RETURN);
572+
}
573+
memcpy(tiff_field_info2, tiff_field_info, sizeof(tiff_field_info));
574+
/* Switch field array for extender callback. */
575+
p_tiff_field_info = tiff_field_info2;
576+
577+
/*-- Adapt tiff_field_info array for ignoring unknown tags to LibTIFF, which
578+
* have been written to file before. --*/
579+
/* a.) Just set field_bit to FIELD_IGNORE = 0 */
580+
tiff_field_info2[2].field_bit = FIELD_IGNORE;
581+
/* b.) Usecase with all field array infos zero but the tag value. */
582+
ttag_t tag = tiff_field_info2[4].field_tag;
583+
memset(&tiff_field_info2[4], 0, sizeof(tiff_field_info2[4]));
584+
tiff_field_info2[4].field_tag = tag;
585+
586+
fprintf(stdout, "\n-- Reading file with unknown tags to be ignored ...\n");
587+
TIFF *tif = TIFFOpen(szFileName, "r");
588+
589+
/* tiff_field_info2 should not be needed anymore, as long as the still
590+
* active extender() is not called again. Therefore, the extender callback
591+
* should be disabled by resetting it to the saved one. */
592+
free(tiff_field_info2);
593+
tiff_field_info2 = NULL;
594+
TIFFSetTagExtender(parent);
595+
596+
if (!tif)
597+
{
598+
fprintf(stdout, "Can't open test TIFF file %s.\n", szFileName);
599+
return (FAULT_RETURN);
600+
}
601+
602+
/* Read the first two known tags for testing */
603+
ret = TIFFGetField(tif, SINT8, &s8l);
604+
if (ret != 1)
605+
{
606+
fprintf(stdout, "Error reading SINT8: ret=%d\n", ret);
607+
GOTOFAILURE
608+
}
609+
else
610+
{
611+
if (s8l != s8[idxSingle])
612+
{
613+
fprintf(stdout,
614+
"Read value of SINT8 %d differs from set value %d\n", s8l,
615+
s8[idxSingle]);
616+
GOTOFAILURE
617+
}
618+
}
619+
ret = TIFFGetField(tif, SINT16, &s16l);
620+
if (ret != 1)
621+
{
622+
fprintf(stdout, "Error reading SINT16: ret=%d\n", ret);
623+
GOTOFAILURE
624+
}
625+
else
626+
{
627+
if (s16l != s16[idxSingle])
628+
{
629+
fprintf(stdout,
630+
"Read value of SINT16 %d differs from set value %d\n",
631+
s16l, s16[idxSingle]);
632+
GOTOFAILURE
633+
}
634+
}
635+
636+
/* The two ignored tags shall not be present. */
637+
ret = TIFFGetField(tif, tiff_field_info[2].field_tag, &s32l);
638+
if (ret != 0)
639+
{
640+
fprintf(stdout,
641+
"Error: Tag %d, set to be ignored, has been read from file.\n",
642+
tiff_field_info[2].field_tag);
643+
GOTOFAILURE
644+
}
645+
646+
ret = TIFFGetField(tif, tiff_field_info[4].field_tag, &s32l);
647+
if (ret != 0)
648+
{
649+
fprintf(stdout,
650+
"Error: Tag %d, set to be ignored, has been read from file.\n",
651+
tiff_field_info[4].field_tag);
652+
GOTOFAILURE
653+
}
654+
655+
retcode = OK_RETURN;
656+
failure:
657+
658+
fprintf(stdout,
659+
"-- End of test for ignored unknown tags. Closing TIFF file. --\n");
660+
TIFFClose(tif);
661+
return (retcode);
662+
}
663+
/*-- readTestTiff_ignore_some_tags() --*/
509664

510665
int main(void)
511666
{
667+
/*-- Signed tags test --*/
512668
parent = TIFFSetTagExtender(&extender);
513669
if (writeTestTiff("temp.tif", 0) != OK_RETURN)
514670
return (-1);
515671
if (readTestTiff("temp.tif", 0) != OK_RETURN)
516672
return (-1);
517-
unlink("temp.tif");
673+
518674
if (writeTestTiff("tempBig.tif", 1) != OK_RETURN)
519675
return (-1);
520676
if (readTestTiff("tempBig.tif", 1) != OK_RETURN)
521677
return (-1);
522678
unlink("tempBig.tif");
523-
fprintf(stdout, "---------- Test finished OK -----------\n");
679+
fprintf(stdout, "---------- Signed tag test finished OK -----------\n");
680+
681+
/*-- Adapt tiff_field_info array for ignoring unknown tags to LibTIFF, which
682+
* have been written to file. --*/
683+
if (readTestTiff_ignore_some_tags("temp.tif") != OK_RETURN)
684+
return (-1);
685+
unlink("temp.tif");
686+
fprintf(stdout,
687+
"---------- Ignoring unknown tag test finished OK -----------\n");
688+
524689
return 0;
525690
}

0 commit comments

Comments
 (0)