Issue #4393: fix 3 classes of potential portability problems in longobject.c:

- fix some places where counters into ob_digit were declared as
   int instead of Py_ssize_t
 - add (twodigit) casts where necessary
 - fix code in _PyLong_AsByteArray that uses << on negative values
This commit is contained in:
Mark Dickinson 2009-01-24 15:27:44 +00:00
parent 0dfcfc8b59
commit ff84aa87b4
1 changed files with 20 additions and 23 deletions

View File

@ -513,7 +513,7 @@ _PyLong_FromByteArray(const unsigned char* bytes, size_t n,
/* Because we're going LSB to MSB, thisbyte is /* Because we're going LSB to MSB, thisbyte is
more significant than what's already in accum, more significant than what's already in accum,
so needs to be prepended to accum. */ so needs to be prepended to accum. */
accum |= thisbyte << accumbits; accum |= (twodigits)thisbyte << accumbits;
accumbits += 8; accumbits += 8;
if (accumbits >= PyLong_SHIFT) { if (accumbits >= PyLong_SHIFT) {
/* There's enough to fill a Python digit. */ /* There's enough to fill a Python digit. */
@ -542,7 +542,7 @@ _PyLong_AsByteArray(PyLongObject* v,
unsigned char* bytes, size_t n, unsigned char* bytes, size_t n,
int little_endian, int is_signed) int little_endian, int is_signed)
{ {
int i; /* index into v->ob_digit */ Py_ssize_t i; /* index into v->ob_digit */
Py_ssize_t ndigits; /* |v->ob_size| */ Py_ssize_t ndigits; /* |v->ob_size| */
twodigits accum; /* sliding register */ twodigits accum; /* sliding register */
unsigned int accumbits; /* # bits in accum */ unsigned int accumbits; /* # bits in accum */
@ -587,7 +587,7 @@ _PyLong_AsByteArray(PyLongObject* v,
accumbits = 0; accumbits = 0;
carry = do_twos_comp ? 1 : 0; carry = do_twos_comp ? 1 : 0;
for (i = 0; i < ndigits; ++i) { for (i = 0; i < ndigits; ++i) {
twodigits thisdigit = v->ob_digit[i]; digit thisdigit = v->ob_digit[i];
if (do_twos_comp) { if (do_twos_comp) {
thisdigit = (thisdigit ^ PyLong_MASK) + carry; thisdigit = (thisdigit ^ PyLong_MASK) + carry;
carry = thisdigit >> PyLong_SHIFT; carry = thisdigit >> PyLong_SHIFT;
@ -596,26 +596,23 @@ _PyLong_AsByteArray(PyLongObject* v,
/* Because we're going LSB to MSB, thisdigit is more /* Because we're going LSB to MSB, thisdigit is more
significant than what's already in accum, so needs to be significant than what's already in accum, so needs to be
prepended to accum. */ prepended to accum. */
accum |= thisdigit << accumbits; accum |= (twodigits)thisdigit << accumbits;
accumbits += PyLong_SHIFT;
/* The most-significant digit may be (probably is) at least /* The most-significant digit may be (probably is) at least
partly empty. */ partly empty. */
if (i == ndigits - 1) { if (i == ndigits - 1) {
/* Count # of sign bits -- they needn't be stored, /* Count # of sign bits -- they needn't be stored,
* although for signed conversion we need later to * although for signed conversion we need later to
* make sure at least one sign bit gets stored. * make sure at least one sign bit gets stored. */
* First shift conceptual sign bit to real sign bit. digit s = do_twos_comp ? thisdigit ^ PyLong_MASK :
*/ thisdigit;
stwodigits s = (stwodigits)(thisdigit << while (s != 0) {
(8*sizeof(stwodigits) - PyLong_SHIFT)); s >>= 1;
unsigned int nsignbits = 0; accumbits++;
while ((s < 0) == do_twos_comp && nsignbits < PyLong_SHIFT) {
++nsignbits;
s <<= 1;
} }
accumbits -= nsignbits;
} }
else
accumbits += PyLong_SHIFT;
/* Store as many bytes as possible. */ /* Store as many bytes as possible. */
while (accumbits >= 8) { while (accumbits >= 8) {
@ -1079,7 +1076,7 @@ convert_binop(PyObject *v, PyObject *w, PyLongObject **a, PyLongObject **b) {
static digit static digit
v_iadd(digit *x, Py_ssize_t m, digit *y, Py_ssize_t n) v_iadd(digit *x, Py_ssize_t m, digit *y, Py_ssize_t n)
{ {
int i; Py_ssize_t i;
digit carry = 0; digit carry = 0;
assert(m >= n); assert(m >= n);
@ -1105,7 +1102,7 @@ v_iadd(digit *x, Py_ssize_t m, digit *y, Py_ssize_t n)
static digit static digit
v_isub(digit *x, Py_ssize_t m, digit *y, Py_ssize_t n) v_isub(digit *x, Py_ssize_t m, digit *y, Py_ssize_t n)
{ {
int i; Py_ssize_t i;
digit borrow = 0; digit borrow = 0;
assert(m >= n); assert(m >= n);
@ -1171,7 +1168,7 @@ inplace_divrem1(digit *pout, digit *pin, Py_ssize_t size, digit n)
digit hi; digit hi;
rem = (rem << PyLong_SHIFT) + *--pin; rem = (rem << PyLong_SHIFT) + *--pin;
*--pout = hi = (digit)(rem / n); *--pout = hi = (digit)(rem / n);
rem -= hi * n; rem -= (twodigits)hi * n;
} }
return (digit)rem; return (digit)rem;
} }
@ -1436,11 +1433,11 @@ long_from_binary_base(char **str, int base)
while (--p >= start) { while (--p >= start) {
int k = _PyLong_DigitValue[Py_CHARMASK(*p)]; int k = _PyLong_DigitValue[Py_CHARMASK(*p)];
assert(k >= 0 && k < base); assert(k >= 0 && k < base);
accum |= (twodigits)(k << bits_in_accum); accum |= (twodigits)k << bits_in_accum;
bits_in_accum += bits_per_char; bits_in_accum += bits_per_char;
if (bits_in_accum >= PyLong_SHIFT) { if (bits_in_accum >= PyLong_SHIFT) {
*pdigit++ = (digit)(accum & PyLong_MASK); *pdigit++ = (digit)(accum & PyLong_MASK);
assert(pdigit - z->ob_digit <= (int)n); assert(pdigit - z->ob_digit <= n);
accum >>= PyLong_SHIFT; accum >>= PyLong_SHIFT;
bits_in_accum -= PyLong_SHIFT; bits_in_accum -= PyLong_SHIFT;
assert(bits_in_accum < PyLong_SHIFT); assert(bits_in_accum < PyLong_SHIFT);
@ -1449,7 +1446,7 @@ long_from_binary_base(char **str, int base)
if (bits_in_accum) { if (bits_in_accum) {
assert(bits_in_accum <= PyLong_SHIFT); assert(bits_in_accum <= PyLong_SHIFT);
*pdigit++ = (digit)accum; *pdigit++ = (digit)accum;
assert(pdigit - z->ob_digit <= (int)n); assert(pdigit - z->ob_digit <= n);
} }
while (pdigit - z->ob_digit < n) while (pdigit - z->ob_digit < n)
*pdigit++ = 0; *pdigit++ = 0;
@ -1846,7 +1843,7 @@ x_divrem(PyLongObject *v1, PyLongObject *w1, PyLongObject **prem)
digit vj = (j >= size_v) ? 0 : v->ob_digit[j]; digit vj = (j >= size_v) ? 0 : v->ob_digit[j];
twodigits q; twodigits q;
stwodigits carry = 0; stwodigits carry = 0;
int i; Py_ssize_t i;
SIGCHECK({ SIGCHECK({
Py_DECREF(a); Py_DECREF(a);
@ -2008,7 +2005,7 @@ x_add(PyLongObject *a, PyLongObject *b)
{ {
Py_ssize_t size_a = ABS(Py_SIZE(a)), size_b = ABS(Py_SIZE(b)); Py_ssize_t size_a = ABS(Py_SIZE(a)), size_b = ABS(Py_SIZE(b));
PyLongObject *z; PyLongObject *z;
int i; Py_ssize_t i;
digit carry = 0; digit carry = 0;
/* Ensure a is the larger of the two: */ /* Ensure a is the larger of the two: */