diff options
author | fwarmerdam <fwarmerdam> | 2010-06-14 00:21:46 +0000 |
---|---|---|
committer | fwarmerdam <fwarmerdam> | 2010-06-14 00:21:46 +0000 |
commit | ca24b1957b9dc0a9cbe24754eb38b18553e18fb2 (patch) | |
tree | b5aa4c34fda7b4b2c86b101bd96d166f08a26742 | |
parent | 3c20d38c92a6a9966535a9defe46fae4a5ccdb56 (diff) | |
download | libtiff-ca24b1957b9dc0a9cbe24754eb38b18553e18fb2.tar.gz |
fixed bad handling of out of order tags defined late by codecs (#2210)
-rw-r--r-- | ChangeLog | 3 | ||||
-rw-r--r-- | libtiff/tif_dirread.c | 105 |
2 files changed, 81 insertions, 27 deletions
@@ -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 |