changeset 3473:82c8c54ac1d5

4421494: infinite loop while parsing double literal Reviewed-by: darcy, alanb Contributed-by: dmitry.nadezhin@oracle.com
author alanb
date Tue, 08 Feb 2011 19:31:44 +0000
parents 947ce00ed7a2
children 6661a1dfa369
files src/share/classes/sun/misc/FloatingDecimal.java test/java/lang/Double/ParseDouble.java
diffstat 2 files changed, 40 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/sun/misc/FloatingDecimal.java	Tue Feb 08 15:50:30 2011 +0000
+++ b/src/share/classes/sun/misc/FloatingDecimal.java	Tue Feb 08 19:31:44 2011 +0000
@@ -1547,7 +1547,7 @@
                 if ( (cmpResult = bigB.cmp( bigD ) ) > 0 ){
                     overvalue = true; // our candidate is too big.
                     diff = bigB.sub( bigD );
-                    if ( (bigIntNBits == 1) && (bigIntExp > -expBias) ){
+                    if ( (bigIntNBits == 1) && (bigIntExp > -expBias+1) ){
                         // candidate is a normalized exact power of 2 and
                         // is too big. We will be subtracting.
                         // For our purposes, ulp is the ulp of the
--- a/test/java/lang/Double/ParseDouble.java	Tue Feb 08 15:50:30 2011 +0000
+++ b/test/java/lang/Double/ParseDouble.java	Tue Feb 08 19:31:44 2011 +0000
@@ -23,11 +23,12 @@
 
 /*
  * @test
- * @bug 4160406 4705734 4707389 4826774 4895911
+ * @bug 4160406 4705734 4707389 4826774 4895911 4421494
  * @summary Test for Double.parseDouble method and acceptance regex
  */
 
 import java.util.regex.*;
+import java.math.BigDecimal;
 
 public class ParseDouble {
 
@@ -416,7 +417,15 @@
 
         "0x00100p1",
         "0x00.100p1",
-        "0x001.100p1"
+        "0x001.100p1",
+
+        // Limits
+
+        "1.7976931348623157E308",     // Double.MAX_VALUE
+        "4.9e-324",                   // Double.MIN_VALUE
+        "2.2250738585072014e-308",    // Double.MIN_NORMAL
+
+        "2.2250738585072012e-308",    // near Double.MIN_NORMAL
     };
 
     static String paddedBadStrings[];
@@ -546,6 +555,32 @@
 
     }
 
+    /**
+     * For each subnormal power of two, test at boundaries of
+     * region that should convert to that value.
+     */
+    private static void testSubnormalPowers() {
+        BigDecimal TWO = BigDecimal.valueOf(2);
+        // An ulp is the same for all subnormal values
+        BigDecimal ulp_BD = new BigDecimal(Double.MIN_VALUE);
+
+        // Test subnormal powers of two
+        for(int i = -1074; i <= -1022; i++) {
+            double d = Math.scalb(1.0, i);
+
+            /*
+             * The region [d - ulp/2, d + ulp/2] should round to d.
+             */
+            BigDecimal d_BD = new BigDecimal(d);
+
+            BigDecimal lowerBound = d_BD.subtract(ulp_BD.divide(TWO));
+            BigDecimal upperBound = d_BD.add(ulp_BD.divide(TWO));
+
+            double convertedLowerBound = Double.parseDouble(lowerBound.toString());
+            double convertedUpperBound = Double.parseDouble(upperBound.toString());
+        }
+    }
+
     public static void main(String[] args) throws Exception {
         rudimentaryTest();
 
@@ -558,5 +593,7 @@
         testRegex(paddedGoodStrings, false);
         testRegex(badStrings, true);
         testRegex(paddedBadStrings, true);
+
+        testSubnormalPowers();
     }
 }