summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIrit Katriel <iritkatriel@yahoo.com>2020-11-17 19:31:55 (GMT)
committerGitHub <noreply@github.com>2020-11-17 19:31:55 (GMT)
commit48a9c0eb2a3304ea64d1b32fdf9db853d5d8c429 (patch)
treef6ae1333bc97f35c514718d82baf1409cdb22f52
parent05a5d697f4f097f37c5c1e2ed0e2338a33c3fb6a (diff)
downloadcpython-48a9c0eb2a3304ea64d1b32fdf9db853d5d8c429.zip
cpython-48a9c0eb2a3304ea64d1b32fdf9db853d5d8c429.tar.gz
cpython-48a9c0eb2a3304ea64d1b32fdf9db853d5d8c429.tar.bz2
[3.9] bpo-39934: Account for control blocks in 'except' in compiler. (GH-22395) (GH-23303)
* bpo-39934: backport PR 22395 to 3.9
-rw-r--r--Lib/test/test_syntax.py9
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2020-09-24-12-15-45.bpo-39934.YVHTCF.rst3
-rw-r--r--Python/compile.c19
3 files changed, 23 insertions, 8 deletions
diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py
index 1336231..f0c9c98 100644
--- a/Lib/test/test_syntax.py
+++ b/Lib/test/test_syntax.py
@@ -946,6 +946,15 @@ pass
except SyntaxError:
self.fail("Empty line after a line continuation character is valid.")
+ @support.cpython_only
+ def test_nested_named_except_blocks(self):
+ code = ""
+ for i in range(12):
+ code += f"{' '*i}try:\n"
+ code += f"{' '*(i+1)}raise Exception\n"
+ code += f"{' '*i}except Exception as e:\n"
+ code += f"{' '*4*12}pass"
+ self._check_error(code, "too many statically nested blocks")
def test_barry_as_flufl_with_syntax_errors(self):
# The "barry_as_flufl" rule can produce some "bugs-at-a-distance" if
diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-09-24-12-15-45.bpo-39934.YVHTCF.rst b/Misc/NEWS.d/next/Core and Builtins/2020-09-24-12-15-45.bpo-39934.YVHTCF.rst
new file mode 100644
index 0000000..92cd1ba
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2020-09-24-12-15-45.bpo-39934.YVHTCF.rst
@@ -0,0 +1,3 @@
+Correctly count control blocks in 'except' in compiler. Ensures that a
+syntax error, rather a fatal error, occurs for deeply nested, named
+exception handlers.
diff --git a/Python/compile.c b/Python/compile.c
index 51af28b..722d52d 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -84,8 +84,8 @@ It's called a frame block to distinguish it from a basic block in the
compiler IR.
*/
-enum fblocktype { WHILE_LOOP, FOR_LOOP, EXCEPT, FINALLY_TRY, FINALLY_END,
- WITH, ASYNC_WITH, HANDLER_CLEANUP, POP_VALUE };
+enum fblocktype { WHILE_LOOP, FOR_LOOP, TRY_EXCEPT, FINALLY_TRY, FINALLY_END,
+ WITH, ASYNC_WITH, HANDLER_CLEANUP, POP_VALUE, EXCEPTION_HANDLER };
struct fblockinfo {
enum fblocktype fb_type;
@@ -1624,9 +1624,7 @@ compiler_push_fblock(struct compiler *c, enum fblocktype t, basicblock *b,
{
struct fblockinfo *f;
if (c->u->u_nfblocks >= CO_MAXBLOCKS) {
- PyErr_SetString(PyExc_SyntaxError,
- "too many statically nested blocks");
- return 0;
+ return compiler_error(c, "too many statically nested blocks");
}
f = &c->u->u_fblock[c->u->u_nfblocks++];
f->fb_type = t;
@@ -1666,6 +1664,7 @@ compiler_unwind_fblock(struct compiler *c, struct fblockinfo *info,
{
switch (info->fb_type) {
case WHILE_LOOP:
+ case EXCEPTION_HANDLER:
return 1;
case FOR_LOOP:
@@ -1676,7 +1675,7 @@ compiler_unwind_fblock(struct compiler *c, struct fblockinfo *info,
ADDOP(c, POP_TOP);
return 1;
- case EXCEPT:
+ case TRY_EXCEPT:
ADDOP(c, POP_BLOCK);
return 1;
@@ -3064,14 +3063,17 @@ compiler_try_except(struct compiler *c, stmt_ty s)
return 0;
ADDOP_JREL(c, SETUP_FINALLY, except);
compiler_use_next_block(c, body);
- if (!compiler_push_fblock(c, EXCEPT, body, NULL, NULL))
+ if (!compiler_push_fblock(c, TRY_EXCEPT, body, NULL, NULL))
return 0;
VISIT_SEQ(c, stmt, s->v.Try.body);
ADDOP(c, POP_BLOCK);
- compiler_pop_fblock(c, EXCEPT, body);
+ compiler_pop_fblock(c, TRY_EXCEPT, body);
ADDOP_JREL(c, JUMP_FORWARD, orelse);
n = asdl_seq_LEN(s->v.Try.handlers);
compiler_use_next_block(c, except);
+ /* Runtime will push a block here, so we need to account for that */
+ if (!compiler_push_fblock(c, EXCEPTION_HANDLER, NULL, NULL, NULL))
+ return 0;
for (i = 0; i < n; i++) {
excepthandler_ty handler = (excepthandler_ty)asdl_seq_GET(
s->v.Try.handlers, i);
@@ -3156,6 +3158,7 @@ compiler_try_except(struct compiler *c, stmt_ty s)
}
compiler_use_next_block(c, except);
}
+ compiler_pop_fblock(c, EXCEPTION_HANDLER, NULL);
ADDOP(c, RERAISE);
compiler_use_next_block(c, orelse);
VISIT_SEQ(c, stmt, s->v.Try.orelse);