8158356: SIGSEGV when attempting to rotate BufferedImage using AffineTransform by NaN degrees
authoraghaisas
Thu, 25 Aug 2016 14:12:13 +0530
changeset 40725 2fe225923606
parent 40724 bcce34e79f55
child 40726 c403bb724166
8158356: SIGSEGV when attempting to rotate BufferedImage using AffineTransform by NaN degrees Reviewed-by: flar, prr
jdk/src/java.desktop/share/native/libawt/awt/medialib/awt_ImagingLib.c
jdk/src/java.desktop/share/native/libmlib_image/mlib_ImageScanPoly.c
jdk/src/java.desktop/share/native/libmlib_image/safe_math.h
jdk/test/java/awt/geom/AffineTransform/InvalidTransformParameterTest.java
--- a/jdk/src/java.desktop/share/native/libawt/awt/medialib/awt_ImagingLib.c	Thu Aug 25 13:46:17 2016 +0530
+++ b/jdk/src/java.desktop/share/native/libawt/awt/medialib/awt_ImagingLib.c	Thu Aug 25 14:12:13 2016 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -772,6 +772,7 @@
     mlib_image *src;
     mlib_image *dst;
     int i;
+    int j = 0;
     int retStatus = 1;
     mlib_status status;
     double *matrix;
@@ -824,6 +825,15 @@
         return 0;
     }
 
+    /* Check for invalid double value in transformation matrix */
+    for (j = 0; j < 6; j++) {
+
+        if (!(IS_FINITE(matrix[j]))) {
+            (*env)->ReleasePrimitiveArrayCritical(env, jmatrix, matrix, JNI_ABORT);
+            return 0;
+        }
+    }
+
     if (s_printIt) {
         printf("matrix is %g %g %g %g %g %g\n", matrix[0], matrix[1],
                matrix[2], matrix[3], matrix[4], matrix[5]);
@@ -980,6 +990,7 @@
     mlib_image *src;
     mlib_image *dst;
     int i;
+    int j = 0;
     int retStatus = 1;
     mlib_status status;
     double *matrix;
@@ -1044,6 +1055,18 @@
         return 0;
     }
 
