Skip to content

Commit 09ff4ec

Browse files
[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)
1 parent d358f74 commit 09ff4ec

File tree

2 files changed

+57
-15
lines changed

2 files changed

+57
-15
lines changed

Objects/longobject.c

+55-13
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);
@@ -1528,7 +1540,18 @@ PyLong_AsUnsignedLongLong(PyObject *vv)
15281540
v = (PyLongObject*)vv;
15291541
if (_PyLong_IsNonNegativeCompact(v)) {
15301542
res = 0;
1531-
bytes = _PyLong_CompactValue(v);
1543+
#if SIZEOF_LONG_LONG < SIZEOF_SIZE_T
1544+
size_t tmp = (size_t)_PyLong_CompactValue(v);
1545+
bytes = (unsigned long long)tmp;
1546+
if (bytes != tmp) {
1547+
PyErr_SetString(PyExc_OverflowError,
1548+
"Python int too large to convert "
1549+
"to C unsigned long long");
1550+
res = -1;
1551+
}
1552+
#else
1553+
bytes = (unsigned long long)(size_t)_PyLong_CompactValue(v);
1554+
#endif
15321555
}
15331556
else {
15341557
res = _PyLong_AsByteArray((PyLongObject *)vv, (unsigned char *)&bytes,
@@ -1559,7 +1582,11 @@ _PyLong_AsUnsignedLongLongMask(PyObject *vv)
15591582
}
15601583
v = (PyLongObject *)vv;
15611584
if (_PyLong_IsCompact(v)) {
1562-
return (unsigned long long)(signed long long)_PyLong_CompactValue(v);
1585+
#if SIZEOF_LONG_LONG < SIZEOF_SIZE_T
1586+
return (unsigned long long)(size_t)_PyLong_CompactValue(v);
1587+
#else
1588+
return (unsigned long long)(long long)_PyLong_CompactValue(v);
1589+
#endif
15631590
}
15641591
i = _PyLong_DigitCount(v);
15651592
sign = _PyLong_NonCompactSign(v);
@@ -1631,7 +1658,22 @@ PyLong_AsLongLongAndOverflow(PyObject *vv, int *overflow)
16311658
do_decref = 1;
16321659
}
16331660
if (_PyLong_IsCompact(v)) {
1661+
#if SIZEOF_LONG_LONG < SIZEOF_SIZE_T
1662+
Py_ssize_t tmp = _PyLong_CompactValue(v);
1663+
if (tmp < LLONG_MIN) {
1664+
*overflow = -1;
1665+
res = -1;
1666+
}
1667+
else if (tmp > LLONG_MAX) {
1668+
*overflow = 1;
1669+
res = -1;
1670+
}
1671+
else {
1672+
res = (long long)tmp;
1673+
}
1674+
#else
16341675
res = _PyLong_CompactValue(v);
1676+
#endif
16351677
}
16361678
else {
16371679
i = _PyLong_DigitCount(v);
@@ -3568,7 +3610,7 @@ long_hash(PyLongObject *v)
35683610
int sign;
35693611

35703612
if (_PyLong_IsCompact(v)) {
3571-
x = _PyLong_CompactValue(v);
3613+
x = (Py_uhash_t)_PyLong_CompactValue(v);
35723614
if (x == (Py_uhash_t)-1) {
35733615
x = (Py_uhash_t)-2;
35743616
}

Python/bltinmodule.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -2601,8 +2601,8 @@ builtin_sum_impl(PyObject *module, PyObject *iterable, PyObject *start)
26012601
b = PyLong_AsLongAndOverflow(item, &overflow);
26022602
}
26032603
if (overflow == 0 &&
2604-
(i_result >= 0 ? (b <= LONG_MAX - i_result)
2605-
: (b >= LONG_MIN - i_result)))
2604+
(i_result >= 0 ? (b <= PY_SSIZE_T_MAX - i_result)
2605+
: (b >= PY_SSIZE_T_MIN - i_result)))
26062606
{
26072607
i_result += b;
26082608
Py_DECREF(item);

0 commit comments

Comments
 (0)