8145113: OutOfMemoryError when reading a 17KB corrupted TIFF image
authorbpb
Mon, 04 Jan 2016 17:05:04 -0800
changeset 35660 471caf9d2ac0
parent 35659 ae936857454f
child 35661 29a43191feaf
8145113: OutOfMemoryError when reading a 17KB corrupted TIFF image Summary: Add checks on size of field count and size of field data and consistency of data offsets and byte counts. Reviewed-by: prr
jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFIFD.java
--- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFIFD.java	Wed Dec 30 19:28:05 2015 +0300
+++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFIFD.java	Mon Jan 04 17:05:04 2016 -0800
@@ -362,9 +362,9 @@
             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 @@
             }
         }
 
+        // 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 @@
                 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 @@
                 continue;
             }
 
+            int count = (int)longCount;
+
             if (tag == null) {
                 tag = new TIFFTag(TIFFTag.UNKNOWN_TAG_NAME, tagNumber,
                     1 << type, count);
@@ -518,7 +528,14 @@
                 }
             }
 
-            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();