4421494: infinite loop while parsing double literal
Reviewed-by: darcy, alanb
Contributed-by: dmitry.nadezhin@oracle.com
--- a/jdk/src/share/classes/sun/misc/FloatingDecimal.java Tue Feb 08 15:50:30 2011 +0000
+++ b/jdk/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/jdk/test/java/lang/Double/ParseDouble.java Tue Feb 08 15:50:30 2011 +0000
+++ b/jdk/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();
}
}