From 74284b9606b4c2743ef82119b41eb3a74dd5b2d2 Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Sun, 8 Oct 2006 07:06:29 +0000 Subject: [PATCH] Patch #1542451: fix crash with continue in nested try/finally (backport from rev. 51439) --- Lib/test/test_syntax.py | 84 +++++++++++++++++++++++++++++++++++++++++ Misc/NEWS | 2 + Python/compile.c | 14 +++++-- 3 files changed, 96 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py index dc7a16d1e2..bc9cb127ea 100644 --- a/Lib/test/test_syntax.py +++ b/Lib/test/test_syntax.py @@ -235,6 +235,90 @@ SyntaxError: assignment to None (, line 1) >>> f() += 1 Traceback (most recent call last): SyntaxError: illegal expression for augmented assignment (, 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 (, 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 (, line 7) + + >>> def foo(): + ... try: + ... pass + ... finally: + ... continue + Traceback (most recent call last): + ... + SyntaxError: 'continue' not supported inside 'finally' clause (, line 5) + + >>> def foo(): + ... for a in (): + ... try: pass + ... finally: continue + Traceback (most recent call last): + ... + SyntaxError: 'continue' not supported inside 'finally' clause (, 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 (, 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 (, line 8) + """ import re diff --git a/Misc/NEWS b/Misc/NEWS index 7a8e4de2f1..9bccc28b69 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -12,6 +12,8 @@ What's New in Python 2.5.1c1? Core and builtins ----------------- +- Patch #1542451: disallow continue anywhere under a finally. + - list.pop(x) accepts any object x following the __index__ protocol. - Fix some leftovers from the conversion from int to Py_ssize_t diff --git a/Python/compile.c b/Python/compile.c index 92eff00732..76c462829d 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -2288,6 +2288,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) @@ -2299,15 +2301,19 @@ 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 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) 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; -- 2.50.1