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 2
2
3
3
import sys
4
4
import unittest
5
+ import gc
5
6
from test .support import run_unittest , cpython_only
6
7
from test .support .os_helper import TESTFN , unlink
7
8
from test .support import check_free_after_iterating , ALWAYS_EQ , NEVER_EQ
@@ -1036,6 +1037,25 @@ def test_error_iter(self):
1036
1037
self .assertRaises (TypeError , iter , typ ())
1037
1038
self .assertRaises (ZeroDivisionError , iter , BadIterableClass ())
1038
1039
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
+
1039
1059
1040
1060
def test_main ():
1041
1061
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)
1993
1993
if (result == NULL )
1994
1994
goto Fail ;
1995
1995
1996
+ // bpo-15108: Code can access the result tuple while being
1997
+ // incomplete when calling PyIter_Next().
1998
+ PyObject_GC_UnTrack (result );
1996
1999
/* Fill the tuple. */
1997
2000
for (j = 0 ; ; ++ j ) {
1998
2001
PyObject * item = PyIter_Next (it );
@@ -2022,10 +2025,17 @@ PySequence_Tuple(PyObject *v)
2022
2025
Py_DECREF (item );
2023
2026
goto Fail ;
2024
2027
}
2028
+ // Resizing could track the tuple again
2029
+ PyObject_GC_UnTrack (result );
2025
2030
}
2026
2031
PyTuple_SET_ITEM (result , j , item );
2027
2032
}
2028
2033
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
+
2029
2039
/* Cut tuple back if guess was too large. */
2030
2040
if (j < n &&
2031
2041
_PyTuple_Resize (& result , j ) != 0 )
You can’t perform that action at this time.
0 commit comments