summaryrefslogtreecommitdiffstats
path: root/Objects/floatobject.c
diff options
context:
space:
mode:
authorTim Peters <tim.peters@gmail.com>2002-11-21 22:26:37 (GMT)
committerTim Peters <tim.peters@gmail.com>2002-11-21 22:26:37 (GMT)
commit7d791240c0858f9cf508234c255d2ca4dabd6088 (patch)
treeba07d418e78dabf2ccffffd5eb352eb17d76b379 /Objects/floatobject.c
parentd899605e30eef8e77f70184eac15fad1bf770586 (diff)
downloadcpython-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/floatobject.c')
-rw-r--r--Objects/floatobject.c30
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 *