diff --git a/Objects/longobject.c b/Objects/longobject.c --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -1246,8 +1246,7 @@ PyLong_AsUnsignedLongLong(PyObject *vv) { PyLongObject *v; - unsigned PY_LONG_LONG bytes; - int res; + unsigned PY_LONG_LONG result = 0; if (vv == NULL) { PyErr_BadInternalCall(); @@ -1260,18 +1259,28 @@ v = (PyLongObject*)vv; switch(Py_SIZE(v)) { - case 0: return 0; - case 1: return v->ob_digit[0]; - } - - res = _PyLong_AsByteArray((PyLongObject *)vv, (unsigned char *)&bytes, - SIZEOF_LONG_LONG, PY_LITTLE_ENDIAN, 0); - - /* Plan 9 can't handle PY_LONG_LONG in ? : expressions */ - if (res < 0) - return (unsigned PY_LONG_LONG)res; - else - return bytes; +#define DIGIT_AS_LLU(n) ((unsigned PY_LONG_LONG)v->ob_digit[n] << (n*PyLong_SHIFT)) +#if PYLONG_BITS_IN_DIGIT == 15 + case 5: if (v->ob_digit[4] > 0xF) goto overflow_error; + result |= DIGIT_AS_LLU(4); + case 4: result |= DIGIT_AS_LLU(3); + case 3: result |= DIGIT_AS_LLU(2); +#else + case 3: if (v->ob_digit[2] > 0xF) goto overflow_error; + result |= DIGIT_AS_LLU(2); +#endif + case 2: result |= DIGIT_AS_LLU(1); + case 1: result |= DIGIT_AS_LLU(0); + case 0: break; + default: goto overflow_error; + } + + return result; + +overflow_error: + PyErr_Format(PyExc_OverflowError, + "input out of range for unsigned long long: %R", vv); + return (unsigned PY_LONG_LONG)-1; } /* Get a C unsigned long int from an int object, ignoring the high bits.