diff src/share/native/sun/awt/image/awt_parseImage.c @ 6381:2a9c79db0040

8012597: Better image channel verification Reviewed-by: ahgross, vadim, prr
author bae
date Tue, 30 Apr 2013 04:20:46 +0400
parents 0dcf8ad3e63d
children 26edfc8182bb
line wrap: on
line diff
--- a/src/share/native/sun/awt/image/awt_parseImage.c	Tue Apr 30 12:25:32 2013 -0700
+++ b/src/share/native/sun/awt/image/awt_parseImage.c	Tue Apr 30 04:20:46 2013 +0400
@@ -396,10 +396,39 @@
     return 1;
 }
 
+static int getColorModelType(JNIEnv *env, jobject jcmodel) {
+    int type = UNKNOWN_CM_TYPE;
+
+    if ((*env)->IsInstanceOf(env, jcmodel,
+                 (*env)->FindClass(env, "java/awt/image/IndexColorModel")))
+    {
+        type = INDEX_CM_TYPE;
+    } else if ((*env)->IsInstanceOf(env, jcmodel,
+                 (*env)->FindClass(env, "java/awt/image/PackedColorModel")))
+    {
+        if  ((*env)->IsInstanceOf(env, jcmodel,
+                (*env)->FindClass(env, "java/awt/image/DirectColorModel"))) {
+            type = DIRECT_CM_TYPE;
+        }
+        else {
+            type = PACKED_CM_TYPE;
+        }
+    }
+    else if ((*env)->IsInstanceOf(env, jcmodel,
+                 (*env)->FindClass(env, "java/awt/image/ComponentColorModel")))
+    {
+        type = COMPONENT_CM_TYPE;
+    }
+
+    return type;
+}
+
 int awt_parseColorModel (JNIEnv *env, jobject jcmodel, int imageType,
                          ColorModelS_t *cmP) {
     /*jmethodID jID;   */
     jobject jnBits;
+    jsize   nBitsLength;
+
     int i;
     static jobject s_jdefCM = NULL;
 
@@ -421,15 +450,55 @@
     cmP->transparency = (*env)->GetIntField(env, jcmodel,
                                             g_CMtransparencyID);
 
+    jnBits = (*env)->GetObjectField(env, jcmodel, g_CMnBitsID);
+    if (jnBits == NULL) {
+        JNU_ThrowNullPointerException(env, "null nBits structure in CModel");
+        return -1;
+    }
+
+    nBitsLength = (*env)->GetArrayLength(env, jnBits);
+    if (nBitsLength != cmP->numComponents) {
+        // invalid number of components?
+        return -1;
+    }
+
+    cmP->nBits = NULL;
+    if (SAFE_TO_ALLOC_2(cmP->numComponents, sizeof(jint))) {
+        cmP->nBits = (jint *)malloc(cmP->numComponents * sizeof(jint));
+    }
+
+    if (cmP->nBits == NULL){
+        JNU_ThrowOutOfMemoryError(env, "Out of memory");
+        return -1;
+    }
+    (*env)->GetIntArrayRegion(env, jnBits, 0, cmP->numComponents,
+                              cmP->nBits);
+    cmP->maxNbits = 0;
+    for (i=0; i < cmP->numComponents; i++) {
+        if (cmP->maxNbits < cmP->nBits[i]) {
+            cmP->maxNbits = cmP->nBits[i];
+        }
+    }
+
+    cmP->is_sRGB = (*env)->GetBooleanField(env, cmP->jcmodel, g_CMis_sRGBID);
+
+    cmP->csType = (*env)->GetIntField(env, cmP->jcmodel, g_CMcsTypeID);
+
+    cmP->cmType = getColorModelType(env, jcmodel);
+
+    cmP->isDefaultCM = FALSE;
+    cmP->isDefaultCompatCM = FALSE;
+
+    /* look for standard cases */
     if (imageType == java_awt_image_BufferedImage_TYPE_INT_ARGB) {
         cmP->isDefaultCM = TRUE;
         cmP->isDefaultCompatCM = TRUE;
     } else if (imageType == java_awt_image_BufferedImage_TYPE_INT_ARGB_PRE ||
-             imageType == java_awt_image_BufferedImage_TYPE_INT_RGB) {
-        cmP->isDefaultCompatCM = TRUE;
-    } else if (imageType == java_awt_image_BufferedImage_TYPE_INT_BGR ||
+               imageType == java_awt_image_BufferedImage_TYPE_INT_RGB ||
+               imageType == java_awt_image_BufferedImage_TYPE_INT_BGR ||
                imageType == java_awt_image_BufferedImage_TYPE_4BYTE_ABGR ||
-               imageType == java_awt_image_BufferedImage_TYPE_4BYTE_ABGR_PRE){
+               imageType == java_awt_image_BufferedImage_TYPE_4BYTE_ABGR_PRE)
+    {
         cmP->isDefaultCompatCM = TRUE;
     }
     else {
@@ -450,50 +519,25 @@
         cmP->isDefaultCompatCM = cmP->isDefaultCM;
     }
 
+    /* check whether image attributes correspond to default cm */
     if (cmP->isDefaultCompatCM) {
-        cmP->cmType = DIRECT_CM_TYPE;
-        cmP->nBits = (jint *) malloc(sizeof(jint)*4);
-        cmP->nBits[0] = cmP->nBits[1] = cmP->nBits[2] = cmP->nBits[3] = 8;
-        cmP->maxNbits = 8;
-        cmP->is_sRGB = TRUE;
-        cmP->csType  = java_awt_color_ColorSpace_TYPE_RGB;
+        if (cmP->csType != java_awt_color_ColorSpace_TYPE_RGB ||
+            !cmP->is_sRGB)
+        {
+            return -1;
+        }
 
-        return 1;
-    }
-
-    jnBits = (*env)->GetObjectField(env, jcmodel, g_CMnBitsID);
-    if (jnBits == NULL) {
-        JNU_ThrowNullPointerException(env, "null nBits structure in CModel");
-        return -1;
-    }
-
-    cmP->nBits = NULL;
-    if (SAFE_TO_ALLOC_2(cmP->numComponents, sizeof(jint))) {
-        cmP->nBits = (jint *)malloc(cmP->numComponents * sizeof(jint));
-    }
-    if (cmP->nBits == NULL){
-        JNU_ThrowOutOfMemoryError(env, "Out of memory");
-        return -1;
-    }
-    (*env)->GetIntArrayRegion(env, jnBits, 0, cmP->numComponents,
-                              cmP->nBits);
-    cmP->maxNbits = 0;
-    for (i=0; i < cmP->numComponents; i++) {
-        if (cmP->maxNbits < cmP->nBits[i]) {
-            cmP->maxNbits = cmP->nBits[i];
+        for (i = 0; i < cmP->numComponents; i++) {
+            if (cmP->nBits[i] != 8) {
+                return -1;
+            }
         }
     }
 
-    cmP->is_sRGB = (*env)->GetBooleanField(env, cmP->jcmodel, g_CMis_sRGBID);
-
-    cmP->csType = (*env)->GetIntField(env, cmP->jcmodel, g_CMcsTypeID);
-
-    /* Find out what type of colol model */
+    /* Get index color model attributes */
     if (imageType == java_awt_image_BufferedImage_TYPE_BYTE_INDEXED ||
-        (*env)->IsInstanceOf(env, jcmodel,
-                 (*env)->FindClass(env, "java/awt/image/IndexColorModel")))
+        cmP->cmType == INDEX_CM_TYPE)
     {
-        cmP->cmType = INDEX_CM_TYPE;
         cmP->transIdx = (*env)->GetIntField(env, jcmodel, g_ICMtransIdxID);
         cmP->mapSize = (*env)->GetIntField(env, jcmodel, g_ICMmapSizeID);
         cmP->jrgb    = (*env)->GetObjectField(env, jcmodel, g_ICMrgbID);
@@ -519,31 +563,6 @@
             }
         }
     }
