mirror of
https://github.com/python/cpython.git
synced 2026-10-28 10:25:05 +08:00
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:
1 parent
c1c4c18dfc
commit
d4750a7751
3 files changed
+16
-1
No files matched your search
@@ -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.
|
||||
@@ -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;
|
||||
|
||||
Reference in new issue
Block a user