summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfwarmerdam <fwarmerdam>2010-06-14 00:21:46 +0000
committerfwarmerdam <fwarmerdam>2010-06-14 00:21:46 +0000
commitca24b1957b9dc0a9cbe24754eb38b18553e18fb2 (patch)
treeb5aa4c34fda7b4b2c86b101bd96d166f08a26742
parent3c20d38c92a6a9966535a9defe46fae4a5ccdb56 (diff)
downloadlibtiff-ca24b1957b9dc0a9cbe24754eb38b18553e18fb2.tar.gz
fixed bad handling of out of order tags defined late by codecs (#2210)
-rw-r--r--ChangeLog3
-rw-r--r--libtiff/tif_dirread.c105
2 files changed, 81 insertions, 27 deletions
diff --git a/ChangeLog b/ChangeLog
index d298031c..a02246d2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,8 @@
2010-06-13 Frank Warmerdam <warmerdam@pobox.com>
+ * libtiff/tif_dirread.c: Fixed bad handling of out of order tags
+ definated late by a codec (#2210)
+
* libtiff/tif_dirread.c: Fixed inadequate validation of the
SubjectDistance field (#2212).
diff --git a/libtiff/tif_dirread.c b/libtiff/tif_dirread.c
index 0c973ee9..907b5318 100644
--- a/libtiff/tif_dirread.c
+++ b/libtiff/tif_dirread.c
@@ -1,4 +1,4 @@
-/* $Id: tif_dirread.c,v 1.92.2.8 2010-06-14 00:19:22 fwarmerdam Exp $ */
+/* $Id: tif_dirread.c,v 1.92.2.9 2010-06-14 00:21:46 fwarmerdam Exp $ */
/*
* Copyright (c) 1988-1997 Sam Leffler
@@ -84,6 +84,7 @@ TIFFReadDirectory(TIFF* tif)
size_t fix;
uint16 dircount;
int diroutoforderwarning = 0, compressionknown = 0;
+ int haveunknowntags = 0;
tif->tif_diroff = tif->tif_nextdiroff;
/*
@@ -160,8 +161,10 @@ TIFFReadDirectory(TIFF* tif)
fix = 0;
for (dp = dir, n = dircount; n > 0; n--, dp++) {
- if (fix >= tif->tif_nfields || dp->tdir_tag == IGNORE)
+ if (dp->tdir_tag == IGNORE)
continue;
+ if (fix >= tif->tif_nfields)
+ fix = 0;
/*
* Silicon Beach (at least) writes unordered
@@ -182,31 +185,9 @@ TIFFReadDirectory(TIFF* tif)
fix++;
if (fix >= tif->tif_nfields ||
tif->tif_fieldinfo[fix]->field_tag != dp->tdir_tag) {
-
- TIFFWarningExt(tif->tif_clientdata,
- module,
- "%s: unknown field with tag %d (0x%x) encountered",
- tif->tif_name,
- dp->tdir_tag,
- dp->tdir_tag);
-
- if (!_TIFFMergeFieldInfo(tif,
- _TIFFCreateAnonFieldInfo(tif,
- dp->tdir_tag,
- (TIFFDataType) dp->tdir_type),
- 1))
- {
- TIFFWarningExt(tif->tif_clientdata,
- module,
- "Registering anonymous field with tag %d (0x%x) failed",
- dp->tdir_tag,
- dp->tdir_tag);
- goto ignore;
- }
- fix = 0;
- while (fix < tif->tif_nfields &&
- tif->tif_fieldinfo[fix]->field_tag < dp->tdir_tag)
- fix++;
+ /* Unknown tag ... we'll deal with it below */
+ haveunknowntags = 1;
+ continue;
}
/*
* Null out old tags that we ignore.
@@ -297,6 +278,76 @@ TIFFReadDirectory(TIFF* tif)
}
/*
+ * If we saw any unknown tags, make an extra pass over the directory
+ * to deal with them. This must be done separately because the tags
+ * could have become known when we registered a codec after finding
+ * the Compression tag. In a correctly-sorted directory there's
+ * no problem because Compression will come before any codec-private
+ * tags, but if the sorting is wrong that might not hold.
+ */
+ if (haveunknowntags) {
+ fix = 0;
+ for (dp = dir, n = dircount; n > 0; n--, dp++) {
+ if (dp->tdir_tag == IGNORE)
+ continue;
+ if (fix >= tif->tif_nfields ||
+ dp->tdir_tag < tif->tif_fieldinfo[fix]->field_tag)
+ fix = 0; /* O(n^2) */
+ while (fix < tif->tif_nfields &&
+ tif->tif_fieldinfo[fix]->field_tag < dp->tdir_tag)
+ fix++;
+ if (fix >= tif->tif_nfields ||
+ tif->tif_fieldinfo[fix]->field_tag != dp->tdir_tag) {
+
+ TIFFWarningExt(tif->tif_clientdata,
+ module,
+ "%s: unknown field with tag %d (0x%x) encountered",
+ tif->tif_name,
+ dp->tdir_tag,
+ dp->tdir_tag);
+
+ if (!_TIFFMergeFieldInfo(tif,
+ _TIFFCreateAnonFieldInfo(tif,
+ dp->tdir_tag,
+ (TIFFDataType) dp->tdir_type),
+ 1))
+ {
+ TIFFWarningExt(tif->tif_clientdata,
+ module,
+ "Registering anonymous field with tag %d (0x%x) failed",
+ dp->tdir_tag,
+ dp->tdir_tag);
+ dp->tdir_tag = IGNORE;
+ continue;
+ }
+ fix = 0;
+ while (fix < tif->tif_nfields &&
+ tif->tif_fieldinfo[fix]->field_tag < dp->tdir_tag)
+ fix++;
+ }
+ /*
+ * Check data type.
+ */
+ fip = tif->tif_fieldinfo[fix];
+ while (dp->tdir_type != (unsigned short) fip->field_type
+ && fix < tif->tif_nfields) {
+ if (fip->field_type == TIFF_ANY) /* wildcard */
+ break;
+ fip = tif->tif_fieldinfo[++fix];
+ if (fix >= tif->tif_nfields ||
+ fip->field_tag != dp->tdir_tag) {
+ TIFFWarningExt(tif->tif_clientdata, module,
+ "%s: wrong data type %d for \"%s\"; tag ignored",
+ tif->tif_name, dp->tdir_type,
+ tif->tif_fieldinfo[fix-1]->field_name);
+ dp->tdir_tag = IGNORE;
+ break;
+ }
+ }
+ }
+ }
+
+ /*
* XXX: OJPEG hack.
* If a) compression is OJPEG, b) planarconfig tag says it's separate,
* c) strip offsets/bytecounts tag are both present and