Skip to content

Commit

Permalink
gh-121153: Fix some errors with use of _PyLong_CompactValue()
Browse files Browse the repository at this point in the history
* The result has type Py_ssize_t, not intptr_t.
* Type cast between unsigned and signdet integer types should be explicit.
* Downcasting should be explicit.
  • Loading branch information
serhiy-storchaka committed Jun 29, 2024
1 parent 2cb84b1 commit 0bc15a8
Showing 1 changed file with 46 additions and 12 deletions.
58 changes: 46 additions & 12 deletions Objects/longobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -483,11 +483,14 @@ PyLong_AsLongAndOverflow(PyObject *vv, int *overflow)
do_decref = 1;
}
if (_PyLong_IsCompact(v)) {
#if SIZEOF_LONG < SIZEOF_VOID_P
intptr_t tmp = _PyLong_CompactValue(v);
res = (long)tmp;
if (res != tmp) {
#if SIZEOF_LONG < SIZEOF_SIZE_T
Py_ssize_t tmp = _PyLong_CompactValue(v);
if ((unsigned long)(size_t)tmp != (size_t)tmp) {
*overflow = tmp < 0 ? -1 : 1;
res = -1;
}
else {
res = (long)tmp;
}
#else
res = _PyLong_CompactValue(v);
Expand Down Expand Up @@ -632,14 +635,14 @@ PyLong_AsUnsignedLong(PyObject *vv)

v = (PyLongObject *)vv;
if (_PyLong_IsNonNegativeCompact(v)) {
#if SIZEOF_LONG < SIZEOF_VOID_P
intptr_t tmp = _PyLong_CompactValue(v);
#if SIZEOF_LONG < SIZEOF_SIZE_T
size_t tmp = (size_t)_PyLong_CompactValue(v);
unsigned long res = (unsigned long)tmp;
if (res != tmp) {
goto overflow;
}
#else
return _PyLong_CompactValue(v);
return (unsigned long)(size_t)_PyLong_CompactValue(v);
#endif
}
if (_PyLong_IsNegative(v)) {
Expand Down Expand Up @@ -685,7 +688,7 @@ PyLong_AsSize_t(PyObject *vv)

v = (PyLongObject *)vv;
if (_PyLong_IsNonNegativeCompact(v)) {
return _PyLong_CompactValue(v);
return (size_t)_PyLong_CompactValue(v);
}
if (_PyLong_IsNegative(v)) {
PyErr_SetString(PyExc_OverflowError,
Expand Down Expand Up @@ -722,7 +725,11 @@ _PyLong_AsUnsignedLongMask(PyObject *vv)
}
v = (PyLongObject *)vv;
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);
int sign = _PyLong_NonCompactSign(v);
Expand Down Expand Up @@ -1540,7 +1547,19 @@ PyLong_AsUnsignedLongLong(PyObject *vv)
v = (PyLongObject*)vv;
if (_PyLong_IsNonNegativeCompact(v)) {
res = 0;
bytes = _PyLong_CompactValue(v);
bytes = (unsigned long long)(size_t)_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 {
res = _PyLong_AsByteArray((PyLongObject *)vv, (unsigned char *)&bytes,
Expand Down Expand Up @@ -1571,7 +1590,11 @@ _PyLong_AsUnsignedLongLongMask(PyObject *vv)
}
v = (PyLongObject *)vv;
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);
sign = _PyLong_NonCompactSign(v);
Expand Down Expand Up @@ -1643,7 +1666,18 @@ PyLong_AsLongLongAndOverflow(PyObject *vv, int *overflow)
do_decref = 1;
}
if (_PyLong_IsCompact(v)) {
#if SIZEOF_LONG_LONG < SIZEOF_SIZE_T
Py_ssize_t tmp = _PyLong_CompactValue(v);
if ((unsigned long long)(size_t)tmp != (size_t)tmp) {
*overflow = tmp < 0 ? -1 : 1;
res = -1;
}
else {
res = (long long)tmp;
}
#else
res = _PyLong_CompactValue(v);
#endif
}
else {
i = _PyLong_DigitCount(v);
Expand Down Expand Up @@ -3579,7 +3613,7 @@ long_hash(PyLongObject *v)
int sign;

if (_PyLong_IsCompact(v)) {
x = _PyLong_CompactValue(v);
x = (Py_uhash_t)_PyLong_CompactValue(v);
if (x == (Py_uhash_t)-1) {
x = (Py_uhash_t)-2;
}
Expand Down

0 comments on commit 0bc15a8

Please sign in to comment.