diff options
| author | Serhiy Storchaka <storchaka@gmail.com> | 2018-03-11 08:32:47 +0200 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-03-11 08:32:47 +0200 | 
| commit | 26c9f565d016db21257a60d29ab2c99383dd5ac7 (patch) | |
| tree | faaef311a9bfff6549d59eb6149d562c22eab01c /Objects/frameobject.c | |
| parent | 51302a5fcc557e6afc0bf1e3b371f5f37c76dc77 (diff) | |
| download | cpython-git-26c9f565d016db21257a60d29ab2c99383dd5ac7.tar.gz | |
bpo-33026: Fix jumping out of "with" block by setting f_lineno. (#6026)
Diffstat (limited to 'Objects/frameobject.c')
| -rw-r--r-- | Objects/frameobject.c | 24 | 
1 files changed, 15 insertions, 9 deletions
| diff --git a/Objects/frameobject.c b/Objects/frameobject.c index b9f380d7b6..31ad8d0be2 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -89,7 +89,6 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno)      long l_new_lineno;      int overflow;      int new_lasti = 0;                  /* The new value of f_lasti */ -    int new_iblock = 0;                 /* The new value of f_iblock */      unsigned char *code = NULL;         /* The bytecode for the frame... */      Py_ssize_t code_len = 0;            /* ...and its length */      unsigned char *lnotab = NULL;       /* Iterating over co_lnotab */ @@ -99,6 +98,7 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno)      int addr = 0;                       /* (ditto) */      int delta_iblock = 0;               /* Scanning the SETUPs and POPs */      int for_loop_delta = 0;             /* (ditto) */ +    int delta;      int blockstack[CO_MAXBLOCKS];       /* Walking the 'finally' blocks */      int blockstack_top = 0;             /* (ditto) */ @@ -258,19 +258,25 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno)      assert(blockstack_top == 0);      /* Pop any blocks that we're jumping out of. */ -    new_iblock = f->f_iblock - delta_iblock; -    while (f->f_iblock > new_iblock) { -        PyTryBlock *b = &f->f_blockstack[--f->f_iblock]; -        while ((f->f_stacktop - f->f_valuestack) > b->b_level) { -            PyObject *v = (*--f->f_stacktop); -            Py_DECREF(v); +    delta = 0; +    if (delta_iblock > 0) { +        f->f_iblock -= delta_iblock; +        PyTryBlock *b = &f->f_blockstack[f->f_iblock]; +        delta = (f->f_stacktop - f->f_valuestack) - b->b_level; +        if (b->b_type == SETUP_FINALLY && +            code[b->b_handler] == WITH_CLEANUP_START) +        { +            /* Pop the exit function. */ +            delta++;          }      }      /* Pop the iterators of any 'for' loop we're jumping out of. */ -    while (for_loop_delta > 0) { +    delta += for_loop_delta; + +    while (delta > 0) {          PyObject *v = (*--f->f_stacktop);          Py_DECREF(v); -        for_loop_delta--; +        delta--;      }      /* Finally set the new f_lineno and f_lasti and return OK. */ | 
