RFR for 8043740 (Doubles with large exponents overflow to Infinity incorrectly)

Sandipan Razzaque me at sandipan.net
Mon Jun 2 14:08:06 UTC 2014


Hi all -

I've made a quick revision to that last patch. Please find inline the
latest link + patch.

http://www.sandipan.net/public/webrevs/8043740/webrev.01/

Cheers,
SR

--- old/src/share/classes/sun/misc/FloatingDecimal.java 2014-06-02
09:32:20.000000000 -0400
+++ new/src/share/classes/sun/misc/FloatingDecimal.java 2014-06-02
09:32:19.000000000 -0400
@@ -1994,19 +1994,29 @@
                 }
                 int expLimit = BIG_DECIMAL_EXPONENT+nDigits+nTrailZero;
                 if ( expOverflow || ( expVal > expLimit ) ){
-                    //
-                    // The intent here is to end up with
-                    // infinity or zero, as appropriate.
-                    // The reason for yielding such a small decExponent,
-                    // rather than something intuitive such as
-                    // expSign*Integer.MAX_VALUE, is that this value
-                    // is subject to further manipulation in
-                    // doubleValue() and floatValue(), and I don't want
-                    // it to be able to cause overflow there!
-                    // (The only way we can get into trouble here is for
-                    // really outrageous nDigits+nTrailZero, such as
2 billion. )
-                    //
-                    decExp = expSign*expLimit;
+    // There is still a chance that the exponent will be
+    // safe to use: if it would eventually decrease
+    // due to a negative decExp, and that number is below the limit.
+    // We check for that here.
+    if ( ( expSign == 1 && decExp < 0 )
+ && ( expVal + decExp ) < expLimit ) {
+ // Cannot overflow - adding a positive and negative number.
+ decExp = expVal + decExp;
+    } else {
+ //
+ // The intent here is to end up with
+ // infinity or zero, as appropriate.
+ // The reason for yielding such a small decExponent,
+ // rather than something intuitive such as
+ // expSign*Integer.MAX_VALUE, is that this value
+ // is subject to further manipulation in
+ // doubleValue() and floatValue(), and I don't want
+ // it to be able to cause overflow there!
+ // (The only way we can get into trouble here is for
+ // really outrageous nDigits+nTrailZero, such as 2 billion. )
+ //
+ decExp = expSign*expLimit;
+    }
                 } else {
                     // this should not overflow, since we tested
                     // for expVal > (MAX+N), where N >= abs(decExp)
--- /dev/null 2014-06-02 09:32:21.000000000 -0400
+++ new/test/java/lang/Double/Bug8043740.java 2014-06-02
09:32:20.000000000 -0400
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2001, 2014, 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 8043740
+ * @summary Test for Double.parseDouble incorrect normalization of exponent.
+ */
+public class Bug8043740 {
+
+    public static void main(String[] args) {
+        String text = "00.000000000000000001e326";
+ double expected = Double.parseDouble("1e308");
+        double value = Double.parseDouble(text);
+        if (Double.compare(expected, value) != 0) {
+            throw new RuntimeException("String [" + text +
+                    "] was incorrectly parsed to [" + value + "]");
+        }
+    }
+
+}


Sandipan Razzaque | www.sandipan.net


On Sun, Jun 1, 2014 at 10:55 PM, Sandipan Razzaque <me at sandipan.net> wrote:
> Hi Brian/all,
>
> Fix for the above-mentioned bug is complete. If you (or anyone else as
> appropriate) could please review the changes and let me know of your
> comments that would be great!
>
> Link for the webrev:
>
> http://www.sandipan.net/public/webrevs/8043740/webrev.00/
>
> The patch is inlined below my signature.
>
> Cheers,
> SR
>
>
> --- old/src/share/classes/sun/misc/FloatingDecimal.java	2014-06-01
> 22:33:34.947651253 -0400
> +++ new/src/share/classes/sun/misc/FloatingDecimal.java	2014-06-01
> 22:33:34.827651251 -0400
> @@ -1992,7 +1992,10 @@
>                          break expLoop; // stop parsing exponent.
>                      }
>                  }
> -                int expLimit = BIG_DECIMAL_EXPONENT+nDigits+nTrailZero;
> +
> +                int expLimit = BIG_DECIMAL_EXPONENT + nDigits + nTrailZero
> +                                                    - (nLeadZero - decPt);
> +
>                  if ( expOverflow || ( expVal > expLimit ) ){
>                      //
>                      // The intent here is to end up with
> --- /dev/null	2014-05-28 21:22:08.061671015 -0400
> +++ new/test/java/lang/Double/Bug8043740.java	2014-06-01 22:33:35.227651260
> -0400
> @@ -0,0 +1,40 @@
> +/*
> + * Copyright (c) 2001, 2014, 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 8043740
> + * @summary Test for Double.parseDouble incorrect normalization of
> exponent.
> + */
> +public class Bug8043740 {
> +
> +    public static void main(String[] args) {
> +        String text326 = "00.000000000000000001e326"; // expect 1e308
> +        double value326 = Double.parseDouble(text326);
> +        if (Double.isInfinite(value326)) {
> +            throw new RuntimeException("String [" + text326 +
> +                    "] was incorrectly parsed to Infinity.");
> +        }
> +    }
> +
> +}
>
>



More information about the core-libs-dev mailing list