File tree Expand file tree Collapse file tree 3 files changed +33
-0
lines changed
Misc/NEWS.d/next/Core and Builtins Expand file tree Collapse file tree 3 files changed +33
-0
lines changed Original file line number Diff line number Diff line change 22
33import sys
44import unittest
5+ import gc
56from test .support import run_unittest , cpython_only
67from test .support .os_helper import TESTFN , unlink
78from test .support import check_free_after_iterating , ALWAYS_EQ , NEVER_EQ
@@ -1036,6 +1037,25 @@ def test_error_iter(self):
10361037 self .assertRaises (TypeError , iter , typ ())
10371038 self .assertRaises (ZeroDivisionError , iter , BadIterableClass ())
10381039
1040+ def test_access_result_tuple_while_iterating (self ):
1041+ TAG = object ()
1042+
1043+ def monitor ():
1044+ lst = [x for x in gc .get_referrers (TAG ) if isinstance (x , tuple )]
1045+ # This would be the result tuple if is accessible mid-iteration
1046+ t = lst [0 ]
1047+ print (t )
1048+ return t
1049+
1050+ def my_iter ():
1051+ yield TAG
1052+ t = monitor ()
1053+ breakpoint ()
1054+ for x in range (10 ):
1055+ yield x
1056+
1057+ self .assertRaises (IndexError , tuple , my_iter ())
1058+
10391059
10401060def test_main ():
10411061 run_unittest (TestCase )
Original file line number Diff line number Diff line change 1+ Fixed an issue that could cause a crash when accessing an incomplete tuple
2+ when collecting an iterable into a :class: `tuple ` using :c:func: `PySequence_Tuple `.
3+ Patch by Pablo Galindo.
Original file line number Diff line number Diff line change @@ -1993,6 +1993,9 @@ PySequence_Tuple(PyObject *v)
19931993 if (result == NULL )
19941994 goto Fail ;
19951995
1996+ // bpo-15108: Code can access the result tuple while being
1997+ // incomplete when calling PyIter_Next().
1998+ PyObject_GC_UnTrack (result );
19961999 /* Fill the tuple. */
19972000 for (j = 0 ; ; ++ j ) {
19982001 PyObject * item = PyIter_Next (it );
@@ -2022,10 +2025,17 @@ PySequence_Tuple(PyObject *v)
20222025 Py_DECREF (item );
20232026 goto Fail ;
20242027 }
2028+ // Resizing could track the tuple again
2029+ PyObject_GC_UnTrack (result );
20252030 }
20262031 PyTuple_SET_ITEM (result , j , item );
20272032 }
20282033
2034+ // No more calls can go back into Python, so is safe
2035+ // to re-track the tuple.
2036+
2037+ PyObject_GC_Track (result );
2038+
20292039 /* Cut tuple back if guess was too large. */
20302040 if (j < n &&
20312041 _PyTuple_Resize (& result , j ) != 0 )
You can’t perform that action at this time.
0 commit comments