view patches/openjdk/6791502-invalid_icc_profile.patch @ 2929:222321136c48

Backport a number of JPEG fixes from 7u. S4893408: JPEGReader throws IllegalArgException when setting the destination to BYTE_GRAY S6631559: Registration of ImageIO plugins should not cause loading of jpeg.dlli and cmm.dll S6791502: IIOException "Invalid icc profile" on jpeg after update from JDK5 to JDK6 S6793818: JpegImageReader is too greedy creating color profiles S6888215: memory leak in jpeg plugin S6989760: cmm native compiler warnings S6989774: imageio compiler warnings in native code S7013519: [parfait] Integer overflows in 2D code S7018912: [parfait] potential buffer overruns in imageio jpeg S8005194: [parfait] #353 sun/awt/image/jpeg/imageioJPEG.c Memory leak of pointer 'scale' allocated with calloc() S8020983, RH976897: OutOfMemoryError caused by non garbage collected JPEGImageWriter Instances 2013-08-30 Andrew John Hughes <gnu.andrew@redhat.com> * Makefile.am: (ICEDTEA_PATCHES): Add new patches. * NEWS: Updated with new patches. * patches/imageiojpeg_sync.patch: Bring in changes to imageioJPEG.c made between the start of OpenJDK 6 and the start of OpenJDK 7's hg repositories. * patches/libraries.patch: Updated against patches below. * patches/openjdk/4893408-jpegreader_byte_gray.patch, * patches/openjdk/6631559-dont_load_libjpeg_to_register_imageio_plugins.patch, * patches/openjdk/6791502-invalid_icc_profile.patch, * patches/openjdk/6793818-jpegimagereader_too_greedy.patch, * patches/openjdk/6888215-jpeg_memory_leak.patch, * patches/openjdk/6989760-native_warnings.patch, * patches/openjdk/6989774-imageio_compiler_warnings.patch, * patches/openjdk/7013519-integer_overflows.patch, * patches/openjdk/7018912-potential_buffer_overruns_in_jpeg.patch, * patches/openjdk/8005194-scale_memory_leak.patch, * patches/openjdk/8020983-outofmemoryerror_jpegimagewriter.patch: New backports from OpenJDK 7u.
author Andrew John Hughes <gnu.andrew@redhat.com>
date Tue, 03 Sep 2013 20:08:26 +0100
parents
children
line wrap: on
line source

diff -Nru openjdk.orig/jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c openjdk/jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c
--- openjdk.orig/jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c	2013-08-30 15:28:52.333056323 +0100
+++ openjdk/jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c	2013-08-30 15:31:17.627316140 +0100
@@ -403,7 +403,7 @@
     data->jpegObj = cinfo;
     cinfo->client_data = data;
 
-#ifdef DEBUG
+#ifdef DEBUG_IIO_JPEG
     printf("new structures: data is %p, cinfo is %p\n", data, cinfo);
 #endif
 
@@ -686,7 +686,7 @@
     j_decompress_ptr decomp;
 
     qlen = (*env)->GetArrayLength(env, qtables);
-#ifdef DEBUG
+#ifdef DEBUG_IIO_JPEG
     printf("in setQTables, qlen = %d, write is %d\n", qlen, write);
 #endif
     if (qlen > NUM_QUANT_TBLS) {
@@ -912,7 +912,7 @@
         return FALSE;
     }
 
-#ifdef DEBUG
+#ifdef DEBUG_IIO_JPEG
     printf("Filling input buffer, remaining skip is %ld, ",
            sb->remaining_skip);
     printf("Buffer length is %d\n", sb->bufferLength);
@@ -942,7 +942,7 @@
             cinfo->err->error_exit((j_common_ptr) cinfo);
     }
 
