Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions Lib/test/test_compile.py
Original file line number Diff line number Diff line change
Expand Up @@ -708,6 +708,19 @@ def test_func_and(self):
code += " x and x\n" * self.N
self.check_stack_size(code)

def test_try_except(self):
# See issue #24340.
source = "try: x\nexcept E: y\n"
code = compile(source, "<foo>", "exec")
code2 = compile(source * self.N, "<foo>", "exec")
self.assertEqual(code2.co_stacksize, code.co_stacksize)

def test_try_finally(self):
source = "try: x\nfinally: y\n"
code = compile(source, "<foo>", "exec")
code2 = compile(source * self.N, "<foo>", "exec")
self.assertEqual(code2.co_stacksize, code.co_stacksize)


if __name__ == "__main__":
unittest.main()
3 changes: 3 additions & 0 deletions Misc/NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ What's New in Python 3.7.0 alpha 1?
Core and Builtins
-----------------

- bpo-24340: Fixed a "leak" in the computation of the stack size effect for
try/except and try/finally.

- bpo-25324: Tokens needed for parsing in Python moved to C. ``COMMENT``,
``NL`` and ``ENCODING``. This way the tokens and tok_names in the token
module don't get changed when you import the tokenize module.
Expand Down
15 changes: 8 additions & 7 deletions Python/compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -946,9 +946,9 @@ PyCompile_OpcodeStackEffect(int opcode, int oparg)
case POP_BLOCK:
return 0;
case POP_EXCEPT:
return 0; /* -3 except if bad bytecode */
return -3; /* the previous exception state */
case END_FINALLY:
return -1; /* or -2 or -3 if exception occurred */
return -6; /* see SETUP_FINALLY */

case STORE_NAME:
return -1;
Expand Down Expand Up @@ -4850,11 +4850,12 @@ stackdepth_walk(struct compiler *c, basicblock *b, int depth, int maxdepth)
if (instr->i_opcode == FOR_ITER) {
target_depth = depth-2;
}
else if (instr->i_opcode == SETUP_FINALLY ||
instr->i_opcode == SETUP_EXCEPT) {
target_depth = depth+3;
if (target_depth > maxdepth)
maxdepth = target_depth;
else if (instr->i_opcode == SETUP_EXCEPT) {
depth = depth - 6;
}
else if (instr->i_opcode == SETUP_FINALLY) {
depth = depth - 1; /* for None */
continue; /* should pass to finally handler in any case */
}
else if (instr->i_opcode == JUMP_IF_TRUE_OR_POP ||
instr->i_opcode == JUMP_IF_FALSE_OR_POP)
Expand Down