https://github.com/python/cpython/commit/ae62786a27d2f7a37bbc09073742595c5db0453e
commit: ae62786a27d2f7a37bbc09073742595c5db0453e
branch: 3.15
author: Miss Islington (bot) <[email protected]>
committer: gpshead <[email protected]>
date: 2026-10-22T04:24:40Z
summary:

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

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.
(cherry picked from commit d4750a77519d9936da875953d85e07a851a1d8cd)

Co-authored-by: Gregory P. Smith <[email protected]>

files:
A 
Misc/NEWS.d/next/Core_and_Builtins/2026-10-22-00-30-21.gh-issue-160162.lShf32.rst
M Lib/test/test_long.py
M Objects/longobject.c

diff --git a/Lib/test/test_long.py b/Lib/test/test_long.py
index b48a8812a1a2d1..7c368e121024d2 100644
--- a/Lib/test/test_long.py
+++ b/Lib/test/test_long.py
@@ -996,6 +996,16 @@ def test_huge_lshift(self, size):
         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)
diff --git 
a/Misc/NEWS.d/next/Core_and_Builtins/2026-10-22-00-30-21.gh-issue-160162.lShf32.rst
 
b/Misc/NEWS.d/next/Core_and_Builtins/2026-10-22-00-30-21.gh-issue-160162.lShf32.rst
new file mode 100644
index 00000000000000..5aa2021bddd44e
--- /dev/null
+++ 
b/Misc/NEWS.d/next/Core_and_Builtins/2026-10-22-00-30-21.gh-issue-160162.lShf32.rst
@@ -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.
diff --git a/Objects/longobject.c b/Objects/longobject.c
index ec4368b87a247d..34e09e10884ab0 100644
--- a/Objects/longobject.c
+++ b/Objects/longobject.c
@@ -5530,7 +5530,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;

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to