changeset 2131:04cd613daca9

S4421494, CVE-2010-4476: infinite loop while parsing double literal. 2011-02-09 Andrew John Hughes <ahughes@redhat.com> * Makefile.am: Add patch. * NEWS: Updated. * patches/security/20110209/4421494.patch: Add floating point bug fix.
author Andrew John Hughes <ahughes@redhat.com>
date Wed, 09 Feb 2011 12:36:05 +0000
parents 6e111db7700c
children c43e42301ab8
files ChangeLog Makefile.am NEWS patches/security/20110209/4421494.patch
diffstat 4 files changed, 118 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Tue Feb 01 18:15:36 2011 +0000
+++ b/ChangeLog	Wed Feb 09 12:36:05 2011 +0000
@@ -1,3 +1,10 @@
+2011-02-09  Andrew John Hughes  <ahughes@redhat.com>
+
+	* Makefile.am: Add patch.
+	* NEWS: Updated.
+	* patches/security/20110209/4421494.patch:
+	Add floating point bug fix.
+
 2011-02-01  Andrew John Hughes  <ahughes@redhat.com>
 
 	* NEWS: Update for 1.8.6.
--- a/Makefile.am	Tue Feb 01 18:15:36 2011 +0000
+++ b/Makefile.am	Wed Feb 09 12:36:05 2011 +0000
@@ -251,7 +251,8 @@
 	patches/security/20101012/6961084.patch \
 	patches/security/20101012/6963285.patch \
 	patches/security/20101012/6981426.patch \
-	patches/security/20101012/6990437.patch
+	patches/security/20101012/6990437.patch \
+	patches/security/20110209/4421494.patch
 
 ICEDTEA_PATCHES = \
 	$(SECURITY_PATCHES) \
--- a/NEWS	Tue Feb 01 18:15:36 2011 +0000
+++ b/NEWS	Wed Feb 09 12:36:05 2011 +0000
@@ -10,6 +10,9 @@
 
 New in release 1.8.6 (20XX-XX-XX):
 
+* Security updates
+  - S4421494, CVE-2010-4476: infinite loop while parsing double literal.
+
 New in release 1.8.5 (2011-02-01):
 
 * Security updates
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/security/20110209/4421494.patch	Wed Feb 09 12:36:05 2011 +0000
@@ -0,0 +1,106 @@
+# HG changeset patch
+# User alanb
+# Date 1297019854 0
+# Node ID d00080320e439c339594d380f0322c865553a046
+# Parent  f7afe7a5e086a6af1f23dd6304bcbe7fb2b6226a
+4421494: infinite loop while parsing double literal
+Reviewed-by: darcy, alanb
+Contributed-by: dmitry.nadezhin@oracle.com
+
+diff --git a/src/share/classes/sun/misc/FloatingDecimal.java b/src/share/classes/sun/misc/FloatingDecimal.java
+--- openjdk/jdk/src/share/classes/sun/misc/FloatingDecimal.java
++++ openjdk/jdk/src/share/classes/sun/misc/FloatingDecimal.java
+@@ -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
+diff --git a/test/java/lang/Double/ParseDouble.java b/test/java/lang/Double/ParseDouble.java
+--- openjdk/jdk/test/java/lang/Double/ParseDouble.java
++++ openjdk/jdk/test/java/lang/Double/ParseDouble.java
+@@ -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();
+     }
+ }