[3.13] gh-121153: Fix some errors with use of _PyLong_CompactValue() (GH-121154) (GH-121900)

* The result has type Py_ssize_t, not intptr_t.
* Type cast between unsigned and signed integer types should be explicit.
* Downcasting should be explicit.
* Fix integer overflow check in sum().
(cherry picked from commit 1801545)
This commit is contained in:
Serhiy Storchaka 2024-07-17 11:04:45 +03:00 committed by GitHub
parent d358f74a69
commit 09ff4ec14f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 57 additions and 15 deletions

View File

@ -483,11 +483,18 @@ PyLong_AsLongAndOverflow(PyObject *vv, int *overflow)
do_decref = 1; do_decref = 1;
} }
if (_PyLong_IsCompact(v)) { if (_PyLong_IsCompact(v)) {
#if SIZEOF_LONG < SIZEOF_VOID_P #if SIZEOF_LONG < SIZEOF_SIZE_T
intptr_t tmp = _PyLong_CompactValue(v); Py_ssize_t tmp = _PyLong_CompactValue(v);
res = (long)tmp; if (tmp < LONG_MIN) {
if (res != tmp) { *overflow = -1;
*overflow = tmp < 0 ? -1 : 1; res = -1;
}
else if (tmp > LONG_MAX) {
*overflow = 1;
res = -1;
}
else {
res = (long)tmp;
} }
#else #else
res = _PyLong_CompactValue(v); res = _PyLong_CompactValue(v);
@ -632,14 +639,15 @@ PyLong_AsUnsignedLong(PyObject *vv)
v = (PyLongObject *)vv; v = (PyLongObject *)vv;
if (_PyLong_IsNonNegativeCompact(v)) { if (_PyLong_IsNonNegativeCompact(v)) {
#if SIZEOF_LONG < SIZEOF_VOID_P #if SIZEOF_LONG < SIZEOF_SIZE_T
intptr_t tmp = _PyLong_CompactValue(v); size_t tmp = (size_t)_PyLong_CompactValue(v);
unsigned long res = (unsigned long)tmp; unsigned long res = (unsigned long)tmp;
if (res != tmp) { if (res != tmp) {
goto overflow; goto overflow;
} }
return res;
#else #else
return _PyLong_CompactValue(v); return (unsigned long)(size_t)_PyLong_CompactValue(v);
#endif #endif
} }
if (_PyLong_IsNegative(v)) { if (_PyLong_IsNegative(v)) {
@ -685,7 +693,7 @@ PyLong_AsSize_t(PyObject *vv)
v = (PyLongObject *)vv; v = (PyLongObject *)vv;
if (_PyLong_IsNonNegativeCompact(v)) { if (_PyLong_IsNonNegativeCompact(v)) {
return _PyLong_CompactValue(v); return (size_t)_PyLong_CompactValue(v);
} }
if (_PyLong_IsNegative(v)) { if (_PyLong_IsNegative(v)) {
PyErr_SetString(PyExc_OverflowError, PyErr_SetString(PyExc_OverflowError,
@ -722,7 +730,11 @@ _PyLong_AsUnsignedLongMask(PyObject *vv)
} }
v = (PyLongObject *)vv; v = (PyLongObject *)vv;
if (_PyLong_IsCompact(v)) { if (_PyLong_IsCompact(v)) {
return (unsigned long)_PyLong_CompactValue(v); #if SIZEOF_LONG < SIZEOF_SIZE_T
return (unsigned long)(size_t)_PyLong_CompactValue(v);
#else
return (unsigned long)(long)_PyLong_CompactValue(v);
#endif
} }
i = _PyLong_DigitCount(v); i = _PyLong_DigitCount(v);
int sign = _PyLong_NonCompactSign(v); int sign = _PyLong_NonCompactSign(v);
@ -1528,7 +1540,18 @@ PyLong_AsUnsignedLongLong(PyObject *vv)
v = (PyLongObject*)vv; v = (PyLongObject*)vv;
if (_PyLong_IsNonNegativeCompact(v)) { if (_PyLong_IsNonNegativeCompact(v)) {
res = 0; res = 0;
bytes = _PyLong_CompactValue(v); #if SIZEOF_LONG_LONG < SIZEOF_SIZE_T
size_t tmp = (size_t)_PyLong_CompactValue(v);
bytes = (unsigned long long)tmp;
if (bytes != tmp) {
PyErr_SetString(PyExc_OverflowError,
"Python int too large to convert "
"to C unsigned long long");
res = -1;
}
#else
bytes = (unsigned long long)(size_t)_PyLong_CompactValue(v);
#endif
} }
else { else {
res = _PyLong_AsByteArray((PyLongObject *)vv, (unsigned char *)&bytes, res = _PyLong_AsByteArray((PyLongObject *)vv, (unsigned char *)&bytes,
@ -1559,7 +1582,11 @@ _PyLong_AsUnsignedLongLongMask(PyObject *vv)
} }
v = (PyLongObject *)vv; v = (PyLongObject *)vv;
if (_PyLong_IsCompact(v)) { if (_PyLong_IsCompact(v)) {
return (unsigned long long)(signed long long)_PyLong_CompactValue(v); #if SIZEOF_LONG_LONG < SIZEOF_SIZE_T
return (unsigned long long)(size_t)_PyLong_CompactValue(v);
#else
return (unsigned long long)(long long)_PyLong_CompactValue(v);
#endif
} }
i = _PyLong_DigitCount(v); i = _PyLong_DigitCount(v);
sign = _PyLong_NonCompactSign(v); sign = _PyLong_NonCompactSign(v);
@ -1631,7 +1658,22 @@ PyLong_AsLongLongAndOverflow(PyObject *vv, int *overflow)
do_decref = 1; do_decref = 1;
} }
if (_PyLong_IsCompact(v)) { if (_PyLong_IsCompact(v)) {
#if SIZEOF_LONG_LONG < SIZEOF_SIZE_T
Py_ssize_t tmp = _PyLong_CompactValue(v);
if (tmp < LLONG_MIN) {
*overflow = -1;
res = -1;
}
else if (tmp > LLONG_MAX) {
*overflow = 1;
res = -1;
}
else {
res = (long long)tmp;
}
#else
res = _PyLong_CompactValue(v); res = _PyLong_CompactValue(v);
#endif
} }
else { else {
i = _PyLong_DigitCount(v); i = _PyLong_DigitCount(v);
@ -3568,7 +3610,7 @@ long_hash(PyLongObject *v)
int sign; int sign;
if (_PyLong_IsCompact(v)) { if (_PyLong_IsCompact(v)) {
x = _PyLong_CompactValue(v); x = (Py_uhash_t)_PyLong_CompactValue(v);
if (x == (Py_uhash_t)-1) { if (x == (Py_uhash_t)-1) {
x = (Py_uhash_t)-2; x = (Py_uhash_t)-2;
} }

View File

@ -2601,8 +2601,8 @@ builtin_sum_impl(PyObject *module, PyObject *iterable, PyObject *start)
b = PyLong_AsLongAndOverflow(item, &overflow); b = PyLong_AsLongAndOverflow(item, &overflow);
} }
if (overflow == 0 && if (overflow == 0 &&
(i_result >= 0 ? (b <= LONG_MAX - i_result) (i_result >= 0 ? (b <= PY_SSIZE_T_MAX - i_result)
: (b >= LONG_MIN - i_result))) : (b >= PY_SSIZE_T_MIN - i_result)))
{ {
i_result += b; i_result += b;
Py_DECREF(item); Py_DECREF(item);