]> granicus.if.org Git - python/commitdiff
Fix _PyGen_yf()
authorVictor Stinner <victor.stinner@gmail.com>
Thu, 24 Nov 2016 21:33:01 +0000 (22:33 +0100)
committerVictor Stinner <victor.stinner@gmail.com>
Thu, 24 Nov 2016 21:33:01 +0000 (22:33 +0100)
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.

Misc/NEWS
Objects/genobject.c
Python/ceval.c

index b606101b8ca4b7024c798ac975c660ba67001f18..929ce5322b26195ec80d72c2547415a88cd89e5c 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -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
 -------
 
index 558f809b024d82ed21e2a9d2c6c713bf4c85d4cd..2680ab0e129da4bf8966156987032db5cc78400e 100644 (file)
@@ -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);
index 83296f637fcfa335824f7dec58567ba51b4258b5..d5172b9631f43d79f39c4b187151d0bf191f5f65 100644 (file)
@@ -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;
         }