From a5fe3ef8d835d8dffe42b58398d101eb42b897af Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Sun, 8 Oct 2006 07:12:23 +0000 Subject: Fix #1569998: no break inside try statement (outside loop) allowed. (backport from rev. 52129) --- Lib/test/test_syntax.py | 14 ++++++++++++++ Misc/NEWS | 3 +++ Python/compile.c | 14 +++++++++++++- 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py index bc9cb12..521789f 100644 --- a/Lib/test/test_syntax.py +++ b/Lib/test/test_syntax.py @@ -319,6 +319,20 @@ This is essentially a continue in a finally which should not be allowed. ... SyntaxError: 'continue' not supported inside 'finally' clause (, line 8) +There is one test for a break that is not in a loop. The compiler +uses a single data structure to keep track of try-finally and loops, +so we need to be sure that a break is actually inside a loop. If it +isn't, there should be a syntax error. + + >>> try: + ... print 1 + ... break + ... print 2 + ... finally: + ... print 3 + Traceback (most recent call last): + ... + SyntaxError: 'break' outside loop (, line 3) """ import re diff --git a/Misc/NEWS b/Misc/NEWS index 9bccc28..a390730c 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -12,6 +12,9 @@ What's New in Python 2.5.1c1? Core and builtins ----------------- +- Bug #1569998: break inside a try statement (outside a loop) is now + recognized and rejected. + - Patch #1542451: disallow continue anywhere under a finally. - list.pop(x) accepts any object x following the __index__ protocol. diff --git a/Python/compile.c b/Python/compile.c index 76c4628..038bc2f 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -187,6 +187,8 @@ static int compiler_push_fblock(struct compiler *, enum fblocktype, basicblock *); static void compiler_pop_fblock(struct compiler *, enum fblocktype, basicblock *); +/* Returns true if there is a loop on the fblock stack. */ +static int compiler_in_loop(struct compiler *); static int inplace_binop(struct compiler *, operator_ty); static int expr_constant(expr_ty e); @@ -2764,7 +2766,7 @@ compiler_visit_stmt(struct compiler *c, stmt_ty s) case Pass_kind: break; case Break_kind: - if (!c->u->u_nfblocks) + if (!compiler_in_loop(c)) return compiler_error(c, "'break' outside loop"); ADDOP(c, BREAK_LOOP); break; @@ -3754,6 +3756,16 @@ compiler_pop_fblock(struct compiler *c, enum fblocktype t, basicblock *b) assert(u->u_fblock[u->u_nfblocks].fb_block == b); } +static int +compiler_in_loop(struct compiler *c) { + int i; + struct compiler_unit *u = c->u; + for (i = 0; i < u->u_nfblocks; ++i) { + if (u->u_fblock[i].fb_type == LOOP) + return 1; + } + return 0; +} /* Raises a SyntaxError and returns 0. If something goes wrong, a different exception may be raised. */ -- cgit v0.12