diff options
author | Victor Stinner <victor.stinner@gmail.com> | 2016-11-24 21:33:01 (GMT) |
---|---|---|
committer | Victor Stinner <victor.stinner@gmail.com> | 2016-11-24 21:33:01 (GMT) |
commit | f7d199ff329f0cb68f367c7aa169e058b2ab50f4 (patch) | |
tree | fd33432812139614d49b9c45c47994231c75d96c | |
parent | b3c5dc912daaec0f1f64dd05f5e49bfe9755fdb9 (diff) | |
download | cpython-f7d199ff329f0cb68f367c7aa169e058b2ab50f4.zip cpython-f7d199ff329f0cb68f367c7aa169e058b2ab50f4.tar.gz cpython-f7d199ff329f0cb68f367c7aa169e058b2ab50f4.tar.bz2 |
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.
-rw-r--r-- | Misc/NEWS | 4 | ||||
-rw-r--r-- | Objects/genobject.c | 9 | ||||
-rw-r--r-- | Python/ceval.c | 1 |
3 files changed, 14 insertions, 0 deletions
@@ -10,6 +10,10 @@ What's New in Python 3.6.0 release candidate 1 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 ------- diff --git a/Objects/genobject.c b/Objects/genobject.c index 558f809..2680ab0 100644 --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -355,6 +355,14 @@ _PyGen_yf(PyGenObject *gen) PyObject *bytecode = f->f_code->co_code; 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) return NULL; yf = f->f_stacktop[-1]; @@ -463,6 +471,7 @@ _gen_throw(PyGenObject *gen, int close_on_genexit, assert(ret == yf); Py_DECREF(ret); /* Termination repetition of YIELD_FROM */ + assert(gen->gi_frame->f_lasti >= 0); gen->gi_frame->f_lasti += sizeof(_Py_CODEUNIT); if (_PyGen_FetchStopIterationValue(&val) == 0) { ret = gen_send_ex(gen, val, 0, 0); diff --git a/Python/ceval.c b/Python/ceval.c index 83296f6..d5172b9 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2043,6 +2043,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) f->f_stacktop = stack_pointer; why = WHY_YIELD; /* and repeat... */ + assert(f->f_lasti >= (int)sizeof(_Py_CODEUNIT)); f->f_lasti -= sizeof(_Py_CODEUNIT); goto fast_yield; } |