mirror of https://github.com/python/cpython
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:
parent
0dfcfc8b59
commit
ff84aa87b4
|
@ -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: */
|
||||||
|
|
Loading…
Reference in New Issue