Kaydet (Commit) 7ab6be21 authored tarafından Mark Dickinson's avatar Mark Dickinson

PyLong_FromSsize_t was incorrect when sizeof(size_t) > sizeof(long);

rewrite it so that it doesn't care about relative sizes of size_t,
long and long long.

The rewrite is modeled on PyLong_FromLong, instead of using
PyLong_FromByteArray;  this makes the algorithm simpler and
more direct, and possibly also slightly faster.
üst 32dde221
...@@ -12,6 +12,9 @@ What's New in Python 3.0a5? ...@@ -12,6 +12,9 @@ What's New in Python 3.0a5?
Core and Builtins Core and Builtins
----------------- -----------------
- Fix misbehaviour of PyLong_FromSsize_t on systems where sizeof(size_t) >
sizeof(long).
- Issue #2221: Corrected a SystemError "error return without exception set", - Issue #2221: Corrected a SystemError "error return without exception set",
when the code executed by exec() raises an exception, and sys.stdout.flush() when the code executed by exec() raises an exception, and sys.stdout.flush()
also raises an error. also raises an error.
......
...@@ -1099,13 +1099,39 @@ PyLong_FromUnsignedLongLong(unsigned PY_LONG_LONG ival) ...@@ -1099,13 +1099,39 @@ PyLong_FromUnsignedLongLong(unsigned PY_LONG_LONG ival)
PyObject * PyObject *
PyLong_FromSsize_t(Py_ssize_t ival) PyLong_FromSsize_t(Py_ssize_t ival)
{ {
Py_ssize_t bytes = ival; PyLongObject *v;
int one = 1; size_t abs_ival;
if (ival < PyLong_BASE) size_t t; /* unsigned so >> doesn't propagate sign bit */
return PyLong_FromLong(ival); int ndigits = 0;
return _PyLong_FromByteArray( int negative = 0;
(unsigned char *)&bytes,
SIZEOF_SIZE_T, IS_LITTLE_ENDIAN, 1); CHECK_SMALL_INT(ival);
if (ival < 0) {
/* avoid signed overflow when ival = SIZE_T_MIN */
abs_ival = (size_t)(-1-ival)+1;
negative = 1;
}
else {
abs_ival = (size_t)ival;
}
/* Count the number of Python digits. */
t = abs_ival;
while (t) {
++ndigits;
t >>= PyLong_SHIFT;
}
v = _PyLong_New(ndigits);
if (v != NULL) {
digit *p = v->ob_digit;
Py_SIZE(v) = negative ? -ndigits : ndigits;
t = abs_ival;
while (t) {
*p++ = (digit)(t & PyLong_MASK);
t >>= PyLong_SHIFT;
}
}
return (PyObject *)v;
} }
/* Create a new long int object from a C size_t. */ /* Create a new long int object from a C size_t. */
...@@ -1113,13 +1139,28 @@ PyLong_FromSsize_t(Py_ssize_t ival) ...@@ -1113,13 +1139,28 @@ PyLong_FromSsize_t(Py_ssize_t ival)
PyObject * PyObject *
PyLong_FromSize_t(size_t ival) PyLong_FromSize_t(size_t ival)
{ {
size_t bytes = ival; PyLongObject *v;
int one = 1; size_t t;
int ndigits = 0;
if (ival < PyLong_BASE) if (ival < PyLong_BASE)
return PyLong_FromLong(ival); return PyLong_FromLong(ival);
return _PyLong_FromByteArray( /* Count the number of Python digits. */
(unsigned char *)&bytes, t = ival;
SIZEOF_SIZE_T, IS_LITTLE_ENDIAN, 0); while (t) {
++ndigits;
t >>= PyLong_SHIFT;
}
v = _PyLong_New(ndigits);
if (v != NULL) {
digit *p = v->ob_digit;
Py_SIZE(v) = ndigits;
while (ival) {
*p++ = (digit)(ival & PyLong_MASK);
ival >>= PyLong_SHIFT;
}
}
return (PyObject *)v;
} }
/* Get a C PY_LONG_LONG int from a long int object. /* Get a C PY_LONG_LONG int from a long int object.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment