summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSu Laus <sulau@freenet.de>2019-08-04 13:23:07 +0000
committerEven Rouault <even.rouault@spatialys.com>2019-08-04 13:23:07 +0000
commit6f5c9477dd429890d33ac23fa3f8c29deb6d6640 (patch)
treea976f8db10fc94790b60c8d3e1572996e2548ccc
parentd8e707a953d1a7be5293ebbe6550213ddc00596c (diff)
downloadlibtiff-git-6f5c9477dd429890d33ac23fa3f8c29deb6d6640.tar.gz
Reading of Tiff tags with ID = 0 (like GPSVERSIONID) corrected.
IGNORE placeholder in tif_dirread.c is now replaced by a field dir_ignore in the TIFFDirEntry structure Currently, in tif_dirread.c a special IGNORE value for the tif tags is defined in order to flag status preventing already processed tags from further processing. This irrational behaviour prevents reading of custom tags with id code 0 - like tag GPSVERSIONID from EXIF 2.31 definition. An additional field 'tdir_ignore' is now added to the TIFFDirEntry structure and code is changed to allow tags with id code 0 to be read correctly. This change was already proposed as pending improvement in tif_dirread.c around line 32. Reference is also made to: - Discussion in https://gitlab.com/libtiff/libtiff/merge_requests/39 - http://bugzilla.maptools.org/show_bug.cgi?id=2540 Comments and indention adapted. Preparation to rebase onto master
-rw-r--r--libtiff/tif_dir.h1
-rw-r--r--libtiff/tif_dirread.c366
2 files changed, 183 insertions, 184 deletions
diff --git a/libtiff/tif_dir.h b/libtiff/tif_dir.h
index 718f146f..e7f06673 100644
--- a/libtiff/tif_dir.h
+++ b/libtiff/tif_dir.h
@@ -58,6 +58,7 @@ typedef struct {
uint32 toff_long;
uint64 toff_long8;
} tdir_offset; /* either offset or the data itself if fits */
+ uint8 tdir_ignore; /* flag status to ignore tag when parsing tags in tif_dirread.c */
} TIFFDirEntry;
/*
diff --git a/libtiff/tif_dirread.c b/libtiff/tif_dirread.c
index 1b300b09..3a06ea71 100644
--- a/libtiff/tif_dirread.c
+++ b/libtiff/tif_dirread.c
@@ -29,9 +29,6 @@
*/
/* Suggested pending improvements:
- * - add a field 'ignore' to the TIFFDirEntry structure, to flag status,
- * eliminating current use of the IGNORE value, and therefore eliminating
- * current irrational behaviour on tags with tag id code 0
* - add a field 'field_info' to the TIFFDirEntry structure, and set that with
* the pointer to the appropriate TIFFField structure early on in
* TIFFReadDirectory, so as to eliminate current possibly repetitive lookup.
@@ -41,7 +38,6 @@
#include <float.h>
#include <stdlib.h>
-#define IGNORE 0 /* tag placeholder used below */
#define FAILED_FII ((uint32) -1)
#ifdef HAVE_IEEEFP
@@ -3617,8 +3613,9 @@ TIFFReadDirectory(TIFF* tif)
uint16 nb;
for (na=ma+1, nb=mb+1; nb<dircount; na++, nb++)
{
- if (ma->tdir_tag==na->tdir_tag)
- na->tdir_tag=IGNORE;
+ if (ma->tdir_tag == na->tdir_tag) {
+ na->tdir_ignore = TRUE;
+ }
}
}
}
@@ -3659,7 +3656,7 @@ TIFFReadDirectory(TIFF* tif)
{
if (!TIFFFetchNormalTag(tif,dp,0))
goto bad;
- dp->tdir_tag=IGNORE;
+ dp->tdir_ignore = TRUE;
}
dp=TIFFReadDirectoryFindEntry(tif,dir,dircount,TIFFTAG_COMPRESSION);
if (dp)
@@ -3682,7 +3679,7 @@ TIFFReadDirectory(TIFF* tif)
}
if (!TIFFSetField(tif,TIFFTAG_COMPRESSION,value))
goto bad;
- dp->tdir_tag=IGNORE;
+ dp->tdir_ignore = TRUE;
}
else
{
@@ -3694,7 +3691,7 @@ TIFFReadDirectory(TIFF* tif)
*/
for (di=0, dp=dir; di<dircount; di++, dp++)
{
- if (dp->tdir_tag!=IGNORE)
+ if (!dp->tdir_ignore)
{
TIFFReadDirectoryFindFieldInfo(tif,dp->tdir_tag,&fii);
if (fii == FAILED_FII)
@@ -3702,8 +3699,8 @@ TIFFReadDirectory(TIFF* tif)
TIFFWarningExt(tif->tif_clientdata, module,
"Unknown field with tag %d (0x%x) encountered",
dp->tdir_tag,dp->tdir_tag);
- /* the following knowingly leaks the
- anonymous field structure */
+ /* the following knowingly leaks the
+ anonymous field structure */
if (!_TIFFMergeFields(tif,
_TIFFCreateAnonField(tif,
dp->tdir_tag,
@@ -3714,18 +3711,18 @@ TIFFReadDirectory(TIFF* tif)
"Registering anonymous field with tag %d (0x%x) failed",
dp->tdir_tag,
dp->tdir_tag);
- dp->tdir_tag=IGNORE;
+ dp->tdir_ignore = TRUE;
} else {
TIFFReadDirectoryFindFieldInfo(tif,dp->tdir_tag,&fii);
assert(fii != FAILED_FII);
}
}
}
- if (dp->tdir_tag!=IGNORE)
+ if (!dp->tdir_ignore)
{
fip=tif->tif_fields[fii];
if (fip->field_bit==FIELD_IGNORE)
- dp->tdir_tag=IGNORE;
+ dp->tdir_ignore = TRUE;
else
{
switch (dp->tdir_tag)
@@ -3747,12 +3744,12 @@ TIFFReadDirectory(TIFF* tif)
case TIFFTAG_EXTRASAMPLES:
if (!TIFFFetchNormalTag(tif,dp,0))
goto bad;
- dp->tdir_tag=IGNORE;
+ dp->tdir_ignore = TRUE;
+ break;
+ default:
+ if( !_TIFFCheckFieldIsValidForCodec(tif, dp->tdir_tag) )
+ dp->tdir_ignore = TRUE;
break;
- default:
- if( !_TIFFCheckFieldIsValidForCodec(tif, dp->tdir_tag) )
- dp->tdir_tag=IGNORE;
- break;
}
}
}
@@ -3768,8 +3765,8 @@ TIFFReadDirectory(TIFF* tif)
if ((tif->tif_dir.td_compression==COMPRESSION_OJPEG)&&
(tif->tif_dir.td_planarconfig==PLANARCONFIG_SEPARATE))
{
- if (!_TIFFFillStriles(tif))
- goto bad;
+ if (!_TIFFFillStriles(tif))
+ goto bad;
dp=TIFFReadDirectoryFindEntry(tif,dir,dircount,TIFFTAG_STRIPOFFSETS);
if ((dp!=0)&&(dp->tdir_count==1))
{
@@ -3841,164 +3838,164 @@ TIFFReadDirectory(TIFF* tif)
*/
for (di=0, dp=dir; di<dircount; di++, dp++)
{
- switch (dp->tdir_tag)
- {
- case IGNORE:
- break;
- case TIFFTAG_MINSAMPLEVALUE:
- case TIFFTAG_MAXSAMPLEVALUE:
- case TIFFTAG_BITSPERSAMPLE:
- case TIFFTAG_DATATYPE:
- case TIFFTAG_SAMPLEFORMAT:
- /*
- * The MinSampleValue, MaxSampleValue, BitsPerSample
- * DataType and SampleFormat tags are supposed to be
- * written as one value/sample, but some vendors
- * incorrectly write one value only -- so we accept
- * that as well (yuck). Other vendors write correct
- * value for NumberOfSamples, but incorrect one for
- * BitsPerSample and friends, and we will read this
- * too.
- */
- {
- uint16 value;
- enum TIFFReadDirEntryErr err;
- err=TIFFReadDirEntryShort(tif,dp,&value);
- if (err==TIFFReadDirEntryErrCount)
- err=TIFFReadDirEntryPersampleShort(tif,dp,&value);
- if (err!=TIFFReadDirEntryErrOk)
- {
- fip = TIFFFieldWithTag(tif,dp->tdir_tag);
- TIFFReadDirEntryOutputErr(tif,err,module,fip ? fip->field_name : "unknown tagname",0);
- goto bad;
- }
- if (!TIFFSetField(tif,dp->tdir_tag,value))
- goto bad;
- if( dp->tdir_tag == TIFFTAG_BITSPERSAMPLE )
- bitspersample_read = TRUE;
- }
- break;
- case TIFFTAG_SMINSAMPLEVALUE:
- case TIFFTAG_SMAXSAMPLEVALUE:
- {
-
- double *data = NULL;
- enum TIFFReadDirEntryErr err;
- uint32 saved_flags;
- int m;
- if (dp->tdir_count != (uint64)tif->tif_dir.td_samplesperpixel)
- err = TIFFReadDirEntryErrCount;
- else
- err = TIFFReadDirEntryDoubleArray(tif, dp, &data);
- if (err!=TIFFReadDirEntryErrOk)
- {
- fip = TIFFFieldWithTag(tif,dp->tdir_tag);
- TIFFReadDirEntryOutputErr(tif,err,module,fip ? fip->field_name : "unknown tagname",0);
- goto bad;
- }
- saved_flags = tif->tif_flags;
- tif->tif_flags |= TIFF_PERSAMPLE;
- m = TIFFSetField(tif,dp->tdir_tag,data);
- tif->tif_flags = saved_flags;
- _TIFFfree(data);
- if (!m)
- goto bad;
- }
- break;
- case TIFFTAG_STRIPOFFSETS:
- case TIFFTAG_TILEOFFSETS:
- _TIFFmemcpy( &(tif->tif_dir.td_stripoffset_entry),
- dp, sizeof(TIFFDirEntry) );
- break;
- case TIFFTAG_STRIPBYTECOUNTS:
- case TIFFTAG_TILEBYTECOUNTS:
- _TIFFmemcpy( &(tif->tif_dir.td_stripbytecount_entry),
- dp, sizeof(TIFFDirEntry) );
- break;
- case TIFFTAG_COLORMAP:
- case TIFFTAG_TRANSFERFUNCTION:
- {
- enum TIFFReadDirEntryErr err;
- uint32 countpersample;
- uint32 countrequired;
- uint32 incrementpersample;
- uint16* value=NULL;
- /* It would be dangerous to instantiate those tag values */
- /* since if td_bitspersample has not yet been read (due to */
- /* unordered tags), it could be read afterwards with a */
- /* values greater than the default one (1), which may cause */
- /* crashes in user code */
- if( !bitspersample_read )
- {
- fip = TIFFFieldWithTag(tif,dp->tdir_tag);
- TIFFWarningExt(tif->tif_clientdata,module,
- "Ignoring %s since BitsPerSample tag not found",
- fip ? fip->field_name : "unknown tagname");
- continue;
- }
- /* ColorMap or TransferFunction for high bit */
- /* depths do not make much sense and could be */
- /* used as a denial of service vector */
- if (tif->tif_dir.td_bitspersample > 24)
- {
- fip = TIFFFieldWithTag(tif,dp->tdir_tag);
- TIFFWarningExt(tif->tif_clientdata,module,
- "Ignoring %s because BitsPerSample=%d>24",
- fip ? fip->field_name : "unknown tagname",
- tif->tif_dir.td_bitspersample);
- continue;
- }
- countpersample=(1U<<tif->tif_dir.td_bitspersample);
- if ((dp->tdir_tag==TIFFTAG_TRANSFERFUNCTION)&&(dp->tdir_count==(uint64)countpersample))
+ if (!dp->tdir_ignore) {
+ switch (dp->tdir_tag)
+ {
+ case TIFFTAG_MINSAMPLEVALUE:
+ case TIFFTAG_MAXSAMPLEVALUE:
+ case TIFFTAG_BITSPERSAMPLE:
+ case TIFFTAG_DATATYPE:
+ case TIFFTAG_SAMPLEFORMAT:
+ /*
+ * The MinSampleValue, MaxSampleValue, BitsPerSample
+ * DataType and SampleFormat tags are supposed to be
+ * written as one value/sample, but some vendors
+ * incorrectly write one value only -- so we accept
+ * that as well (yuck). Other vendors write correct
+ * value for NumberOfSamples, but incorrect one for
+ * BitsPerSample and friends, and we will read this
+ * too.
+ */
{
- countrequired=countpersample;
- incrementpersample=0;
+ uint16 value;
+ enum TIFFReadDirEntryErr err;
+ err=TIFFReadDirEntryShort(tif,dp,&value);
+ if (err==TIFFReadDirEntryErrCount)
+ err=TIFFReadDirEntryPersampleShort(tif,dp,&value);
+ if (err!=TIFFReadDirEntryErrOk)
+ {
+ fip = TIFFFieldWithTag(tif,dp->tdir_tag);
+ TIFFReadDirEntryOutputErr(tif,err,module,fip ? fip->field_name : "unknown tagname",0);
+ goto bad;
+ }
+ if (!TIFFSetField(tif,dp->tdir_tag,value))
+ goto bad;
+ if( dp->tdir_tag == TIFFTAG_BITSPERSAMPLE )
+ bitspersample_read = TRUE;
}
- else
+ break;
+ case TIFFTAG_SMINSAMPLEVALUE:
+ case TIFFTAG_SMAXSAMPLEVALUE:
{
- countrequired=3*countpersample;
- incrementpersample=countpersample;
+
+ double *data = NULL;
+ enum TIFFReadDirEntryErr err;
+ uint32 saved_flags;
+ int m;
+ if (dp->tdir_count != (uint64)tif->tif_dir.td_samplesperpixel)
+ err = TIFFReadDirEntryErrCount;
+ else
+ err = TIFFReadDirEntryDoubleArray(tif, dp, &data);
+ if (err!=TIFFReadDirEntryErrOk)
+ {
+ fip = TIFFFieldWithTag(tif,dp->tdir_tag);
+ TIFFReadDirEntryOutputErr(tif,err,module,fip ? fip->field_name : "unknown tagname",0);
+ goto bad;
+ }
+ saved_flags = tif->tif_flags;
+ tif->tif_flags |= TIFF_PERSAMPLE;
+ m = TIFFSetField(tif,dp->tdir_tag,data);
+ tif->tif_flags = saved_flags;
+ _TIFFfree(data);
+ if (!m)
+ goto bad;
}
- if (dp->tdir_count!=(uint64)countrequired)
- err=TIFFReadDirEntryErrCount;
- else
- err=TIFFReadDirEntryShortArray(tif,dp,&value);
- if (err!=TIFFReadDirEntryErrOk)
- {
- fip = TIFFFieldWithTag(tif,dp->tdir_tag);
- TIFFReadDirEntryOutputErr(tif,err,module,fip ? fip->field_name : "unknown tagname",1);
- }
- else
+ break;
+ case TIFFTAG_STRIPOFFSETS:
+ case TIFFTAG_TILEOFFSETS:
+ _TIFFmemcpy( &(tif->tif_dir.td_stripoffset_entry),
+ dp, sizeof(TIFFDirEntry) );
+ break;
+ case TIFFTAG_STRIPBYTECOUNTS:
+ case TIFFTAG_TILEBYTECOUNTS:
+ _TIFFmemcpy( &(tif->tif_dir.td_stripbytecount_entry),
+ dp, sizeof(TIFFDirEntry) );
+ break;
+ case TIFFTAG_COLORMAP:
+ case TIFFTAG_TRANSFERFUNCTION:
{
- TIFFSetField(tif,dp->tdir_tag,value,value+incrementpersample,value+2*incrementpersample);
- _TIFFfree(value);
+ enum TIFFReadDirEntryErr err;
+ uint32 countpersample;
+ uint32 countrequired;
+ uint32 incrementpersample;
+ uint16* value=NULL;
+ /* It would be dangerous to instantiate those tag values */
+ /* since if td_bitspersample has not yet been read (due to */
+ /* unordered tags), it could be read afterwards with a */
+ /* values greater than the default one (1), which may cause */
+ /* crashes in user code */
+ if( !bitspersample_read )
+ {
+ fip = TIFFFieldWithTag(tif,dp->tdir_tag);
+ TIFFWarningExt(tif->tif_clientdata,module,
+ "Ignoring %s since BitsPerSample tag not found",
+ fip ? fip->field_name : "unknown tagname");
+ continue;
+ }
+ /* ColorMap or TransferFunction for high bit */
+ /* depths do not make much sense and could be */
+ /* used as a denial of service vector */
+ if (tif->tif_dir.td_bitspersample > 24)
+ {
+ fip = TIFFFieldWithTag(tif,dp->tdir_tag);
+ TIFFWarningExt(tif->tif_clientdata,module,
+ "Ignoring %s because BitsPerSample=%d>24",
+ fip ? fip->field_name : "unknown tagname",
+ tif->tif_dir.td_bitspersample);
+ continue;
+ }
+ countpersample=(1U<<tif->tif_dir.td_bitspersample);
+ if ((dp->tdir_tag==TIFFTAG_TRANSFERFUNCTION)&&(dp->tdir_count==(uint64)countpersample))
+ {
+ countrequired=countpersample;
+ incrementpersample=0;
+ }
+ else
+ {
+ countrequired=3*countpersample;
+ incrementpersample=countpersample;
+ }
+ if (dp->tdir_count!=(uint64)countrequired)
+ err=TIFFReadDirEntryErrCount;
+ else
+ err=TIFFReadDirEntryShortArray(tif,dp,&value);
+ if (err!=TIFFReadDirEntryErrOk)
+ {
+ fip = TIFFFieldWithTag(tif,dp->tdir_tag);
+ TIFFReadDirEntryOutputErr(tif,err,module,fip ? fip->field_name : "unknown tagname",1);
+ }
+ else
+ {
+ TIFFSetField(tif,dp->tdir_tag,value,value+incrementpersample,value+2*incrementpersample);
+ _TIFFfree(value);
+ }
}
- }
- break;
+ break;
/* BEGIN REV 4.0 COMPATIBILITY */
- case TIFFTAG_OSUBFILETYPE:
- {
- uint16 valueo;
- uint32 value;
- if (TIFFReadDirEntryShort(tif,dp,&valueo)==TIFFReadDirEntryErrOk)
+ case TIFFTAG_OSUBFILETYPE:
{
- switch (valueo)
+ uint16 valueo;
+ uint32 value;
+ if (TIFFReadDirEntryShort(tif,dp,&valueo)==TIFFReadDirEntryErrOk)
{
- case OFILETYPE_REDUCEDIMAGE: value=FILETYPE_REDUCEDIMAGE; break;
- case OFILETYPE_PAGE: value=FILETYPE_PAGE; break;
- default: value=0; break;
+ switch (valueo)
+ {
+ case OFILETYPE_REDUCEDIMAGE: value=FILETYPE_REDUCEDIMAGE; break;
+ case OFILETYPE_PAGE: value=FILETYPE_PAGE; break;
+ default: value=0; break;
+ }
+ if (value!=0)
+ TIFFSetField(tif,TIFFTAG_SUBFILETYPE,value);
}
- if (value!=0)
- TIFFSetField(tif,TIFFTAG_SUBFILETYPE,value);
}
- }
- break;
+ break;
/* END REV 4.0 COMPATIBILITY */
- default:
- (void) TIFFFetchNormalTag(tif, dp, TRUE);
- break;
- }
- }
+ default:
+ (void) TIFFFetchNormalTag(tif, dp, TRUE);
+ break;
+ }
+ } /* -- if (!dp->tdir_ignore) */
+ } /* -- for-loop -- */
if( tif->tif_mode == O_RDWR &&
tif->tif_dir.td_stripoffset_entry.tdir_tag != 0 &&
@@ -4431,17 +4428,17 @@ TIFFReadCustomDirectory(TIFF* tif, toff_t diroff,
TIFFWarningExt(tif->tif_clientdata, module,
"Registering anonymous field with tag %d (0x%x) failed",
dp->tdir_tag, dp->tdir_tag);
- dp->tdir_tag=IGNORE;
+ dp->tdir_ignore = TRUE;
} else {
TIFFReadDirectoryFindFieldInfo(tif,dp->tdir_tag,&fii);
assert( fii != FAILED_FII );
}
}
- if (dp->tdir_tag!=IGNORE)
+ if (!dp->tdir_ignore)
{
fip=tif->tif_fields[fii];
if (fip->field_bit==FIELD_IGNORE)
- dp->tdir_tag=IGNORE;
+ dp->tdir_ignore = TRUE;
else
{
/* check data type */
@@ -4461,7 +4458,7 @@ TIFFReadCustomDirectory(TIFF* tif, toff_t diroff,
TIFFWarningExt(tif->tif_clientdata, module,
"Wrong data type %d for \"%s\"; tag ignored",
dp->tdir_type,fip->field_name);
- dp->tdir_tag=IGNORE;
+ dp->tdir_ignore = TRUE;
}
else
{
@@ -4475,21 +4472,21 @@ TIFFReadCustomDirectory(TIFF* tif, toff_t diroff,
else
expected=(uint32)fip->field_readcount;
if (!CheckDirCount(tif,dp,expected))
- dp->tdir_tag=IGNORE;
+ dp->tdir_ignore = TRUE;
}
}
}
- switch (dp->tdir_tag)
- {
- case IGNORE:
- break;
- case EXIFTAG_SUBJECTDISTANCE:
- (void) TIFFFetchSubjectDistance(tif,dp);
- break;
- default:
- (void) TIFFFetchNormalTag(tif, dp, TRUE);
- break;
- }
+ if (!dp->tdir_ignore) {
+ switch (dp->tdir_tag)
+ {
+ case EXIFTAG_SUBJECTDISTANCE:
+ (void)TIFFFetchSubjectDistance(tif, dp);
+ break;
+ default:
+ (void)TIFFFetchNormalTag(tif, dp, TRUE);
+ break;
+ }
+ } /*-- if (!dp->tdir_ignore) */
}
}
if (dir)
@@ -4909,6 +4906,7 @@ TIFFFetchDirectory(TIFF* tif, uint64 diroff, TIFFDirEntry** pdir,
mb=dir;
for (n=0; n<dircount16; n++)
{
+ mb->tdir_ignore = FALSE;
if (tif->tif_flags&TIFF_SWAB)
TIFFSwabShort((uint16*)ma);
mb->tdir_tag=*(uint16*)ma;
@@ -4923,7 +4921,7 @@ TIFFFetchDirectory(TIFF* tif, uint64 diroff, TIFFDirEntry** pdir,
TIFFSwabLong((uint32*)ma);
mb->tdir_count=(uint64)(*(uint32*)ma);
ma+=sizeof(uint32);
- mb->tdir_offset.toff_long8=0;
+ mb->tdir_offset.toff_long8=0;
*(uint32*)(&mb->tdir_offset)=*(uint32*)ma;
ma+=sizeof(uint32);
}