diff options
author | Tim Peters <tim.peters@gmail.com> | 2002-11-21 22:26:37 (GMT) |
---|---|---|
committer | Tim Peters <tim.peters@gmail.com> | 2002-11-21 22:26:37 (GMT) |
commit | 7d791240c0858f9cf508234c255d2ca4dabd6088 (patch) | |
tree | ba07d418e78dabf2ccffffd5eb352eb17d76b379 /Objects | |
parent | d899605e30eef8e77f70184eac15fad1bf770586 (diff) | |
download | cpython-7d791240c0858f9cf508234c255d2ca4dabd6088.zip cpython-7d791240c0858f9cf508234c255d2ca4dabd6088.tar.gz cpython-7d791240c0858f9cf508234c255d2ca4dabd6088.tar.bz2 |
float_int(): Some systems raise an exception if a double is cast to
long but the double is too big to fit in a long. Prevent that. This
closes some recent bug or patch on SF, but SF is down now so I can't
say which.
Bugfix candidate.
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/floatobject.c | 30 |
1 files changed, 16 insertions, 14 deletions
diff --git a/Objects/floatobject.c b/Objects/floatobject.c index 129f5bd..cd28349 100644 --- a/Objects/floatobject.c +++ b/Objects/floatobject.c @@ -653,23 +653,25 @@ float_int(PyObject *v) { double x = PyFloat_AsDouble(v); double wholepart; /* integral portion of x, rounded toward 0 */ - long aslong; /* (long)wholepart */ (void)modf(x, &wholepart); -#ifdef RISCOS - /* conversion from floating to integral type would raise exception */ - if (wholepart>LONG_MAX || wholepart<LONG_MIN) { - return float_long(v); - } -#endif - /* doubles may have more bits than longs, or vice versa; and casting - to long may yield gibberish in either case. What really matters - is whether converting back to double again reproduces what we - started with. */ - aslong = (long)wholepart; - if ((double)aslong == wholepart) + /* Try to get out cheap if this fits in a Python int. The attempt + * to cast to long must be protected, as C doesn't define what + * happens if the double is too big to fit in a long. Some rare + * systems raise an exception then (RISCOS was mentioned as one, + * and someone using a non-default option on Sun also bumped into + * that). Note that checking for >= and <= LONG_{MIN,MAX} would + * still be vulnerable: if a long has more bits of precision than + * a double, casting MIN/MAX to double may yield an approximation, + * and if that's rounded up, then, e.g., wholepart=LONG_MAX+1 would + * yield true from the C expression wholepart<=LONG_MAX, despite + * that wholepart is actually greater than LONG_MAX. + */ + if (LONG_MIN < wholepart && wholepart < LONG_MAX) { + const long aslong = (long)wholepart; return PyInt_FromLong(aslong); - return float_long(v); + } + return PyLong_FromDouble(wholepart); } static PyObject * |