]> granicus.if.org Git - python/commitdiff
Issue #7632: Fix a problem with _Py_dg_strtod that could lead to
authorMark Dickinson <dickinsm@gmail.com>
Tue, 12 Jan 2010 22:23:56 +0000 (22:23 +0000)
committerMark Dickinson <dickinsm@gmail.com>
Tue, 12 Jan 2010 22:23:56 +0000 (22:23 +0000)
crashes in debug builds, for certain long numeric strings
corresponding to subnormal values.

Lib/test/floating_points.txt
Misc/NEWS
Python/dtoa.c

index 70d21ea7140ef9aff326c983fbf6858cfaad4985..539073d19d857733b36d383c9f9c0def0a65ea93 100644 (file)
 +43723334984997307E-26
 +10182419849537963E-24
 -93501703572661982E-26
+
+# A value that caused a crash in debug builds for Python >= 2.7, 3.1
+# See http://bugs.python.org/issue7632
+2183167012312112312312.23538020374420446192e-370
+
+# Another value designed to test a corner case of Python's strtod code.
+0.99999999999999999999999999999999999999999e+23
index 245b6a6acdbd93732e8219bafba1cce994309433..9fc17dc1d2ea2607277e50faa75756c582ef4d0f 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -12,6 +12,10 @@ What's New in Python 2.7 alpha 3?
 Core and Builtins
 -----------------
 
+- Issue #7632: Fix a crash in dtoa.c that occurred in debug builds
+  when parsing certain long numeric strings corresponding to subnormal
+  values.
+
 - Issue #7319: Silence DeprecationWarning by default.
 
 - Issue #2335: Backport set literals syntax from Python 3.x.
index 12e6f806380932de83fe89f7623e7cbe2aba8b2e..4d64be5f07bdd3ea8b5b3891cb902b66045ae552 100644 (file)
@@ -1142,7 +1142,7 @@ bigcomp(U *rv, const char *s0, BCinfo *bc)
     dsign = bc->dsign;
     nd = bc->nd;
     nd0 = bc->nd0;
-    p5 = nd + bc->e0 - 1;
+    p5 = nd + bc->e0;
     speccase = 0;
     if (rv->d == 0.) {  /* special case: value near underflow-to-zero */
         /* threshold was rounded to zero */
@@ -1227,17 +1227,21 @@ bigcomp(U *rv, const char *s0, BCinfo *bc)
         }
     }
 
-    /* Now b/d = exactly half-way between the two floating-point values */
-    /* on either side of the input string.  Compute first digit of b/d. */
-
-    if (!(dig = quorem(b,d))) {
-        b = multadd(b, 10, 0);  /* very unlikely */
-        if (b == NULL) {
-            Bfree(d);
-            return -1;
-        }
-        dig = quorem(b,d);
+    /* Now 10*b/d = exactly half-way between the two floating-point values
+       on either side of the input string.  If b >= d, round down. */
+    if (cmp(b, d) >= 0) {
+        dd = -1;
+        goto ret;
+    }
+       
+    /* Compute first digit of 10*b/d. */
+    b = multadd(b, 10, 0);
+    if (b == NULL) {
+        Bfree(d);
+        return -1;
     }
+    dig = quorem(b, d);
+    assert(dig < 10);
 
     /* Compare b/d with s0 */