+    /* Check for invalid double value in transformation matrix */
+    for (j = 0; j < 6; j++) {
+
+        if (!(IS_FINITE(matrix[j]))) {
+            (*env)->ReleasePrimitiveArrayCritical(env, jmatrix, matrix, JNI_ABORT);
+            free(srcRasterP);
+            free(dstRasterP);
+
+            return 0;
+        }
+    }
+
     if (s_printIt) {
         printf("matrix is %g %g %g %g %g %g\n", matrix[0], matrix[1],
                matrix[2], matrix[3], matrix[4], matrix[5]);
--- a/jdk/src/java.desktop/share/native/libmlib_image/mlib_ImageScanPoly.c	Thu Aug 25 13:46:17 2016 +0530
+++ b/jdk/src/java.desktop/share/native/libmlib_image/mlib_ImageScanPoly.c	Thu Aug 25 14:12:13 2016 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,6 +33,8 @@
 #include "mlib_image.h"
 #include "mlib_SysMath.h"
 #include "mlib_ImageAffine.h"
+#include "safe_math.h"
+
 
 /***************************************************************/
 mlib_status mlib_AffineEdges(mlib_affine_param *param,
@@ -83,6 +85,12 @@
   dstYStride = mlib_ImageGetStride(dst);
   paddings = mlib_ImageGetPaddings(src);
 
+  /* All the transformation matrix parameters should be finite. if not, return failure */
+  if (!(IS_FINITE(a) && IS_FINITE(b) && IS_FINITE(c) && IS_FINITE(d) &&
+        IS_FINITE(tx) && IS_FINITE(ty))) {
+    return MLIB_FAILURE;
+  }
+
   if (srcWidth >= (1 << 15) || srcHeight >= (1 << 15)) {
     return MLIB_FAILURE;
   }
@@ -288,6 +296,10 @@
     if (dY1 == dY2)
       continue;
 
+    if (!(IS_FINITE(slope))) {
+      continue;
+    }
+
     if (dY1 < 0.0)
       y1 = 0;
     else {
@@ -328,6 +340,10 @@
     if (dY1 == dY2)
       continue;
 
+    if (!(IS_FINITE(slope))) {
+      continue;
+    }
+
     if (dY1 < 0.0)
       y1 = 0;
     else {
--- a/jdk/src/java.desktop/share/native/libmlib_image/safe_math.h	Thu Aug 25 13:46:17 2016 +0530
+++ b/jdk/src/java.desktop/share/native/libmlib_image/safe_math.h	Thu Aug 25 14:12:13 2016 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,10 +26,15 @@
 #ifndef __SAFE_MATH_H__
 #define __SAFE_MATH_H__
 
+#include "mlib_types.h"
+
 #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)))
 
+#define IS_FINITE(a) \
+    (((a) >= MLIB_D64_MIN) && ((a) <= MLIB_D64_MAX))
+
 #endif // __SAFE_MATH_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/geom/AffineTransform/InvalidTransformParameterTest.java	Thu Aug 25 14:12:13 2016 +0530
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 8158356
+ * @summary Test AffineTransform transformations do not result in SIGSEGV
+ * if NaN or infinity parameter is passed as argument.
+ * @run main InvalidTransformParameterTest
+ */
+
+import java.awt.geom.AffineTransform;
+import java.awt.image.AffineTransformOp;
+import java.awt.image.BufferedImage;
+import java.awt.image.ImagingOpException;
+import java.awt.Point;
+import java.awt.image.DataBuffer;
+import java.awt.image.DataBufferByte;
+import java.awt.image.PixelInterleavedSampleModel;
+import java.awt.image.Raster;
+import java.awt.image.WritableRaster;
+import java.awt.image.RasterOp;
+import java.awt.image.SampleModel;
+
+public class InvalidTransformParameterTest {
+
+    public static void main(String[] args) {
+        int count = 0;
+        final int testScenarios = 12;
+        double NaNArg = 0.0 / 0.0;
+        double positiveInfArg = 1.0 / 0.0;
+        double negativeInfArg = -1.0 / 0.0;
+
+        BufferedImage img = new BufferedImage(5, 5, BufferedImage.TYPE_INT_ARGB);
+
+        AffineTransform[] inputTransforms = new AffineTransform[testScenarios];
+
+        for (int i = 0; i < inputTransforms.length; i++) {
+            inputTransforms[i] = new AffineTransform();
+        }
+
+        inputTransforms[0].rotate(NaNArg, img.getWidth()/2, img.getHeight()/2);
+        inputTransforms[1].translate(NaNArg, NaNArg);
+        inputTransforms[2].scale(NaNArg, NaNArg);
+        inputTransforms[3].shear(NaNArg, NaNArg);
+
+        inputTransforms[4].rotate(positiveInfArg, img.getWidth()/2, img.getHeight()/2);
+        inputTransforms[5].translate(positiveInfArg, positiveInfArg);
+        inputTransforms[6].scale(positiveInfArg, positiveInfArg);
+        inputTransforms[7].shear(positiveInfArg, positiveInfArg);
+
+        inputTransforms[8].rotate(negativeInfArg, img.getWidth()/2, img.getHeight()/2);
+        inputTransforms[9].translate(negativeInfArg, negativeInfArg);
+        inputTransforms[10].scale(negativeInfArg, negativeInfArg);
+        inputTransforms[11].shear(negativeInfArg, negativeInfArg);
+
+        // Test BufferedImage AffineTransform ---------------------------------
+
+        for (int i = 0; i < inputTransforms.length; i++) {
+            try {
+                testImageTransform(img, inputTransforms[i]);
+            } catch (ImagingOpException ex) {
+                count++;
+            }
+        }
+
+        if (count != testScenarios) {
+            throw new RuntimeException("Test failed. All test scenarios did not"
+                                       + " result in exception as expected.");
+        }
+
+        // Test Raster AffineTransform ---------------------------------
+
+        count = 0;
+        int[] bandOffsets = {0};
+        Point location = new Point(0, 0);
+        DataBuffer db = new DataBufferByte(10 * 10);
+        SampleModel sm = new PixelInterleavedSampleModel(DataBuffer.TYPE_BYTE,
+                                                         10, 10, 1, 10,
+                                                         bandOffsets);
+
+        Raster src = Raster.createRaster(sm, db, location);
+        WritableRaster dst = Raster.createWritableRaster(sm, db, location);
+
+        for (int i = 0; i < inputTransforms.length; i++) {
+            try {
+                testRasterTransform(src, dst, inputTransforms[i]);
+            } catch (ImagingOpException ex) {
+                count++;
+            }
+        }
+
+        if (count != testScenarios) {
+            throw new RuntimeException("Test failed. All test scenarios did not"
+                                       + " result in exception as expected.");
+        }
+    }
+
+    public static BufferedImage testImageTransform(BufferedImage image,
+                                                   AffineTransform transform) {
+        AffineTransformOp op =
+                new AffineTransformOp(transform, AffineTransformOp.TYPE_BILINEAR);
+
+        BufferedImage transformedImage = new BufferedImage(image.getWidth(),
+                                                           image.getHeight(),
+                                                           image.getType());
+
+        return op.filter(image, transformedImage);
+    }
+
+    public static Raster testRasterTransform(Raster src, WritableRaster dst,
+                                             AffineTransform transform) {
+        AffineTransformOp op =
+                new AffineTransformOp(transform, AffineTransformOp.TYPE_BILINEAR);
+
+        return op.filter(src, dst);
+    }
+}
+