Commit 854c3032 authored by Victor Stinner's avatar Victor Stinner

Fix _PyGen_yf()

Issue #28782: Fix a bug in the implementation ``yield from`` when checking
if the next instruction is YIELD_FROM. Regression introduced by WORDCODE
(issue #26647).

Reviewed by Serhiy Storchaka and Yury Selivanov.
parent a7be82a1
...@@ -10,6 +10,10 @@ What's New in Python 3.6.0 release candidate 1 ...@@ -10,6 +10,10 @@ What's New in Python 3.6.0 release candidate 1
Core and Builtins Core and Builtins
----------------- -----------------
- Issue #28782: Fix a bug in the implementation ``yield from`` when checking
if the next instruction is YIELD_FROM. Regression introduced by WORDCODE
(issue #26647).
Library Library
------- -------
......
...@@ -355,6 +355,14 @@ _PyGen_yf(PyGenObject *gen) ...@@ -355,6 +355,14 @@ _PyGen_yf(PyGenObject *gen)
PyObject *bytecode = f->f_code->co_code; PyObject *bytecode = f->f_code->co_code;
unsigned char *code = (unsigned char *)PyBytes_AS_STRING(bytecode); unsigned char *code = (unsigned char *)PyBytes_AS_STRING(bytecode);
if (f->f_lasti < 0) {
/* Return immediately if the frame didn't start yet. YIELD_FROM
always come after LOAD_CONST: a code object should not start
with YIELD_FROM */
assert(code[0] != YIELD_FROM);
return NULL;
}
if (code[f->f_lasti + sizeof(_Py_CODEUNIT)] != YIELD_FROM) if (code[f->f_lasti + sizeof(_Py_CODEUNIT)] != YIELD_FROM)
return NULL; return NULL;
yf = f->f_stacktop[-1]; yf = f->f_stacktop[-1];
...@@ -463,6 +471,7 @@ _gen_throw(PyGenObject *gen, int close_on_genexit, ...@@ -463,6 +471,7 @@ _gen_throw(PyGenObject *gen, int close_on_genexit,
assert(ret == yf); assert(ret == yf);
Py_DECREF(ret); Py_DECREF(ret);
/* Termination repetition of YIELD_FROM */ /* Termination repetition of YIELD_FROM */
assert(gen->gi_frame->f_lasti >= 0);
gen->gi_frame->f_lasti += sizeof(_Py_CODEUNIT); gen->gi_frame->f_lasti += sizeof(_Py_CODEUNIT);
if (_PyGen_FetchStopIterationValue(&val) == 0) { if (_PyGen_FetchStopIterationValue(&val) == 0) {
ret = gen_send_ex(gen, val, 0, 0); ret = gen_send_ex(gen, val, 0, 0);
......
...@@ -2043,6 +2043,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) ...@@ -2043,6 +2043,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
f->f_stacktop = stack_pointer; f->f_stacktop = stack_pointer;
why = WHY_YIELD; why = WHY_YIELD;
/* and repeat... */ /* and repeat... */
assert(f->f_lasti >= (int)sizeof(_Py_CODEUNIT));
f->f_lasti -= sizeof(_Py_CODEUNIT); f->f_lasti -= sizeof(_Py_CODEUNIT);
goto fast_yield; goto fast_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