8005126: [parfait] #418 - #428 XRBackendNative.c Integer overflow
authorjchen
Wed, 24 Jul 2013 13:05:03 -0700
changeset 19009 1f1914231324
parent 19008 f013dabb0bf8
child 19010 8148c141f16e
8005126: [parfait] #418 - #428 XRBackendNative.c Integer overflow Reviewed-by: prr, vadim
jdk/src/solaris/native/sun/java2d/x11/XRBackendNative.c
--- a/jdk/src/solaris/native/sun/java2d/x11/XRBackendNative.c	Wed Jul 24 12:40:26 2013 -0700
+++ b/jdk/src/solaris/native/sun/java2d/x11/XRBackendNative.c	Wed Jul 24 13:05:03 2013 -0700
@@ -112,6 +112,25 @@
 #define PKGINFO_LINE_LEN_MAX 256
 #define PKGINFO_LINE_CNT_MAX 50
 
+/*
+ * X protocol uses (u_int16)length to specify the length in 4 bytes quantities
+ * of the whole request.  Both XRenderFillRectangles() and XFillRectangles()
+ * have provisions to fragment into several requests if the number of rectangles
+ * plus the current x request does not fit into 65535*4 bytes.  While
+ * XRenderCreateLinearGradient() and XRenderCreateRadialGradient() have
+ * provisions to gracefully degrade if the resulting request would exceed
+ * 65535*4 bytes.
+ *
+ * Below, we define a cap of 65535*4 bytes for the maximum X request payload
+ * allowed for Non-(XRenderFillRectangles() or XFillRectangles()) API calls,
+ * just to be conservative.  This is offset by the size of our maximum x*Req
+ * type in this compilation unit, which is xRenderCreateRadiaGradientReq.
+ *
+ * Note that sizeof(xRenderCreateRadiaGradientReq) = 36
+ */
+#define MAX_PAYLOAD (262140u - 36u)
+#define MAXUINT (0xffffffffu)
+
 static jboolean IsXRenderAvailable(jboolean verbose) {
 
     void *xrenderlib;
@@ -410,6 +429,10 @@
     if (rectCnt <= 256) {
         xRects = &sRects[0];
     } else {
+        if (MAXUINT / sizeof(XRectangle) < (unsigned)rectCnt) {
+            /* rectCnt too big, integer overflow */
+            return;
+        }
         xRects = (XRectangle *) malloc(sizeof(XRectangle) * rectCnt);
         if (xRects == NULL) {
             return;
@@ -466,6 +489,12 @@
    XFixed *stops;
    XLinearGradient grad;
 
+   if (MAX_PAYLOAD / (sizeof(XRenderColor) + sizeof(XFixed))
+       < (unsigned)numStops) {
+       /* numStops too big, payload overflow */
+       return -1;
+   }
+
    if ((pixels = (jshort *)
         (*env)->GetPrimitiveArrayCritical(env, pixelsArray, NULL)) == NULL) {
        return -1;
@@ -486,6 +515,18 @@
     colors = (XRenderColor *) malloc(numStops * sizeof(XRenderColor));
     stops =  (XFixed *) malloc(numStops * sizeof(XFixed));
 
+    if (colors == NULL || stops == NULL) {
+        if (colors != NULL) {
+            free(colors);
+        }
+        if (stops != NULL) {
+            free(stops);
+        }
+        (*env)->ReleasePrimitiveArrayCritical(env, pixelsArray, pixels, JNI_ABORT);
+        (*env)->ReleasePrimitiveArrayCritical(env, fractionsArray, fractions, JNI_ABORT);
+        return -1;
+    }
+
     for (i=0; i < numStops; i++) {
       stops[i] = XDoubleToFixed(fractions[i]);
       colors[i].alpha = pixels[i*4 + 0];
@@ -533,6 +574,11 @@
    XFixed *stops;
    XRadialGradient grad;
 
+   if (MAX_PAYLOAD / (sizeof(XRenderColor) + sizeof(XFixed))
+       < (unsigned)numStops) {
+       /* numStops too big, payload overflow */
+       return -1;
+   }
 
    if ((pixels =
        (jshort *)(*env)->GetPrimitiveArrayCritical(env, pixelsArray, NULL)) == NULL) {
@@ -556,6 +602,18 @@
     colors = (XRenderColor *) malloc(numStops * sizeof(XRenderColor));
     stops =  (XFixed *) malloc(numStops * sizeof(XFixed));
 
+    if (colors == NULL || stops == NULL) {
+        if (colors != NULL) {
+            free(colors);
+        }
+        if (stops != NULL) {
+            free(stops);
+        }
+        (*env)->ReleasePrimitiveArrayCritical(env, pixelsArray, pixels, JNI_ABORT);
+        (*env)->ReleasePrimitiveArrayCritical(env, fractionsArray, fractions, JNI_ABORT);
+        return -1;
+    }
+
     for (i=0; i < numStops; i++) {
       stops[i] = XDoubleToFixed(fractions[i]);
       colors[i].alpha = pixels[i*4 + 0];
@@ -714,6 +772,12 @@
     unsigned char *pixelData;
     int i;
 
+    if (MAX_PAYLOAD / (sizeof(XGlyphInfo) + sizeof(Glyph))
+        < (unsigned)glyphCnt) {
+        /* glyphCnt too big, payload overflow */
+        return;
+    }
+
     XGlyphInfo *xginfo = (XGlyphInfo *) malloc(sizeof(XGlyphInfo) * glyphCnt);
     Glyph *gid = (Glyph *) malloc(sizeof(Glyph) * glyphCnt);
 
@@ -776,6 +840,11 @@
 Java_sun_java2d_xr_XRBackendNative_XRFreeGlyphsNative
  (JNIEnv *env, jclass cls, jint glyphSet, jintArray gidArray, jint glyphCnt) {
 
+    if (MAX_PAYLOAD / sizeof(Glyph) < (unsigned)glyphCnt) {
+        /* glyphCnt too big, payload overflow */
+        return;
+    }
+
     /* The glyph ids are 32 bit but may be stored in a 64 bit long on
      * a 64 bit architecture. So optimise the 32 bit case to avoid
      * extra stack or heap allocations by directly referencing the
@@ -846,6 +915,15 @@
     unsigned int sids[256];
     int charCnt = 0;
 
+    if ((MAX_PAYLOAD / sizeof(XGlyphElt32) < (unsigned)eltCnt)
+        || (MAX_PAYLOAD / sizeof(unsigned int) < (unsigned)glyphCnt)
+        || ((MAX_PAYLOAD - sizeof(XGlyphElt32)*(unsigned)eltCnt) /
+            sizeof(unsigned int) < (unsigned)glyphCnt))
+    {
+        /* (eltCnt, glyphCnt) too big, payload overflow */
+        return;
+    }
+
     if (eltCnt <= 24) {
       xelts = &selts[0];
     }else {
@@ -944,6 +1022,11 @@
     if (rectCnt <= 256) {
       xRects = &sRects[0];
     } else {
+      if (MAXUINT / sizeof(XRectangle) < (unsigned)rectCnt) {
+        /* rectCnt too big, integer overflow */
+        return;
+      }
+
       xRects = (XRectangle *) malloc(sizeof(XRectangle) * rectCnt);
       if (xRects == NULL) {
         return;