[3.14] gh-91153: prevent a crash in bytearray.__setitem__(ind, ...) when ind.__index__ has side-effects (GH-132379) (#136581)

gh-91153: prevent a crash in `bytearray.__setitem__(ind, ...)` when `ind.__index__` has side-effects (GH-132379)
(cherry picked from commit 5e1e21dee3)

Co-authored-by: Bast <52266665+bast0006@users.noreply.github.com>
Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
This commit is contained in:
Miss Islington (bot) 2025-07-12 16:38:57 +02:00 committed by GitHub
parent c71ecd1418
commit d5866a8e84
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 42 additions and 2 deletions

View file

@ -1899,6 +1899,8 @@ class ByteArrayTest(BaseBytesTest, unittest.TestCase):
self.assertEqual(b3, b'xcxcxc')
def test_mutating_index(self):
# bytearray slice assignment can call into python code
# that reallocates the internal buffer
# See gh-91153
class Boom:
@ -1916,6 +1918,39 @@ class ByteArrayTest(BaseBytesTest, unittest.TestCase):
with self.assertRaises(IndexError):
self._testlimitedcapi.sequence_setitem(b, 0, Boom())
def test_mutating_index_inbounds(self):
# gh-91153 continued
# Ensure buffer is not broken even if length is correct
class MutatesOnIndex:
def __init__(self):
self.ba = bytearray(0x180)
def __index__(self):
self.ba.clear()
self.new_ba = bytearray(0x180) # to catch out-of-bounds writes
self.ba.extend([0] * 0x180) # to check bounds checks
return 0
with self.subTest("skip_bounds_safety"):
instance = MutatesOnIndex()
instance.ba[instance] = ord("?")
self.assertEqual(instance.ba[0], ord("?"), "Assigned bytearray not altered")
self.assertEqual(instance.new_ba, bytearray(0x180), "Wrong object altered")
with self.subTest("skip_bounds_safety_capi"):
instance = MutatesOnIndex()
instance.ba[instance] = ord("?")
self._testlimitedcapi.sequence_setitem(instance.ba, instance, ord("?"))
self.assertEqual(instance.ba[0], ord("?"), "Assigned bytearray not altered")
self.assertEqual(instance.new_ba, bytearray(0x180), "Wrong object altered")
with self.subTest("skip_bounds_safety_slice"):
instance = MutatesOnIndex()
instance.ba[instance:1] = [ord("?")]
self.assertEqual(instance.ba[0], ord("?"), "Assigned bytearray not altered")
self.assertEqual(instance.new_ba, bytearray(0x180), "Wrong object altered")
class AssortedBytesTest(unittest.TestCase):
#