I. BACKGROUND

http://en.wikipedia.org/wiki/JavaSE
http://openjdk.java.net/projects/jdk7u/
http://hg.openjdk.java.net/jdk7u/jdk7u/jdk  // Java and native sources


II. DESCRIPTION
    
The vulnerable Java's ByteComponentRaster.verify() method allows to bypass all
"dataOffsets[]" boundary checks when the "numDataElements" field is 0:

    // sun.awt.image.ByteComponentRaster
    protected final void verify() {
        for (int i = 0; i < dataOffsets.length; i++) {
            if (dataOffsets[i] < 0) {
                throw new RasterFormatException("Data offsets for band " + i + "(" + dataOffsets[i] + ") must be >= 0");
            }
        }

        int maxSize = 0;
        int size;

        // we can be sure that width and height are greater than 0
        if (scanlineStride < 0 || scanlineStride > (Integer.MAX_VALUE / height))
        {
            // integer overflow
            throw new RasterFormatException("Incorrect scanline stride: " + scanlineStride);
        }
        int lastScanOffset = (height - 1) * scanlineStride;

        if (pixelStride < 0 || pixelStride > (Integer.MAX_VALUE / width))
        {
            // integer overflow
            throw new RasterFormatException("Incorrect pixel stride: " + pixelStride);
        }
        int lastPixelOffset = (width - 1) * pixelStride;

        if (lastPixelOffset > (Integer.MAX_VALUE - lastScanOffset)) {
            // integer overflow
            throw new RasterFormatException("Incorrect raster attributes");
        }
        lastPixelOffset += lastScanOffset;

        for (int i = 0; i < numDataElements; i++) {
            size = lastPixelOffset + dataOffsets[i];
            if (dataOffsets[i] > (Integer.MAX_VALUE - lastPixelOffset)) {
                throw new RasterFormatException("Incorrect band offset: " + dataOffsets[i]);
            }
            if (size > maxSize) {
                maxSize = size;
            }
        }
        if (data.length < maxSize) {
            throw new RasterFormatException("Data array too small (should be " + maxSize + " )");
        }
    }   

Thereafter all raster's parameters can be stored internally by the native 
Java_sun_awt_image_BufImgSurfaceData_initRaster() function:

    // sun.awt.image.BufImgSurfaceData
    public static SurfaceData createDataBC(BufferedImage bImg,
                                           SurfaceType sType,
                                           int primaryBank) {
        ByteComponentRaster bcRaster =
            (ByteComponentRaster)bImg.getRaster();
        BufImgSurfaceData bisd =
            new BufImgSurfaceData(bcRaster.getDataBuffer(), bImg, sType);
        ColorModel cm = bImg.getColorModel();
        IndexColorModel icm = ((cm instanceof IndexColorModel)
                               ? (IndexColorModel) cm
                               : null);
        bisd.initRaster(bcRaster.getDataStorage(),
                        bcRaster.getDataOffset(primaryBank), 0,
                        bcRaster.getWidth(),
                        bcRaster.getHeight(),
                        bcRaster.getPixelStride(),
                        bcRaster.getScanlineStride(),
                        icm);
        return bisd;
    }

The memory corruption occurs later when the stored "dataOffset" value will be 
used by the native code.


III. ANALYSIS

This vulnerability allows remote attackers to execute arbitrary code on vulnerable 
installations of Oracle Java. User interaction is required to exploit this 
vulnerability in that the target must visit a malicious page or open a malicious file.



IV. DETECTION
Oracle Java SE 6u43, 7u17
