changeset 433:9242f7e22b5d

6963023: ZDI-CAN-809: Sun JRE JPEGImageWriter.writeImage Remote Code Execution Vulnerability Reviewed-by: prr
author bae
date Wed, 30 Jun 2010 11:15:38 +0400
parents 28503855a149
children 34dd517c7183
files src/share/native/sun/awt/image/jpeg/imageioJPEG.c
diffstat 1 files changed, 18 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/native/sun/awt/image/jpeg/imageioJPEG.c	Mon Jun 28 15:10:58 2010 -0700
+++ b/src/share/native/sun/awt/image/jpeg/imageioJPEG.c	Wed Jun 30 11:15:38 2010 +0400
@@ -2619,7 +2619,8 @@
     JSAMPROW scanLinePtr;
     int i, j;
     int pixelStride;
-    unsigned char *in, *out, *pixelLimit;
+    unsigned char *in, *out, *pixelLimit, *scanLineLimit;
+    unsigned int scanLineSize, pixelBufferSize;
     int targetLine;
     pixelBufferPtr pb;
     sun_jpeg_error_ptr jerr;
@@ -2655,19 +2656,25 @@
 
     }
 
+    scanLineSize = destWidth * numBands;
     if ((inCs < 0) || (inCs > JCS_YCCK) ||
         (outCs < 0) || (outCs > JCS_YCCK) ||
         (numBands < 1) || (numBands > MAX_BANDS) ||
         (srcWidth < 0) ||
         (destWidth < 0) || (destWidth > srcWidth) ||
         (destHeight < 0) ||
-        (stepX < 0) || (stepY < 0))
+        (stepX < 0) || (stepY < 0) ||
+        ((scanLineSize / numBands) < destWidth))  /* destWidth causes an integer overflow */
     {
         JNU_ThrowByName(env, "javax/imageio/IIOException",
                         "Invalid argument to native writeImage");
         return JNI_FALSE;
     }
 
+    if (stepX > srcWidth) {
+        stepX = srcWidth;
+    }
+
     bandSize = (*env)->GetIntArrayElements(env, bandSizes, NULL);
 
     for (i = 0; i < numBands; i++) {
@@ -2707,7 +2714,7 @@
     }
 
     // Allocate a 1-scanline buffer
-    scanLinePtr = (JSAMPROW)malloc(destWidth*numBands);
+    scanLinePtr = (JSAMPROW)malloc(scanLineSize);
     if (scanLinePtr == NULL) {
         RELEASE_ARRAYS(env, data, (const JOCTET *)(dest->next_output_byte));
         JNU_ThrowByName( env,
@@ -2715,6 +2722,7 @@
                          "Writing JPEG Stream");
         return data->abortFlag;
     }
+    scanLineLimit = scanLinePtr + scanLineSize;
 
     /* Establish the setjmp return context for sun_jpeg_error_exit to use. */
     jerr = (sun_jpeg_error_ptr) cinfo->err;
@@ -2863,6 +2871,8 @@
     }
 
     targetLine = 0;
+    pixelBufferSize = srcWidth * numBands;
+    pixelStride = numBands * stepX;
 
     // for each line in destHeight
     while ((data->abortFlag == JNI_FALSE)
@@ -2883,10 +2893,10 @@
 
         in = data->pixelBuf.buf.bp;
         out = scanLinePtr;
-        pixelLimit = in + srcWidth*numBands;
-        pixelStride = numBands*stepX;
+        pixelLimit = in + ((pixelBufferSize > data->pixelBuf.byteBufferLength) ?
+                           data->pixelBuf.byteBufferLength : pixelBufferSize);
         if (mustScale) {
-            for (; in < pixelLimit; in += pixelStride) {
+          for (; (in < pixelLimit) && (out < scanLineLimit); in += pixelStride) {
                 for (i = 0; i < numBands; i++) {
                     *out++ = data->scale[i][*(in+i)];
 #ifdef DEBUG
@@ -2902,11 +2912,11 @@
 #endif
             }
         } else {
-            for (; in < pixelLimit; in += pixelStride) {
+          for (; (in < pixelLimit) && (out < scanLineLimit); in += pixelStride) {
                 for (i = 0; i < numBands; i++) {
                     *out++ = *(in+i);
                 }
-            }
+          }
         }
         // write it out
         jpeg_write_scanlines(cinfo, (JSAMPARRAY)&scanLinePtr, 1);