Skip to content

Commit 5a6872f

Browse files
pythongh-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 5a6872f

File tree

1 file changed

+45
-12
lines changed

1 file changed

+45
-12
lines changed

Objects/longobject.c

Lines changed: 45 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,18 @@ PyLong_AsUnsignedLongLong(PyObject *vv)
15401547
v = (PyLongObject*)vv;
15411548
if (_PyLong_IsNonNegativeCompact(v)) {
15421549
res = 0;
1543-
bytes = _PyLong_CompactValue(v);
1550+
#if SIZEOF_LONG_LONG < SIZEOF_SIZE_T
1551+
size_t tmp = (size_t)_PyLong_CompactValue(v);
1552+
bytes = (unsigned long long)tmp;
1553+
if (bytes != tmp) {
1554+
PyErr_SetString(PyExc_OverflowError,
1555+
"Python int too large to convert "
1556+
"to C unsigned long long");
1557+
res = -1;
1558+
}
1559+
#else
1560+
bytes = (unsigned long long)(size_t)_PyLong_CompactValue(v);
1561+
#endif
15441562
}
15451563
else {
15461564
res = _PyLong_AsByteArray((PyLongObject *)vv, (unsigned char *)&bytes,
@@ -1571,7 +1589,11 @@ _PyLong_AsUnsignedLongLongMask(PyObject *vv)
15711589
}
15721590
v = (PyLongObject *)vv;
15731591
if (_PyLong_IsCompact(v)) {
1574-
return (unsigned long long)(signed long long)_PyLong_CompactValue(v);
1592+
#if SIZEOF_LONG_LONG < SIZEOF_SIZE_T
1593+
return (unsigned long long)(size_t)_PyLong_CompactValue(v);
1594+
#else
1595+
return (unsigned long long)(long long)_PyLong_CompactValue(v);
1596+
#endif
15751597
}
15761598
i = _PyLong_DigitCount(v);
15771599
sign = _PyLong_NonCompactSign(v);
@@ -1643,7 +1665,18 @@ PyLong_AsLongLongAndOverflow(PyObject *vv, int *overflow)
16431665
do_decref = 1;
16441666
}
16451667
if (_PyLong_IsCompact(v)) {
1668+
#if SIZEOF_LONG_LONG < SIZEOF_SIZE_T
1669+
Py_ssize_t tmp = _PyLong_CompactValue(v);
1670+
if ((unsigned long long)(size_t)tmp != (size_t)tmp) {
1671+
*overflow = tmp < 0 ? -1 : 1;
1672+
res = -1;
1673+
}
1674+
else {
1675+
res = (long long)tmp;
1676+
}
1677+
#else
16461678
res = _PyLong_CompactValue(v);
1679+
#endif
16471680
}
16481681
else {
16491682
i = _PyLong_DigitCount(v);
@@ -3579,7 +3612,7 @@ long_hash(PyLongObject *v)
35793612
int sign;
35803613

35813614
if (_PyLong_IsCompact(v)) {
3582-
x = _PyLong_CompactValue(v);
3615+
x = (Py_uhash_t)_PyLong_CompactValue(v);
35833616
if (x == (Py_uhash_t)-1) {
35843617
x = (Py_uhash_t)-2;
35853618
}

0 commit comments

Comments
 (0)