7058602: BMP parser bugs found via zzuf fuzzing
authorbae
Mon, 14 Oct 2013 15:32:29 +0400
changeset 21221 d80929154039
parent 21220 a6cbbedabed7
child 21222 69edb4f345a3
7058602: BMP parser bugs found via zzuf fuzzing Reviewed-by: prr, vadim
jdk/src/share/classes/com/sun/imageio/plugins/bmp/BMPImageReader.java
jdk/src/share/classes/com/sun/imageio/plugins/common/iio-plugin.properties
jdk/src/share/classes/java/awt/image/ComponentSampleModel.java
--- a/jdk/src/share/classes/com/sun/imageio/plugins/bmp/BMPImageReader.java	Sat Oct 12 14:14:24 2013 -0700
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/bmp/BMPImageReader.java	Mon Oct 14 15:32:29 2013 +0400
@@ -187,15 +187,24 @@
         return 1;
     }
 
+    @Override
     public int getWidth(int imageIndex) throws IOException {
         checkIndex(imageIndex);
-        readHeader();
+        try {
+            readHeader();
+        } catch (IllegalArgumentException e) {
+            throw new IIOException(I18N.getString("BMPImageReader6"), e);
+        }
         return width;
     }
 
     public int getHeight(int imageIndex) throws IOException {
         checkIndex(imageIndex);
-        readHeader();
+        try {
+            readHeader();
+        } catch (IllegalArgumentException e) {
+            throw new IIOException(I18N.getString("BMPImageReader6"), e);
+        }
         return height;
     }
 
@@ -205,7 +214,18 @@
         }
     }
 
-    public void readHeader() throws IOException {
+    /**
+     * Process the image header.
+     *
+     * @exception IllegalStateException if source stream is not set.
+     *
+     * @exception IOException if image stream is corrupted.
+     *
+     * @exception IllegalArgumentException if the image stream does not contain
+     *             a BMP image, or if a sample model instance to describe the
+     *             image can not be created.
+     */
+    protected void readHeader() throws IOException, IllegalArgumentException {
         if (gotHeader)
             return;
 
@@ -307,6 +327,9 @@
                 case BI_RLE4:  // 4-bit RLE compression
 
                     // Read in the palette
+                    if (bitmapOffset < (size + 14)) {
+                        throw new IIOException(I18N.getString("BMPImageReader7"));
+                    }
                     int numberOfEntries = (int)((bitmapOffset-14-size) / 4);
                     int sizeOfPalette = numberOfEntries * 4;
                     palette = new byte[sizeOfPalette];
@@ -375,7 +398,7 @@
                     break;
                 default:
                     throw new
-                        RuntimeException(I18N.getString("BMPImageReader2"));
+                        IIOException(I18N.getString("BMPImageReader2"));
                 }
             } else if (size == 108 || size == 124) {
                 // Windows 4.x BMP
@@ -478,7 +501,7 @@
                 }
             } else {
                 throw new
-                    RuntimeException(I18N.getString("BMPImageReader3"));
+                    IIOException(I18N.getString("BMPImageReader3"));
             }
         }
 
@@ -660,7 +683,11 @@
     public Iterator getImageTypes(int imageIndex)
       throws IOException {
         checkIndex(imageIndex);
-        readHeader();
+        try {
+            readHeader();
+        } catch (IllegalArgumentException e) {
+            throw new IIOException(I18N.getString("BMPImageReader6"), e);
+        }
         ArrayList list = new ArrayList(1);
         list.add(new ImageTypeSpecifier(originalColorModel,
                                         originalSampleModel));
@@ -675,7 +702,11 @@
       throws IOException {
         checkIndex(imageIndex);
         if (metadata == null) {
-            readHeader();
+            try {
+                readHeader();
+            } catch (IllegalArgumentException e) {
+                throw new IIOException(I18N.getString("BMPImageReader6"), e);
+            }
         }
         return metadata;
     }
@@ -686,7 +717,11 @@
 
     public boolean isRandomAccessEasy(int imageIndex) throws IOException {
         checkIndex(imageIndex);
-        readHeader();
+        try {
+            readHeader();
+        } catch (IllegalArgumentException e) {
+            throw new IIOException(I18N.getString("BMPImageReader6"), e);
+        }
         return metadata.compression == BI_RGB;
     }
 
@@ -705,7 +740,11 @@
             param = getDefaultReadParam();
 
         //read header
-        readHeader();
+        try {
+            readHeader();
+        } catch (IllegalArgumentException e) {
+            throw new IIOException(I18N.getString("BMPImageReader6"), e);
+        }
 
         sourceRegion = new Rectangle(0, 0, 0, 0);
         destinationRegion = new Rectangle(0, 0, 0, 0);
@@ -817,7 +856,7 @@
 
             default:
                 throw new
-                    RuntimeException(I18N.getString("BMPImageReader1"));
+                    IIOException(I18N.getString("BMPImageReader1"));
             }
             break;
 