-    else if ((*env)->IsInstanceOf(env, jcmodel,
-                 (*env)->FindClass(env, "java/awt/image/PackedColorModel")))
-    {
-        if  ((*env)->IsInstanceOf(env, jcmodel,
-                (*env)->FindClass(env, "java/awt/image/DirectColorModel"))){
-            cmP->cmType = DIRECT_CM_TYPE;
-        }
-        else {
-            cmP->cmType = PACKED_CM_TYPE;
-        }
-    }
-    else if ((*env)->IsInstanceOf(env, jcmodel,
-                 (*env)->FindClass(env, "java/awt/image/ComponentColorModel")))
-    {
-        cmP->cmType = COMPONENT_CM_TYPE;
-    }
-    else if ((*env)->IsInstanceOf(env, jcmodel,
-              (*env)->FindClass(env, "java/awt/image/PackedColorModel")))
-    {
-        cmP->cmType = PACKED_CM_TYPE;
-    }
-    else {
-        cmP->cmType = UNKNOWN_CM_TYPE;
-    }
-
 
     return 1;
 }
@@ -583,6 +602,13 @@
     ColorModelS_t *cmodelP = &imageP->cmodel;
     int imageType = imageP->imageType;
 
+    // check whether raster and color model are compatible
+    if (cmodelP->numComponents != rasterP->numBands) {
+        if (cmodelP->cmType != INDEX_CM_TYPE) {
+            return -1;
+        }
+    }
+
     hintP->numChans = imageP->cmodel.numComponents;
     hintP->colorOrder = NULL;
     if (SAFE_TO_ALLOC_2(hintP->numChans, sizeof(int))) {
@@ -1074,6 +1100,10 @@
     jsm = (*env)->GetObjectField(env, rasterP->jraster, g_RasterSampleModelID);
     jdatabuffer = (*env)->GetObjectField(env, rasterP->jraster,
                                          g_RasterDataBufferID);
+    if (band >= numBands) {
+        JNU_ThrowInternalError(env, "Band out of range.");
+        return -1;
+    }
     /* Here is the generic code */
     jdata = (*env)->NewIntArray(env, maxBytes*rasterP->numBands*maxLines);
     if (JNU_IsNull(env, jdata)) {
@@ -1082,11 +1112,6 @@
     }
     if (band >= 0) {
         int dOff;
-        if (band >= numBands) {
-            (*env)->DeleteLocalRef(env, jdata);
-            JNU_ThrowInternalError(env, "Band out of range.");
-            return -1;
-        }
         off = 0;
         for (y=0; y < h; y+=maxLines) {
             if (y+maxLines > h) {