GH-127058: Make PySequence_Tuple safer and probably faster. (#127758)

* Use a small buffer, then list when constructing a tuple from an arbitrary sequence.
This commit is contained in:
Mark Shannon 2024-12-11 14:02:59 +00:00 committed by GitHub
parent 359389ed51
commit 5a23994a3d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 88 additions and 48 deletions

View file

@ -1,5 +1,6 @@
import unittest
import sys
import gc
from collections import namedtuple
from test.support import import_helper
@ -257,5 +258,29 @@ class CAPITest(unittest.TestCase):
self.assertRaises(SystemError, resize, [1, 2, 3], 0, False)
self.assertRaises(SystemError, resize, NULL, 0, False)
def test_bug_59313(self):
# Before 3.14, the C-API function PySequence_Tuple
# would create incomplete tuples which were visible to
# the cycle GC, and this test would crash the interpeter.
TAG = object()
tuples = []
def referrer_tuples():
return [x for x in gc.get_referrers(TAG)
if isinstance(x, tuple)]
def my_iter():
nonlocal tuples
yield TAG # 'tag' gets stored in the result tuple
tuples += referrer_tuples()
for x in range(10):
tuples += referrer_tuples()
# Prior to 3.13 would raise a SystemError when the tuple needs to be resized
yield x
self.assertEqual(tuple(my_iter()), (TAG, *range(10)))
self.assertEqual(tuples, [])
if __name__ == "__main__":
unittest.main()