summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeal Norwitz <nnorwitz@gmail.com>2006-08-21 19:47:08 (GMT)
committerNeal Norwitz <nnorwitz@gmail.com>2006-08-21 19:47:08 (GMT)
commit4f096d948797cabbe717197faf4d979d68badd0b (patch)
treeecba29cf8fafc590b7a3fb8cfa1f6a911534d3da
parent076d1e0c0b1858a9086c63c237cbe13691231b0f (diff)
downloadcpython-4f096d948797cabbe717197faf4d979d68badd0b.zip
cpython-4f096d948797cabbe717197faf4d979d68badd0b.tar.gz
cpython-4f096d948797cabbe717197faf4d979d68badd0b.tar.bz2
Patch #1542451: disallow continue anywhere under a finally
I'm undecided if this should be backported to 2.5 or 2.5.1. Armin suggested to wait (I'm of the same opinion). Thomas W thinks it's fine to go in 2.5.
-rw-r--r--Lib/test/test_syntax.py87
-rw-r--r--Misc/NEWS2
-rw-r--r--Python/compile.c13
3 files changed, 98 insertions, 4 deletions
diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py
index dc7a16d..692ba57 100644
--- a/Lib/test/test_syntax.py
+++ b/Lib/test/test_syntax.py
@@ -235,6 +235,93 @@ SyntaxError: assignment to None (<doctest test.test_syntax[32]>, line 1)
>>> f() += 1
Traceback (most recent call last):
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 6)
+
+ >>> 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 7)
+
+ >>> 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
diff --git a/Misc/NEWS b/Misc/NEWS
index f304314..757e28b 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -12,6 +12,8 @@ What's New in Python 2.6?
Core and builtins
-----------------
+- Patch #1542451: disallow continue anywhere under a finally.
+
Library
-------
diff --git a/Python/compile.c b/Python/compile.c
index 5aaf809..a03de0d 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -1682,6 +1682,8 @@ static int
compiler_continue(struct compiler *c)
{
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;
if (!c->u->u_nfblocks)
@@ -1693,15 +1695,18 @@ compiler_continue(struct compiler *c)
break;
case EXCEPT:
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 continue anywhere under a finally
+ even if hidden in a sub-try or except. */
+ if (c->u->u_fblock[i].fb_type == FINALLY_END)
+ return compiler_error(c, IN_FINALLY_ERROR_MSG);
+ }
if (i == -1)
return compiler_error(c, LOOP_ERROR_MSG);
ADDOP_JABS(c, CONTINUE_LOOP, c->u->u_fblock[i].fb_block);
break;
case FINALLY_END:
- return compiler_error(c,
- "'continue' not supported inside 'finally' clause");
+ return compiler_error(c, IN_FINALLY_ERROR_MSG);
}
return 1;