@@ -833,7 +872,7 @@
 
             default:
                 throw new
-                    RuntimeException(I18N.getString("BMPImageReader1"));
+                    IIOException(I18N.getString("BMPImageReader1"));
             }
 
             break;
@@ -874,7 +913,7 @@
 
             default:
                 throw new
-                    RuntimeException(I18N.getString("BMPImageReader1"));
+                    IIOException(I18N.getString("BMPImageReader1"));
             }
 
         case VERSION_4_8_BIT:
@@ -890,7 +929,7 @@
 
             default:
                 throw new
-                    RuntimeException(I18N.getString("BMPImageReader1"));
+                    IIOException(I18N.getString("BMPImageReader1"));
             }
             break;
 
--- a/jdk/src/share/classes/com/sun/imageio/plugins/common/iio-plugin.properties	Sat Oct 12 14:14:24 2013 -0700
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/common/iio-plugin.properties	Mon Oct 14 15:32:29 2013 +0400
@@ -21,6 +21,8 @@
 BMPImageReader3=New BMP version not implemented yet.
 BMPImageReader4=No ImageIO-style reader is found for
 BMPImageReader5=Input has not been set.
+BMPImageReader6=Unable to read the image header.
+BMPImageReader7=Invalid bitmap offset.
 BMPImageWriter0=Output is not an ImageOutputStream.
 BMPImageWriter1=The image region to be encoded is empty.
 BMPImageWriter2=Only 1 or 3 band image is encoded.
@@ -34,7 +36,7 @@
 BMPMetadata1=Metadata is read-only.
 
 
-# WBMP plugin properties 
+# WBMP plugin properties
 WBMPImageReader0=Only one image exists in the stream.
 WBMPImageReader1=Input has not been set.
 WBMPImageReader2=Bad WBMP header.
--- a/jdk/src/share/classes/java/awt/image/ComponentSampleModel.java	Sat Oct 12 14:14:24 2013 -0700
+++ b/jdk/src/share/classes/java/awt/image/ComponentSampleModel.java	Mon Oct 14 15:32:29 2013 +0400
@@ -167,6 +167,7 @@
         for (int i=0; i<numBands; i++) {
             bankIndices[i] = 0;
         }
+        verify();
     }
 
 
@@ -244,24 +245,53 @@
             throw new IllegalArgumentException("Length of bandOffsets must "+
                                                "equal length of bankIndices.");
         }
+        verify();
+    }
+
+    private void verify() {
+        int requiredSize = getBufferSize();
     }
 
     /**
      * Returns the size of the data buffer (in data elements) needed
      * for a data buffer that matches this ComponentSampleModel.
      */
-     private long getBufferSize() {
+     private int getBufferSize() {
          int maxBandOff=bandOffsets[0];
-         for (int i=1; i<bandOffsets.length; i++)
+         for (int i=1; i<bandOffsets.length; i++) {
              maxBandOff = Math.max(maxBandOff,bandOffsets[i]);
+         }
+
+         if (maxBandOff < 0 || maxBandOff > (Integer.MAX_VALUE - 1)) {
+             throw new IllegalArgumentException("Invalid band offset");
+         }
+
+         if (pixelStride < 0 || pixelStride > (Integer.MAX_VALUE / width)) {
+             throw new IllegalArgumentException("Invalid pixel stride");
+         }
+
+         if (scanlineStride < 0 || scanlineStride > (Integer.MAX_VALUE / height)) {
+             throw new IllegalArgumentException("Invalid scanline stride");
+         }
 
-         long size = 0;
-         if (maxBandOff >= 0)
-             size += maxBandOff+1;
-         if (pixelStride > 0)
-             size += pixelStride * (width-1);
-         if (scanlineStride > 0)
-             size += scanlineStride*(height-1);
+         int size = maxBandOff + 1;
+
+         int val = pixelStride * (width - 1);
+
+         if (val > (Integer.MAX_VALUE - size)) {
+             throw new IllegalArgumentException("Invalid pixel stride");
+         }
+
+         size += val;
+
+         val = scanlineStride * (height - 1);
+
+         if (val > (Integer.MAX_VALUE - size)) {
+             throw new IllegalArgumentException("Invalid scan stride");
+         }
+
+         size += val;
+
          return size;
      }
 
@@ -409,7 +439,7 @@
     public DataBuffer createDataBuffer() {
         DataBuffer dataBuffer = null;
 
-        int size = (int)getBufferSize();
+        int size = getBufferSize();
         switch (dataType) {
         case DataBuffer.TYPE_BYTE:
             dataBuffer = new DataBufferByte(size, numBanks);