Skip to content

Commit 8efef5c

Browse files
committed
Issue #7632: Fix a problem with _Py_dg_strtod that could lead to
crashes in debug builds, for certain long numeric strings corresponding to subnormal values.
1 parent efa45f3 commit 8efef5c

3 files changed

Lines changed: 26 additions & 11 deletions

File tree

Lib/test/floating_points.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1019,3 +1019,10 @@
10191019
+43723334984997307E-26
10201020
+10182419849537963E-24
10211021
-93501703572661982E-26
1022+
1023+
# A value that caused a crash in debug builds for Python >= 2.7, 3.1
1024+
# See http://bugs.python.org/issue7632
1025+
2183167012312112312312.23538020374420446192e-370
1026+
1027+
# Another value designed to test a corner case of Python's strtod code.
1028+
0.99999999999999999999999999999999999999999e+23

Misc/NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ What's New in Python 2.7 alpha 3?
1212
Core and Builtins
1313
-----------------
1414

15+
- Issue #7632: Fix a crash in dtoa.c that occurred in debug builds
16+
when parsing certain long numeric strings corresponding to subnormal
17+
values.
18+
1519
- Issue #7319: Silence DeprecationWarning by default.
1620

1721
- Issue #2335: Backport set literals syntax from Python 3.x.

Python/dtoa.c

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1142,7 +1142,7 @@ bigcomp(U *rv, const char *s0, BCinfo *bc)
11421142
dsign = bc->dsign;
11431143
nd = bc->nd;
11441144
nd0 = bc->nd0;
1145-
p5 = nd + bc->e0 - 1;
1145+
p5 = nd + bc->e0;
11461146
speccase = 0;
11471147
if (rv->d == 0.) { /* special case: value near underflow-to-zero */
11481148
/* threshold was rounded to zero */
@@ -1227,17 +1227,21 @@ bigcomp(U *rv, const char *s0, BCinfo *bc)
12271227
}
12281228
}
12291229

1230-
/* Now b/d = exactly half-way between the two floating-point values */
1231-
/* on either side of the input string. Compute first digit of b/d. */
1232-
1233-
if (!(dig = quorem(b,d))) {
1234-
b = multadd(b, 10, 0); /* very unlikely */
1235-
if (b == NULL) {
1236-
Bfree(d);
1237-
return -1;
1238-
}
1239-
dig = quorem(b,d);
1230+
/* Now 10*b/d = exactly half-way between the two floating-point values
1231+
on either side of the input string. If b >= d, round down. */
1232+
if (cmp(b, d) >= 0) {
1233+
dd = -1;
1234+
goto ret;
1235+
}
1236+
1237+
/* Compute first digit of 10*b/d. */
1238+
b = multadd(b, 10, 0);
1239+
if (b == NULL) {
1240+
Bfree(d);
1241+
return -1;
12401242
}
1243+
dig = quorem(b, d);
1244+
assert(dig < 10);
12411245

12421246
/* Compare b/d with s0 */
12431247

0 commit comments

Comments
 (0)