gh-160162: Fix crash in int left shift with huge count on 32-bit (GH-160163)

Bound the shift count by MAX_LONG_DIGITS*PyLong_SHIFT instead of
PY_SSIZE_T_MAX*PyLong_SHIFT, so that the result size computed in
long_lshift1() cannot overflow Py_ssize_t.
This commit is contained in:
Gregory P. Smith authored and GitHub committed 2026-10-21 20:50:05 -07:00
1 parent c1c4c18dfc
commit d4750a7751
3 files changed
+16 -1

No files matched your search

+10
View File
@@ -996,6 +996,16 @@ class LongTest(unittest.TestCase):
self.assertEqual(v.bit_count(), 2)
self.assertEqual(v >> size, 5)
@support.cpython_only
def test_huge_lshift_overflow(self):
# The number of digits of the result doesn't fit in Py_ssize_t.
for a in 1, -1, 1 << SHIFT, -1 << SHIFT, 1 << 10*SHIFT:
for ndigits in range(sys.maxsize - 12, sys.maxsize + 1):
for shift in ndigits*SHIFT - 1, ndigits*SHIFT:
with self.subTest(a=a, shift=shift):
with self.assertRaises(OverflowError):
a << shift
def test_huge_rshift(self):
huge_shift = 1 << 1000
self.assertEqual(42 >> huge_shift, 0)
@@ -0,0 +1,3 @@
Fix a crash on 32-bit platforms when left shifting an :class:`int` by a
count close to ``sys.maxsize * sys.int_info.bits_per_digit``.
:exc:`OverflowError` is now raised, as for other too large counts.
+3 -1
View File
@@ -5527,7 +5527,9 @@ long_lshift_int64(PyLongObject *a, int64_t shiftby)
return PyLong_FromLong(0);
}
#if PY_SSIZE_T_MAX <= INT64_MAX / PyLong_SHIFT
if (shiftby > (int64_t)PY_SSIZE_T_MAX * PyLong_SHIFT) {
/* Keep wordshift <= MAX_LONG_DIGITS, so that oldsize + wordshift
cannot overflow Py_ssize_t in long_lshift1(). */
if (shiftby > (int64_t)MAX_LONG_DIGITS * PyLong_SHIFT) {
PyErr_SetString(PyExc_OverflowError,
"too many digits in integer");
return NULL;