-#ifdef DEBUG
+#ifdef DEBUG_IIO_JPEG
       printf("Buffer filled. ret = %d\n", ret);
 #endif
     /*
@@ -953,7 +953,7 @@
      */
     if (ret <= 0) {
         jobject reader = data->imageIOobj;
-#ifdef DEBUG
+#ifdef DEBUG_IIO_JPEG
       printf("YO! Early EOI! ret = %d\n", ret);
 #endif
         RELEASE_ARRAYS(env, data, src->next_input_byte);
@@ -1252,21 +1252,24 @@
 {
     jpeg_saved_marker_ptr marker;
     int num_markers = 0;
+    int num_found_markers = 0;
     int seq_no;
     JOCTET *icc_data;
+    JOCTET *dst_ptr;
     unsigned int total_length;
 #define MAX_SEQ_NO  255         // sufficient since marker numbers are bytes
-    char marker_present[MAX_SEQ_NO+1];    // 1 if marker found
-    unsigned int data_length[MAX_SEQ_NO+1]; // size of profile data in marker
-    unsigned int data_offset[MAX_SEQ_NO+1]; // offset for data in marker
+    jpeg_saved_marker_ptr icc_markers[MAX_SEQ_NO + 1];
+    int first;         // index of the first marker in the icc_markers array
+    int last;          // index of the last marker in the icc_markers array
     jbyteArray data = NULL;
 
     /* This first pass over the saved markers discovers whether there are
      * any ICC markers and verifies the consistency of the marker numbering.
      */
 
-    for (seq_no = 1; seq_no <= MAX_SEQ_NO; seq_no++)
-        marker_present[seq_no] = 0;
+    for (seq_no = 0; seq_no <= MAX_SEQ_NO; seq_no++)
+        icc_markers[seq_no] = NULL;
+
 
     for (marker = cinfo->marker_list; marker != NULL; marker = marker->next) {
         if (marker_is_icc(marker)) {
@@ -1278,37 +1281,58 @@
                 return NULL;
             }
             seq_no = GETJOCTET(marker->data[12]);
-            if (seq_no <= 0 || seq_no > num_markers) {
+
+            /* Some third-party tools produce images with profile chunk
+             * numeration started from zero. It is inconsistent with ICC
+             * spec, but seems to be recognized by majority of image
+             * processing tools, so we should be more tolerant to this
+             * departure from the spec.
+             */
+            if (seq_no < 0 || seq_no > num_markers) {
                 JNU_ThrowByName(env, "javax/imageio/IIOException",
                      "Invalid icc profile: bad sequence number");
                 return NULL;
             }
-            if (marker_present[seq_no]) {
+            if (icc_markers[seq_no] != NULL) {
                 JNU_ThrowByName(env, "javax/imageio/IIOException",
                      "Invalid icc profile: duplicate sequence numbers");
                 return NULL;
             }
-            marker_present[seq_no] = 1;
-            data_length[seq_no] = marker->data_length - ICC_OVERHEAD_LEN;
+            icc_markers[seq_no] = marker;
+            num_found_markers ++;
         }
     }
 
     if (num_markers == 0)
         return NULL;  // There is no profile
 
-    /* Check for missing markers, count total space needed,
-     * compute offset of each marker's part of the data.
-     */
+    if (num_markers != num_found_markers) {
+        JNU_ThrowByName(env, "javax/imageio/IIOException",
+                        "Invalid icc profile: invalid number of icc markers");
+        return NULL;
+    }
+
+    first = icc_markers[0] ? 0 : 1;
+    last = num_found_markers + first;
 
+    /* Check for missing markers, count total space needed.
+     */
     total_length = 0;
-    for (seq_no = 1; seq_no <= num_markers; seq_no++) {
-        if (marker_present[seq_no] == 0) {
+    for (seq_no = first; seq_no < last; seq_no++) {
+        unsigned int length;
+        if (icc_markers[seq_no] == NULL) {
             JNU_ThrowByName(env, "javax/imageio/IIOException",
                  "Invalid icc profile: missing sequence number");
             return NULL;
         }
-        data_offset[seq_no] = total_length;
-        total_length += data_length[seq_no];
+        /* check the data length correctness */
+        length = icc_markers[seq_no]->data_length;
+        if (ICC_OVERHEAD_LEN > length || length > MAX_BYTES_IN_MARKER) {
+            JNU_ThrowByName(env, "javax/imageio/IIOException",
+                 "Invalid icc profile: invalid data length");
+            return NULL;
+        }
+        total_length += (length - ICC_OVERHEAD_LEN);
     }
 
     if (total_length <= 0) {
@@ -1337,19 +1361,14 @@
     }
 
     /* and fill it in */
-    for (marker = cinfo->marker_list; marker != NULL; marker = marker->next) {
-        if (marker_is_icc(marker)) {
-            JOCTET FAR *src_ptr;
-            JOCTET *dst_ptr;
-            unsigned int length;
-            seq_no = GETJOCTET(marker->data[12]);
-            dst_ptr = icc_data + data_offset[seq_no];
-            src_ptr = marker->data + ICC_OVERHEAD_LEN;
-            length = data_length[seq_no];
-            while (length--) {
-                *dst_ptr++ = *src_ptr++;
-            }
-        }
+    dst_ptr = icc_data;
+    for (seq_no = first; seq_no < last; seq_no++) {
+        JOCTET FAR *src_ptr = icc_markers[seq_no]->data + ICC_OVERHEAD_LEN;
+        unsigned int length =
+            icc_markers[seq_no]->data_length - ICC_OVERHEAD_LEN;
+
+        memcpy(dst_ptr, src_ptr, length);
+        dst_ptr += length;
     }
 
     /* finally, unpin the array */
@@ -1565,6 +1584,7 @@
     j_decompress_ptr cinfo;
     struct jpeg_source_mgr *src;
     sun_jpeg_error_ptr jerr;
+    jbyteArray profileData = NULL;
 
     if (data == NULL) {
         JNU_ThrowByName(env,
@@ -1592,7 +1612,7 @@
         return retval;
     }
 
-#ifdef DEBUG
+#ifdef DEBUG_IIO_JPEG
     printf("In readImageHeader, data is %p cinfo is %p\n", data, cinfo);
     printf("clearFirst is %d\n", clearFirst);
 #endif
@@ -1619,7 +1639,7 @@
     if (ret == JPEG_HEADER_TABLES_ONLY) {
         retval = JNI_TRUE;
         imageio_term_source(cinfo);  // Pushback remaining buffer contents
-#ifdef DEBUG
+#ifdef DEBUG_IIO_JPEG
         printf("just read tables-only image; q table 0 at %p\n",
                cinfo->quant_tbl_ptrs[0]);
 #endif
@@ -1726,6 +1746,14 @@
             }
         }
         RELEASE_ARRAYS(env, data, src->next_input_byte);
+
+        /* read icc profile data */
+        profileData = read_icc_profile(env, cinfo);
+
+        if ((*env)->ExceptionCheck(env)) {
+            return retval;
+        }
+
         (*env)->CallVoidMethod(env, this,
                                JPEGImageReader_setImageDataID,
                                cinfo->image_width,
@@ -1733,7 +1761,7 @@
                                cinfo->jpeg_color_space,
                                cinfo->out_color_space,
                                cinfo->num_components,
-                               read_icc_profile(env, cinfo));
+                               profileData);
         if (reset) {
             jpeg_abort_decompress(cinfo);
         }
@@ -1898,7 +1926,7 @@
     (*env)->ReleaseIntArrayElements(env, bandSizes,
                                     bandSize, JNI_ABORT);
 
-#ifdef DEBUG
+#ifdef DEBUG_IIO_JPEG
     printf("---- in reader.read ----\n");
     printf("numBands is %d\n", numBands);
     printf("bands array: ");
@@ -2578,7 +2606,7 @@
 
     data->streamBuf.suspendable = FALSE;
     if (qtables != NULL) {
-#ifdef DEBUG
+#ifdef DEBUG_IIO_JPEG
         printf("in writeTables: qtables not NULL\n");
 #endif
         setQTables(env, (j_common_ptr) cinfo, qtables, TRUE);
@@ -2854,7 +2882,7 @@
 
     cinfo->restart_interval = restartInterval;
 
-#ifdef DEBUG
+#ifdef DEBUG_IIO_JPEG
     printf("writer setup complete, starting compressor\n");
 #endif
 
@@ -2905,13 +2933,13 @@
           for (; (in < pixelLimit) && (out < scanLineLimit); in += pixelStride) {
                 for (i = 0; i < numBands; i++) {
                     *out++ = data->scale[i][*(in+i)];
-#ifdef DEBUG
+#ifdef DEBUG_IIO_JPEG
                     if (in == data->pixelBuf.buf.bp){ // Just the first pixel
                         printf("in %d -> out %d, ", *(in+i), *(out-i-1));
                     }
 #endif
                 }
-#ifdef DEBUG
+#ifdef DEBUG_IIO_JPEG
                     if (in == data->pixelBuf.buf.bp){ // Just the first pixel
                         printf("\n");
                     }