Index: Include/longobject.h =================================================================== --- Include/longobject.h (révision 67111) +++ Include/longobject.h (copie de travail) @@ -49,7 +49,7 @@ zeroes). Overflow is impossible. Note that the exponent returned must be multiplied by SHIFT! There may not be enough room in an int to store e*SHIFT directly. */ -PyAPI_FUNC(double) _PyLong_AsScaledDouble(PyObject *vv, int *e); +PyAPI_FUNC(double) _PyLong_AsScaledDouble(PyObject *vv, unsigned int *e); PyAPI_FUNC(double) PyLong_AsDouble(PyObject *); PyAPI_FUNC(PyObject *) PyLong_FromVoidPtr(void *); Index: Objects/longobject.c =================================================================== --- Objects/longobject.c (révision 67111) +++ Objects/longobject.c (copie de travail) @@ -900,8 +900,12 @@ } +/** + * Convert a long integer into result * 2^exponent. If exponent is + * bigger than INT_MAX, return -1.0 and raise an OverflowError. + */ double -_PyLong_AsScaledDouble(PyObject *vv, int *exponent) +_PyLong_AsScaledDouble(PyObject *vv, unsigned int *exponent) { /* NBITS_WANTED should be > the number of bits in a double's precision, but small enough so that 2**NBITS_WANTED is within the normal double @@ -947,10 +951,17 @@ } /* There are i digits we didn't shift in. Pretending they're all zeroes, the true value is x * 2**(i*PyLong_SHIFT). */ - *exponent = i; + if (i > INT_MAX / PyLong_SHIFT) + goto overflow; + *exponent = (unsigned long)i * PyLong_SHIFT; assert(x > 0.0); return x * sign; #undef NBITS_WANTED + +overflow: + PyErr_SetString(PyExc_OverflowError, + "Python int too large to convert to C double"); + return -1.0; } /* Get a C double from a long int object. */ @@ -958,7 +969,7 @@ double PyLong_AsDouble(PyObject *vv) { - int e = -1; + unsigned int e; double x; if (vv == NULL || !PyLong_Check(vv)) { @@ -968,13 +979,8 @@ x = _PyLong_AsScaledDouble(vv, &e); if (x == -1.0 && PyErr_Occurred()) return -1.0; - /* 'e' initialized to -1 to silence gcc-4.0.x, but it should be - set correctly after a successful _PyLong_AsScaledDouble() call */ - assert(e >= 0); - if (e > INT_MAX / PyLong_SHIFT) - goto overflow; errno = 0; - x = ldexp(x, e * PyLong_SHIFT); + x = ldexp(x, e); if (Py_OVERFLOWED(x)) goto overflow; return x; @@ -2934,7 +2940,8 @@ long_true_divide(PyObject *a, PyObject *b) { double ad, bd; - int failed, aexp = -1, bexp = -1; + int failed, exp; + unsigned int aexp, bexp; CHECK_BINOP(a, b); ad = _PyLong_AsScaledDouble((PyObject *)a, &aexp); @@ -2942,26 +2949,17 @@ failed = (ad == -1.0 || bd == -1.0) && PyErr_Occurred(); if (failed) return NULL; - /* 'aexp' and 'bexp' were initialized to -1 to silence gcc-4.0.x, - but should really be set correctly after sucessful calls to - _PyLong_AsScaledDouble() */ - assert(aexp >= 0 && bexp >= 0); - if (bd == 0.0) { PyErr_SetString(PyExc_ZeroDivisionError, "int division or modulo by zero"); return NULL; } - /* True value is very close to ad/bd * 2**(PyLong_SHIFT*(aexp-bexp)) */ + /* True value is very close to ad/bd * 2**(aexp-bexp) */ ad /= bd; /* overflow/underflow impossible here */ - aexp -= bexp; - if (aexp > INT_MAX / PyLong_SHIFT) - goto overflow; - else if (aexp < -(INT_MAX / PyLong_SHIFT)) - return PyFloat_FromDouble(0.0); /* underflow to 0 */ + exp = (int)aexp - bexp; errno = 0; - ad = ldexp(ad, aexp * PyLong_SHIFT); + ad = ldexp(ad, exp); if (Py_OVERFLOWED(ad)) /* ignore underflow to 0.0 */ goto overflow; return PyFloat_FromDouble(ad); Index: Modules/mathmodule.c =================================================================== --- Modules/mathmodule.c (révision 67111) +++ Modules/mathmodule.c (copie de travail) @@ -801,18 +801,18 @@ /* If it is long, do it ourselves. */ if (PyLong_Check(arg)) { double x; - int e; + unsigned int e; x = _PyLong_AsScaledDouble(arg, &e); + if (x == -1.0 && PyErr_Occurred()) + return NULL; if (x <= 0.0) { PyErr_SetString(PyExc_ValueError, "math domain error"); return NULL; } - /* Value is ~= x * 2**(e*PyLong_SHIFT), so the log ~= - log(x) + log(2) * e * PyLong_SHIFT. - CAUTION: e*PyLong_SHIFT may overflow using int arithmetic, - so force use of double. */ - x = func(x) + (e * (double)PyLong_SHIFT) * func(2.0); + /* Value is ~= x * 2**e, + * so the log ~= log(x) + log(2) * e */ + x = func(x) + func(2.0) * e; return PyFloat_FromDouble(x); }