Commit 83195c3f authored by Benjamin Peterson's avatar Benjamin Peterson

restore a generator's caller's exception state both on yield and (last) return

This prevents generator exception state from leaking into the caller.

Closes #12475.
parent c77eccd6
......@@ -566,6 +566,21 @@ class ExceptionTests(unittest.TestCase):
del g
self.assertEqual(sys.exc_info()[0], TypeError)
def test_generator_leaking2(self):
# See issue 12475.
def g():
yield
try:
raise RuntimeError
except RuntimeError:
it = g()
next(it)
try:
next(it)
except StopIteration:
pass
self.assertEqual(sys.exc_info(), (None, None, None))
def test_generator_finalizing_and_exc_info(self):
# See #7173
def simple_gen():
......
......@@ -10,6 +10,9 @@ What's New in Python 3.2.2?
Core and Builtins
-----------------
- Issue #12475: Prevent generators from leaking their exception state into the
callers frame as they return for the last time.
Library
-------
......
......@@ -1881,10 +1881,6 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
retval = POP();
f->f_stacktop = stack_pointer;
why = WHY_YIELD;
/* Put aside the current exception state and restore
that of the calling frame. This only serves when
"yield" is used inside an except handler. */
SWAP_EXC_STATE();
goto fast_yield;
TARGET(POP_EXCEPT)
......@@ -3021,6 +3017,11 @@ fast_block_end:
retval = NULL;
fast_yield:
if (co->co_flags & CO_GENERATOR && (why == WHY_YIELD || why == WHY_RETURN))
/* Put aside the current exception state and restore that of the
calling frame. */
SWAP_EXC_STATE();
if (tstate->use_tracing) {
if (tstate->c_tracefunc) {
if (why == WHY_RETURN || why == WHY_YIELD) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment