diff --git a/Lib/test/test_grammar.py b/Lib/test/test_grammar.py index 78d94593c7f322..87c0c7493f19c8 100644 --- a/Lib/test/test_grammar.py +++ b/Lib/test/test_grammar.py @@ -969,6 +969,17 @@ def test_continue_in_finally(self): break self.assertEqual(count, 1) + + def _wrap(): + for number in range(2): + try: + return number + finally: + continue + + with self.assertRaises(RuntimeError): + _wrap() + def test_return_in_finally(self): def g1(): try: diff --git a/Lib/test/test_iter.py b/Lib/test/test_iter.py index 6aceda23e9bd82..ccb36fab01ecd5 100644 --- a/Lib/test/test_iter.py +++ b/Lib/test/test_iter.py @@ -983,7 +983,7 @@ def __next__(self): try: for i in BadIterator() : pass - except TypeError: + except RuntimeError: pass def test_extending_list_with_iterator_does_not_segfault(self): diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-08-12-12-34-32.bpo-37830._W5oAZ.rst b/Misc/NEWS.d/next/Core and Builtins/2019-08-12-12-34-32.bpo-37830._W5oAZ.rst new file mode 100644 index 00000000000000..945fde91031f57 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-08-12-12-34-32.bpo-37830._W5oAZ.rst @@ -0,0 +1,2 @@ +Raise `RuntimeError` instead of getting seg fault on special cases like +returning inside of a try also using continue inside of finally. diff --git a/Python/ceval.c b/Python/ceval.c index 7c7359166dad91..8c8755b028e5d1 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3195,6 +3195,15 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) PREDICTED(FOR_ITER); /* before: [iter]; after: [iter, iter()] *or* [] */ PyObject *iter = TOP(); + if (!PyIter_Check(iter)){ + iter = POP(); + Py_CLEAR(iter); + _PyErr_SetString(tstate, PyExc_RuntimeError, + "cannot use continue inside of a finally " + "if you are returning the iterated value " + "inside try"); + goto error; + } PyObject *next = (*iter->ob_type->tp_iternext)(iter); if (next != NULL) { PUSH(next);