From 8efef5ce9f6c0dfd2cb4720b61a37bbdfdb5e30e Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Tue, 12 Jan 2010 22:23:56 +0000 Subject: 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. --- Lib/test/floating_points.txt | 7 +++++++ Misc/NEWS | 4 ++++ Python/dtoa.c | 26 +++++++++++++++----------- 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/Lib/test/floating_points.txt b/Lib/test/floating_points.txt index 70d21ea..539073d 100644 --- a/Lib/test/floating_points.txt +++ b/Lib/test/floating_points.txt @@ -1019,3 +1019,10 @@ +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 diff --git a/Misc/NEWS b/Misc/NEWS index 245b6a6..9fc17dc 100644 --- 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. diff --git a/Python/dtoa.c b/Python/dtoa.c index 12e6f80..4d64be5 100644 --- a/Python/dtoa.c +++ b/Python/dtoa.c @@ -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 */ -- cgit v0.12