Skip to content

Commit 1801545

Browse files
gh-121153: Fix some errors with use of _PyLong_CompactValue() (GH-121154)
* 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. * Fix integer overflow check in sum().
1 parent 0759cec commit 1801545

File tree

2 files changed

+57
-15
lines changed

2 files changed

+57
-15
lines changed

Objects/longobject.c

Lines changed: 55 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -483,11 +483,18 @@ PyLong_AsLongAndOverflow(PyObject *vv, int *overflow)
483483
do_decref = 1;
484484
}
485485
if (_PyLong_IsCompact(v)) {
486-
#if SIZEOF_LONG < SIZEOF_VOID_P
487-
intptr_t tmp = _PyLong_CompactValue(v);
488-
res = (long)tmp;
489-
if (res != tmp) {
490-
*overflow = tmp < 0 ? -1 : 1;
486+
#if SIZEOF_LONG < SIZEOF_SIZE_T
487+
Py_ssize_t tmp = _PyLong_CompactValue(v);
488+
if (tmp < LONG_MIN) {
489+
*overflow = -1;
490+
res = -1;
491+
}
492+
else if (tmp > LONG_MAX) {
493+
*overflow = 1;
494+
res = -1;
495+
}
496+
else {
497+
res = (long)tmp;
491498
}
492499
#else
493500
res = _PyLong_CompactValue(v);
@@ -632,14 +639,15 @@ PyLong_AsUnsignedLong(PyObject *vv)
632639

633640
v = (PyLongObject *)vv;
634641
if (_PyLong_IsNonNegativeCompact(v)) {
635-
#if SIZEOF_LONG < SIZEOF_VOID_P
636-
intptr_t tmp = _PyLong_CompactValue(v);
642+
#if SIZEOF_LONG < SIZEOF_SIZE_T
643+
size_t tmp = (size_t)_PyLong_CompactValue(v);
637644
unsigned long res = (unsigned long)tmp;
638645
if (res != tmp) {
639646
goto overflow;
640647
}
648+
return res;
641649
#else
642-
return _PyLong_CompactValue(v);
650+
return (unsigned long)(size_t)_PyLong_CompactValue(v);
643651
#endif
644652
}
645653
if (_PyLong_IsNegative(v)) {
@@ -685,7 +693,7 @@ PyLong_AsSize_t(PyObject *vv)
685693

686694
v = (PyLongObject *)vv;
687695
if (_PyLong_IsNonNegativeCompact(v)) {
688-
return _PyLong_CompactValue(v);
696+
return (size_t)_PyLong_CompactValue(v);
689697
}
690698
if (_PyLong_IsNegative(v)) {
691699
PyErr_SetString(PyExc_OverflowError,
@@ -722,7 +730,11 @@ _PyLong_AsUnsignedLongMask(PyObject *vv)
722730
}
723731
v = (PyLongObject *)vv;
724732
if (_PyLong_IsCompact(v)) {
725-
return (unsigned long)_PyLong_CompactValue(v);
733+
#if SIZEOF_LONG < SIZEOF_SIZE_T
734+
return (unsigned long)(size_t)_PyLong_CompactValue(v);
735+
#else
736+
return (unsigned long)(long)_PyLong_CompactValue(v);
737+
#endif
726738
}
727739
i = _PyLong_DigitCount(v);
728740
int sign = _PyLong_NonCompactSign(v);
@@ -1540,7 +1552,18 @@ PyLong_AsUnsignedLongLong(PyObject *vv)
15401552
v = (PyLongObject*)vv;
15411553
if (_PyLong_IsNonNegativeCompact(v)) {
15421554
res = 0;
1543-
bytes = _PyLong_CompactValue(v);
1555+
#if SIZEOF_LONG_LONG < SIZEOF_SIZE_T
1556+
size_t tmp = (size_t)_PyLong_CompactValue(v);
1557+
bytes = (unsigned long long)tmp;
1558+
if (bytes != tmp) {
1559+
PyErr_SetString(PyExc_OverflowError,
1560+
"Python int too large to convert "
1561+
"to C unsigned long long");
1562+
res = -1;
1563+
}
1564+
#else
1565+
bytes = (unsigned long long)(size_t)_PyLong_CompactValue(v);
1566+
#endif
15441567
}
15451568
else {
15461569
res = _PyLong_AsByteArray((PyLongObject *)vv, (unsigned char *)&bytes,
@@ -1571,7 +1594,11 @@ _PyLong_AsUnsignedLongLongMask(PyObject *vv)
15711594
}
15721595
v = (PyLongObject *)vv;
15731596
if (_PyLong_IsCompact(v)) {
1574-
return (unsigned long long)(signed long long)_PyLong_CompactValue(v);
1597+
#if SIZEOF_LONG_LONG < SIZEOF_SIZE_T
1598+
return (unsigned long long)(size_t)_PyLong_CompactValue(v);
1599+
#else
1600+
return (unsigned long long)(long long)_PyLong_CompactValue(v);
1601+
#endif
15751602
}
15761603
i = _PyLong_DigitCount(v);
15771604
sign = _PyLong_NonCompactSign(v);
@@ -1643,7 +1670,22 @@ PyLong_AsLongLongAndOverflow(PyObject *vv, int *overflow)
16431670
do_decref = 1;
16441671
}
16451672
if (_PyLong_IsCompact(v)) {
1673+
#if SIZEOF_LONG_LONG < SIZEOF_SIZE_T
1674+
Py_ssize_t tmp = _PyLong_CompactValue(v);
1675+
if (tmp < LLONG_MIN) {
1676+
*overflow = -1;
1677+
res = -1;
1678+
}
1679+
else if (tmp > LLONG_MAX) {
1680+
*overflow = 1;
1681+
res = -1;
1682+
}
1683+
else {
1684+
res = (long long)tmp;
1685+
}
1686+
#else
16461687
res = _PyLong_CompactValue(v);
1688+
#endif
16471689
}
16481690
else {
16491691
i = _PyLong_DigitCount(v);
@@ -3579,7 +3621,7 @@ long_hash(PyLongObject *v)
35793621
int sign;
35803622

35813623
if (_PyLong_IsCompact(v)) {
3582-
x = _PyLong_CompactValue(v);
3624+
x = (Py_uhash_t)_PyLong_CompactValue(v);
35833625
if (x == (Py_uhash_t)-1) {
35843626
x = (Py_uhash_t)-2;
35853627
}

Python/bltinmodule.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2644,8 +2644,8 @@ builtin_sum_impl(PyObject *module, PyObject *iterable, PyObject *start)
26442644
b = PyLong_AsLongAndOverflow(item, &overflow);
26452645
}
26462646
if (overflow == 0 &&
2647-
(i_result >= 0 ? (b <= LONG_MAX - i_result)
2648-
: (b >= LONG_MIN - i_result)))
2647+
(i_result >= 0 ? (b <= PY_SSIZE_T_MAX - i_result)
2648+
: (b >= PY_SSIZE_T_MIN - i_result)))
26492649
{
26502650
i_result += b;
26512651
Py_DECREF(item);

0 commit comments

Comments
 (0)