8145113: OutOfMemoryError when reading a 17KB corrupted TIFF image

Add checks on size of field count and size of field data and consistency of data offsets and byte counts.

Reviewed-by: prr
This commit is contained in:
Brian Burkhalter 2016-01-04 17:05:04 -08:00
parent c08bfbfb19
commit ceb6329fdc

View File

@ -362,9 +362,9 @@ public class TIFFIFD extends TIFFDirectory {
offsets.add(f);
}
List<TIFFField> byteCounts = new ArrayList<>();
if (offsets.size() > 0) {
// StripByteCounts
List<TIFFField> byteCounts = new ArrayList<>();
f = getTIFFField(BaselineTIFFTagSet.TAG_STRIP_BYTE_COUNTS);
if (f != null) {
if (f.getCount() != count) {
@ -415,6 +415,12 @@ public class TIFFIFD extends TIFFDirectory {
}
}
// Ensure there is at least a data pointer for JPEG interchange format or
// both data offsets and byte counts for other compression types.
if (jpegOffset == null && (offsets.size() == 0 || byteCounts.size() == 0)) {
throw new IIOException("Insufficient data offsets or byte counts");
}
// JPEGQTables - one 64-byte table for each offset.
f = getTIFFField(BaselineTIFFTagSet.TAG_JPEG_Q_TABLES);
if (f != null) {
@ -480,14 +486,16 @@ public class TIFFIFD extends TIFFDirectory {
stream.skipBytes(4);
continue;
}
int count = (int)stream.readUnsignedInt();
long longCount = stream.readUnsignedInt();
// Get the associated TIFFTag.
TIFFTag tag = getTag(tagNumber, tagSetList);
// Ignore unknown fields.
// Ignore unknown fields, fields with unknown type, and fields
// with count out of int range.
if((tag == null && ignoreUnknownFields)
|| (tag != null && !tag.isDataTypeOK(type))) {
|| (tag != null && !tag.isDataTypeOK(type))
|| longCount > Integer.MAX_VALUE) {
// Skip the value/offset so as to leave the stream
// position at the start of the next IFD entry.
stream.skipBytes(4);
@ -496,6 +504,8 @@ public class TIFFIFD extends TIFFDirectory {
continue;
}
int count = (int)longCount;
if (tag == null) {
tag = new TIFFTag(TIFFTag.UNKNOWN_TAG_NAME, tagNumber,
1 << type, count);
@ -518,7 +528,14 @@ public class TIFFIFD extends TIFFDirectory {
}
}
int size = count*sizeOfType;
long longSize = longCount*sizeOfType;
if (longSize > Integer.MAX_VALUE) {
// Continue with the next IFD entry.
stream.skipBytes(4);
continue;
}
int size = (int)longSize;
if (size > 4 || tag.isIFDPointer()) {
// The IFD entry value is a pointer to the actual field value.
long offset = stream.readUnsignedInt();