4421494: infinite loop while parsing double literal
authoralanb
Sun Feb 06 19:17:34 2011 +0000 (2 years ago)
changeset 475d00080320e43
parent 474f7afe7a5e086
child 476ab13e29156f7
child 4874be1306cffe7
4421494: infinite loop while parsing double literal
Reviewed-by: darcy, alanb
Contributed-by: dmitry.nadezhin@oracle.com
src/share/classes/sun/misc/FloatingDecimal.java
test/java/lang/Double/ParseDouble.java
--- a/src/share/classes/sun/misc/FloatingDecimal.java Fri Jan 21 16:21:28 2011 -0800
+++ b/src/share/classes/sun/misc/FloatingDecimal.java Sun Feb 06 19:17:34 2011 +0000
@@ -1547,7 +1547,7 @@ public class FloatingDecimal{
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 Fri Jan 21 16:21:28 2011 -0800
+++ b/test/java/lang/Double/ParseDouble.java Sun Feb 06 19:17:34 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 @@ public class ParseDouble {
"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,42 @@ public class ParseDouble {
}
+ /**
+ * 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);
+
+ System.out.println("Testing 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());
+
+ if (convertedLowerBound != d) {
+ System.out.printf("Exponent %d, unexpected lower bound converted to %a, not %a.%n",
+ i, convertedLowerBound, d);
+ }
+
+ if (convertedUpperBound != d) {
+ System.out.printf("Exponent %d, unexpected upper bound converted to %a, not %a.%n",
+ i, convertedUpperBound, d);
+ }
+ }
+ }
+
public static void main(String[] args) throws Exception {
rudimentaryTest();
@@ -558,5 +603,7 @@ public class ParseDouble {
testRegex(paddedGoodStrings, false);
testRegex(badStrings, true);
testRegex(paddedBadStrings, true);
+
+ testSubnormalPowers();
}
}