Skip to content

Commit 0bc15a8

Browse files
gh-121153: Fix some errors with use of _PyLong_CompactValue()
* 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.
1 parent 2cb84b1 commit 0bc15a8

File tree

1 file changed

+46
-12
lines changed

1 file changed

+46
-12
lines changed

Objects/longobject.c

Lines changed: 46 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -483,11 +483,14 @@ 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) {
486+
#if SIZEOF_LONG < SIZEOF_SIZE_T
487+
Py_ssize_t tmp = _PyLong_CompactValue(v);
488+
if ((unsigned long)(size_t)tmp != (size_t)tmp) {
490489
*overflow = tmp < 0 ? -1 : 1;
490+
res = -1;
491+
}
492+
else {
493+
res = (long)tmp;
491494
}
492495
#else
493496
res = _PyLong_CompactValue(v);
@@ -632,14 +635,14 @@ PyLong_AsUnsignedLong(PyObject *vv)
632635

633636
v = (PyLongObject *)vv;
634637
if (_PyLong_IsNonNegativeCompact(v)) {
635-
#if SIZEOF_LONG < SIZEOF_VOID_P
636-
intptr_t tmp = _PyLong_CompactValue(v);
638+
#if SIZEOF_LONG < SIZEOF_SIZE_T
639+
size_t tmp = (size_t)_PyLong_CompactValue(v);
637640
unsigned long res = (unsigned long)tmp;
638641
if (res != tmp) {
639642
goto overflow;
640643
}
641644
#else
642-
return _PyLong_CompactValue(v);
645+
return (unsigned long)(size_t)_PyLong_CompactValue(v);
643646
#endif
644647
}
645648
if (_PyLong_IsNegative(v)) {
@@ -685,7 +688,7 @@ PyLong_AsSize_t(PyObject *vv)
685688

686689
v = (PyLongObject *)vv;
687690
if (_PyLong_IsNonNegativeCompact(v)) {
688-
return _PyLong_CompactValue(v);
691+
return (size_t)_PyLong_CompactValue(v);
689692
}
690693
if (_PyLong_IsNegative(v)) {
691694
PyErr_SetString(PyExc_OverflowError,
@@ -722,7 +725,11 @@ _PyLong_AsUnsignedLongMask(PyObject *vv)
722725
}
723726
v = (PyLongObject *)vv;
724727
if (_PyLong_IsCompact(v)) {
725-
return (unsigned long)_PyLong_CompactValue(v);
728+
#if SIZEOF_LONG < SIZEOF_SIZE_T
729+
return (unsigned long)(size_t)_PyLong_CompactValue(v);
730+
#else
731+
return (unsigned long)(long)_PyLong_CompactValue(v);
732+
#endif
726733
}
727734
i = _PyLong_DigitCount(v);
728735
int sign = _PyLong_NonCompactSign(v);
@@ -1540,7 +1547,19 @@ PyLong_AsUnsignedLongLong(PyObject *vv)
15401547
v = (PyLongObject*)vv;
15411548
if (_PyLong_IsNonNegativeCompact(v)) {
15421549
res = 0;
1543-
bytes = _PyLong_CompactValue(v);
1550+
bytes = (unsigned long long)(size_t)_PyLong_CompactValue(v);
1551+
#if SIZEOF_LONG_LONG < SIZEOF_SIZE_T
1552+
size_t tmp = (size_t)_PyLong_CompactValue(v);
1553+
bytes = (unsigned long long)tmp;
1554+
if (bytes != tmp) {
1555+
PyErr_SetString(PyExc_OverflowError,
1556+
"Python int too large to convert "
1557+
"to C unsigned long long");
1558+
res = -1;
1559+
}
1560+
#else
1561+
bytes = (unsigned long long)(size_t)_PyLong_CompactValue(v);
1562+
#endif
15441563
}
15451564
else {
15461565
res = _PyLong_AsByteArray((PyLongObject *)vv, (unsigned char *)&bytes,
@@ -1571,7 +1590,11 @@ _PyLong_AsUnsignedLongLongMask(PyObject *vv)
15711590
}
15721591
v = (PyLongObject *)vv;
15731592
if (_PyLong_IsCompact(v)) {
1574-
return (unsigned long long)(signed long long)_PyLong_CompactValue(v);
1593+
#if SIZEOF_LONG_LONG < SIZEOF_SIZE_T
1594+
return (unsigned long long)(size_t)_PyLong_CompactValue(v);
1595+
#else
1596+
return (unsigned long long)(long long)_PyLong_CompactValue(v);
1597+
#endif
15751598
}
15761599
i = _PyLong_DigitCount(v);
15771600
sign = _PyLong_NonCompactSign(v);
@@ -1643,7 +1666,18 @@ PyLong_AsLongLongAndOverflow(PyObject *vv, int *overflow)
16431666
do_decref = 1;
16441667
}
16451668
if (_PyLong_IsCompact(v)) {
1669+
#if SIZEOF_LONG_LONG < SIZEOF_SIZE_T
1670+
Py_ssize_t tmp = _PyLong_CompactValue(v);
1671+
if ((unsigned long long)(size_t)tmp != (size_t)tmp) {
1672+
*overflow = tmp < 0 ? -1 : 1;
1673+
res = -1;
1674+
}
1675+
else {
1676+
res = (long long)tmp;
1677+
}
1678+
#else
16461679
res = _PyLong_CompactValue(v);
1680+
#endif
16471681
}
16481682
else {
16491683
i = _PyLong_DigitCount(v);
@@ -3579,7 +3613,7 @@ long_hash(PyLongObject *v)
35793613
int sign;
35803614

35813615
if (_PyLong_IsCompact(v)) {
3582-
x = _PyLong_CompactValue(v);
3616+
x = (Py_uhash_t)_PyLong_CompactValue(v);
35833617
if (x == (Py_uhash_t)-1) {
35843618
x = (Py_uhash_t)-2;
35853619
}

0 commit comments

Comments
 (0)