mirror of
https://github.com/python/cpython.git
synced 2025-10-10 00:43:41 +00:00
Patch #1542451: fix crash with continue in nested try/finally
(backport from rev. 51439)
This commit is contained in:
parent
2c8851e614
commit
74284b9606
3 changed files with 96 additions and 4 deletions
|
@ -235,6 +235,90 @@ SyntaxError: assignment to None (<doctest test.test_syntax[32]>, line 1)
|
||||||
>>> f() += 1
|
>>> f() += 1
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
SyntaxError: illegal expression for augmented assignment (<doctest test.test_syntax[33]>, line 1)
|
SyntaxError: illegal expression for augmented assignment (<doctest test.test_syntax[33]>, line 1)
|
||||||
|
|
||||||
|
|
||||||
|
Test continue in finally in weird combinations.
|
||||||
|
|
||||||
|
continue in for loop under finally shouuld be ok.
|
||||||
|
|
||||||
|
>>> def test():
|
||||||
|
... try:
|
||||||
|
... pass
|
||||||
|
... finally:
|
||||||
|
... for abc in range(10):
|
||||||
|
... continue
|
||||||
|
... print abc
|
||||||
|
>>> test()
|
||||||
|
9
|
||||||
|
|
||||||
|
Start simple, a continue in a finally should not be allowed.
|
||||||
|
|
||||||
|
>>> def test():
|
||||||
|
... for abc in range(10):
|
||||||
|
... try:
|
||||||
|
... pass
|
||||||
|
... finally:
|
||||||
|
... continue
|
||||||
|
...
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
SyntaxError: 'continue' not supported inside 'finally' clause (<doctest test.test_syntax[36]>, line 6)
|
||||||
|
|
||||||
|
This is essentially a continue in a finally which should not be allowed.
|
||||||
|
|
||||||
|
>>> def test():
|
||||||
|
... for abc in range(10):
|
||||||
|
... try:
|
||||||
|
... pass
|
||||||
|
... finally:
|
||||||
|
... try:
|
||||||
|
... continue
|
||||||
|
... except:
|
||||||
|
... pass
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
SyntaxError: 'continue' not supported inside 'finally' clause (<doctest test.test_syntax[37]>, line 7)
|
||||||
|
|
||||||
|
>>> def foo():
|
||||||
|
... try:
|
||||||
|
... pass
|
||||||
|
... finally:
|
||||||
|
... continue
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
SyntaxError: 'continue' not supported inside 'finally' clause (<doctest test.test_syntax[38]>, line 5)
|
||||||
|
|
||||||
|
>>> def foo():
|
||||||
|
... for a in ():
|
||||||
|
... try: pass
|
||||||
|
... finally: continue
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
SyntaxError: 'continue' not supported inside 'finally' clause (<doctest test.test_syntax[39]>, line 4)
|
||||||
|
|
||||||
|
>>> def foo():
|
||||||
|
... for a in ():
|
||||||
|
... try: pass
|
||||||
|
... finally:
|
||||||
|
... try:
|
||||||
|
... continue
|
||||||
|
... finally: pass
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
SyntaxError: 'continue' not supported inside 'finally' clause (<doctest test.test_syntax[40]>, line 6)
|
||||||
|
|
||||||
|
>>> def foo():
|
||||||
|
... for a in ():
|
||||||
|
... try: pass
|
||||||
|
... finally:
|
||||||
|
... try:
|
||||||
|
... pass
|
||||||
|
... except:
|
||||||
|
... continue
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
SyntaxError: 'continue' not supported inside 'finally' clause (<doctest test.test_syntax[41]>, line 8)
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
|
|
@ -12,6 +12,8 @@ What's New in Python 2.5.1c1?
|
||||||
Core and builtins
|
Core and builtins
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
- Patch #1542451: disallow continue anywhere under a finally.
|
||||||
|
|
||||||
- list.pop(x) accepts any object x following the __index__ protocol.
|
- list.pop(x) accepts any object x following the __index__ protocol.
|
||||||
|
|
||||||
- Fix some leftovers from the conversion from int to Py_ssize_t
|
- Fix some leftovers from the conversion from int to Py_ssize_t
|
||||||
|
|
|
@ -2288,6 +2288,8 @@ static int
|
||||||
compiler_continue(struct compiler *c)
|
compiler_continue(struct compiler *c)
|
||||||
{
|
{
|
||||||
static const char LOOP_ERROR_MSG[] = "'continue' not properly in loop";
|
static const char LOOP_ERROR_MSG[] = "'continue' not properly in loop";
|
||||||
|
static const char IN_FINALLY_ERROR_MSG[] =
|
||||||
|
"'continue' not supported inside 'finally' clause";
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!c->u->u_nfblocks)
|
if (!c->u->u_nfblocks)
|
||||||
|
@ -2299,15 +2301,19 @@ compiler_continue(struct compiler *c)
|
||||||
break;
|
break;
|
||||||
case EXCEPT:
|
case EXCEPT:
|
||||||
case FINALLY_TRY:
|
case FINALLY_TRY:
|
||||||
while (--i >= 0 && c->u->u_fblock[i].fb_type != LOOP)
|
while (--i >= 0 && c->u->u_fblock[i].fb_type != LOOP) {
|
||||||
;
|
/* Prevent try: ... finally:
|
||||||
|
try: continue ... or
|
||||||
|
try: ... except: continue */
|
||||||
|
if (c->u->u_fblock[i].fb_type == FINALLY_END)
|
||||||
|
return compiler_error(c, IN_FINALLY_ERROR_MSG);
|
||||||
|
}
|
||||||
if (i == -1)
|
if (i == -1)
|
||||||
return compiler_error(c, LOOP_ERROR_MSG);
|
return compiler_error(c, LOOP_ERROR_MSG);
|
||||||
ADDOP_JABS(c, CONTINUE_LOOP, c->u->u_fblock[i].fb_block);
|
ADDOP_JABS(c, CONTINUE_LOOP, c->u->u_fblock[i].fb_block);
|
||||||
break;
|
break;
|
||||||
case FINALLY_END:
|
case FINALLY_END:
|
||||||
return compiler_error(c,
|
return compiler_error(c, IN_FINALLY_ERROR_MSG);
|
||||||
"'continue' not supported inside 'finally' clause");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue