diff -Nru openjdk.orig/jdk/src/share/classes/sun/awt/image/ByteComponentRaster.java openjdk/jdk/src/share/classes/sun/awt/image/ByteComponentRaster.java --- openjdk.orig/jdk/src/share/classes/sun/awt/image/ByteComponentRaster.java 2011-11-14 22:11:59.000000000 +0000 +++ jdk/src/share/classes/sun/awt/image/ByteComponentRaster.java 2013-02-01 21:49:28.911324533 +0000 @@ -198,7 +198,7 @@ } this.bandOffset = this.dataOffsets[0]; - verify(false); + verify(); } /** @@ -857,38 +857,68 @@ } /** - * Verify that the layout parameters are consistent with - * the data. If strictCheck - * is false, this method will check for ArrayIndexOutOfBounds conditions. If - * strictCheck is true, this method will check for additional error - * conditions such as line wraparound (width of a line greater than - * the scanline stride). - * @return String Error string, if the layout is incompatible with - * the data. Otherwise returns null. - */ - private void verify (boolean strictCheck) { - // Make sure data for Raster is in a legal range - for (int i=0; i < dataOffsets.length; i++) { + * Verify that the layout parameters are consistent with the data. + * + * The method verifies whether scanline stride and pixel stride do not + * cause an integer overflow during calculation of a position of the pixel + * in data buffer. It also verifies whether the data buffer has enough data + * to correspond the raster layout attributes. + * + * @throws RasterFormatException if an integer overflow is detected, + * or if data buffer has not enough capacity. + */ + 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"); + throw new RasterFormatException("Data offsets for band " + i + + "(" + dataOffsets[i] + + ") must be >= 0"); } } int maxSize = 0; int size; - for (int i=0; i < numDataElements; i++) { - size = (height-1)*scanlineStride + (width-1)*pixelStride + - dataOffsets[i]; + // 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+" )"); + throw new RasterFormatException("Data array too small (should be " + + maxSize + " )"); } } diff -Nru openjdk.orig/jdk/src/share/classes/sun/awt/image/ByteInterleavedRaster.java openjdk/jdk/src/share/classes/sun/awt/image/ByteInterleavedRaster.java --- openjdk.orig/jdk/src/share/classes/sun/awt/image/ByteInterleavedRaster.java 2011-11-14 22:11:59.000000000 +0000 +++ jdk/src/share/classes/sun/awt/image/ByteInterleavedRaster.java 2013-02-01 21:49:28.911324533 +0000 @@ -250,7 +250,7 @@ } } - verify(false); + verify(); } /** @@ -1292,33 +1292,6 @@ return createCompatibleWritableRaster(width,height); } - /** - * Verify that the layout parameters are consistent with - * the data. If strictCheck - * is false, this method will check for ArrayIndexOutOfBounds conditions. If - * strictCheck is true, this method will check for additional error - * conditions such as line wraparound (width of a line greater than - * the scanline stride). - * @return String Error string, if the layout is incompatible with - * the data. Otherwise returns null. - */ - private void verify (boolean strictCheck) { - int maxSize = 0; - int size; - - for (int i=0; i < numDataElements; i++) { - size = (height-1)*scanlineStride + (width-1)*pixelStride + - dataOffsets[i]; - if (size > maxSize) { - maxSize = size; - } - } - if (data.length < maxSize) { - throw new RasterFormatException("Data array too small (should be "+ - maxSize+" )"); - } - } - public String toString() { return new String ("ByteInterleavedRaster: width = "+width+" height = " + height diff -Nru openjdk.orig/jdk/src/share/classes/sun/awt/image/ShortComponentRaster.java openjdk/jdk/src/share/classes/sun/awt/image/ShortComponentRaster.java --- openjdk.orig/jdk/src/share/classes/sun/awt/image/ShortComponentRaster.java 2011-11-14 22:11:59.000000000 +0000 +++ jdk/src/share/classes/sun/awt/image/ShortComponentRaster.java 2013-02-01 21:49:28.911324533 +0000 @@ -198,7 +198,7 @@ } this.bandOffset = this.dataOffsets[0]; - verify(false); + verify(); } /** @@ -791,38 +791,67 @@ } /** - * Verify that the layout parameters are consistent with - * the data. If strictCheck - * is false, this method will check for ArrayIndexOutOfBounds conditions. If - * strictCheck is true, this method will check for additional error - * conditions such as line wraparound (width of a line greater than - * the scanline stride). - * @return String Error string, if the layout is incompatible with - * the data. Otherwise returns null. - */ - private void verify (boolean strictCheck) { - // Make sure data for Raster is in a legal range - for (int i=0; i < dataOffsets.length; i++) { + * Verify that the layout parameters are consistent with the data. + * + * The method verifies whether scanline stride and pixel stride do not + * cause an integer overflow during calculation of a position of the pixel + * in data buffer. It also verifies whether the data buffer has enough data + * to correspond the raster layout attributes. + * + * @throws RasterFormatException if an integer overflow is detected, + * or if data buffer has not enough capacity. + */ + 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"); + throw new RasterFormatException("Data offsets for band " + i + + "(" + dataOffsets[i] + + ") must be >= 0"); } } int maxSize = 0; int size; - for (int i=0; i < numDataElements; i++) { - size = (height-1)*scanlineStride + (width-1)*pixelStride + - dataOffsets[i]; + // 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+" )"); + throw new RasterFormatException("Data array too small (should be " + + maxSize + " )"); } } diff -Nru openjdk.orig/jdk/src/share/classes/sun/awt/image/ShortInterleavedRaster.java openjdk/jdk/src/share/classes/sun/awt/image/ShortInterleavedRaster.java --- openjdk.orig/jdk/src/share/classes/sun/awt/image/ShortInterleavedRaster.java 2011-11-14 22:11:59.000000000 +0000 +++ jdk/src/share/classes/sun/awt/image/ShortInterleavedRaster.java 2013-02-01 21:49:28.911324533 +0000 @@ -171,7 +171,7 @@ sampleModel); } this.bandOffset = this.dataOffsets[0]; - verify(false); + verify(); } /** @@ -762,33 +762,6 @@ return createCompatibleWritableRaster(width,height); } - /** - * Verify that the layout parameters are consistent with - * the data. If strictCheck - * is false, this method will check for ArrayIndexOutOfBounds conditions. If - * strictCheck is true, this method will check for additional error - * conditions such as line wraparound (width of a line greater than - * the scanline stride). - * @return String Error string, if the layout is incompatible with - * the data. Otherwise returns null. - */ - private void verify (boolean strictCheck) { - int maxSize = 0; - int size; - - for (int i=0; i < numDataElements; i++) { - size = (height-1)*scanlineStride + (width-1)*pixelStride + - dataOffsets[i]; - if (size > maxSize) { - maxSize = size; - } - } - if (data.length < maxSize) { - throw new RasterFormatException("Data array too small (should be "+ - maxSize+" )"); - } - } - public String toString() { return new String ("ShortInterleavedRaster: width = "+width +" height = " + height diff -Nru openjdk.orig/jdk/src/share/native/sun/awt/image/awt_parseImage.c openjdk/jdk/src/share/native/sun/awt/image/awt_parseImage.c --- openjdk.orig/jdk/src/share/native/sun/awt/image/awt_parseImage.c 2011-11-14 22:12:11.000000000 +0000 +++ jdk/src/share/native/sun/awt/image/awt_parseImage.c 2013-02-01 21:54:40.100132273 +0000 @@ -114,6 +114,62 @@ return status; } +/* Verifies whether the channel offsets are sane and correspond to the type of + * the raster. + * + * Return value: + * 0: Failure: channel offsets are invalid + * 1: Success + */ +static int checkChannelOffsets(RasterS_t *rasterP, int dataArrayLength) { + int i, lastPixelOffset, lastScanOffset; + switch (rasterP->rasterType) { + case COMPONENT_RASTER_TYPE: + if (!SAFE_TO_MULT(rasterP->height, rasterP->scanlineStride)) { + return 0; + } + if (!SAFE_TO_MULT(rasterP->width, rasterP->pixelStride)) { + return 0; + } + + lastScanOffset = (rasterP->height - 1) * rasterP->scanlineStride; + lastPixelOffset = (rasterP->width - 1) * rasterP->pixelStride; + + + if (!SAFE_TO_ADD(lastPixelOffset, lastScanOffset)) { + return 0; + } + + lastPixelOffset += lastScanOffset; + + for (i = 0; i < rasterP->numDataElements; i++) { + int off = rasterP->chanOffsets[i]; + int size = lastPixelOffset + off; + + if (off < 0 || !SAFE_TO_ADD(lastPixelOffset, off)) { + return 0; + } + + if (size < lastPixelOffset || size >= dataArrayLength) { + // an overflow, or insufficient buffer capacity + return 0; + } + } + return 1; + case BANDED_RASTER_TYPE: + // NB:caller does not support the banded rasters yet, + // so this branch of the code must be re-defined in + // order to provide valid criteria for the data offsets + // verification, when/if banded rasters will be supported. + // At the moment, we prohibit banded rasters as well. + return 0; + default: + // PACKED_RASTER_TYPE: does not support channel offsets + // UNKNOWN_RASTER_TYPE: should not be used, likely indicates an error + return 0; + } +} + /* Parse the raster. All of the raster information is returned in the * rasterP structure. * @@ -125,7 +181,6 @@ int awt_parseRaster(JNIEnv *env, jobject jraster, RasterS_t *rasterP) { jobject joffs = NULL; /* int status;*/ - int isDiscrete = TRUE; if (JNU_IsNull(env, jraster)) { JNU_ThrowNullPointerException(env, "null Raster object"); @@ -155,6 +210,9 @@ return -1; } + // make sure that the raster type is initialized + rasterP->rasterType = UNKNOWN_RASTER_TYPE; + if (rasterP->numBands <= 0 || rasterP->numBands > MAX_NUMBANDS) { @@ -254,7 +312,6 @@ } rasterP->chanOffsets[0] = (*env)->GetIntField(env, jraster, g_BPRdataBitOffsetID); rasterP->dataType = BYTE_DATA_TYPE; - isDiscrete = FALSE; } else { rasterP->type = sun_awt_image_IntegerComponentRaster_TYPE_CUSTOM; @@ -265,7 +322,19 @@ return 0; } - if (isDiscrete) { + // do basic validation of the raster structure + if (rasterP->width <= 0 || rasterP->height <= 0 || + rasterP->pixelStride <= 0 || rasterP->scanlineStride <= 0) + { + // invalid raster + return -1; + } + + // channel (data) offsets + switch (rasterP->rasterType) { + case COMPONENT_RASTER_TYPE: + case BANDED_RASTER_TYPE: // note that this routine does not support banded rasters at the moment + // get channel (data) offsets rasterP->chanOffsets = NULL; if (SAFE_TO_ALLOC_2(rasterP->numDataElements, sizeof(jint))) { rasterP->chanOffsets = @@ -278,6 +347,17 @@ } (*env)->GetIntArrayRegion(env, joffs, 0, rasterP->numDataElements, rasterP->chanOffsets); + if (rasterP->jdata == NULL) { + // unable to verify the raster + return -1; + } + // verify whether channel offsets look sane + if (!checkChannelOffsets(rasterP, (*env)->GetArrayLength(env, rasterP->jdata))) { + return -1; + } + break; + default: + ; // PACKED_RASTER_TYPE does not use the channel offsets. } #if 0 diff -Nru openjdk.orig/jdk/src/share/native/sun/awt/medialib/safe_alloc.h openjdk/jdk/src/share/native/sun/awt/medialib/safe_alloc.h --- openjdk.orig/jdk/src/share/native/sun/awt/medialib/safe_alloc.h 2011-11-14 22:12:12.000000000 +0000 +++ jdk/src/share/native/sun/awt/medialib/safe_alloc.h 2013-02-01 21:49:28.911324533 +0000 @@ -41,5 +41,10 @@ (((w) > 0) && ((h) > 0) && ((sz) > 0) && \ (((0xffffffffu / ((juint)(w))) / ((juint)(h))) > ((juint)(sz)))) +#define SAFE_TO_MULT(a, b) \ + (((a) > 0) && ((b) >= 0) && ((0x7fffffff / (a)) > (b))) + +#define SAFE_TO_ADD(a, b) \ + (((a) >= 0) && ((b) >= 0) && ((0x7fffffff - (a)) > (b))) #endif // __SAFE_ALLOC_H__