Skip to content

Commit 4c5f108

Browse files
committed
py/compile: Fix bug with break/continue in else of optimised for-range.
This patch fixes a bug whereby the Python stack was not correctly reset if there was a break/continue statement in the else black of an optimised for-range loop. For example, in the following code the "j" variable from the inner for loop was not being popped off the Python stack: for i in range(4): for j in range(4): pass else: continue This is now fixed with this patch.
1 parent 458cbac commit 4c5f108

File tree

1 file changed

+19
-2
lines changed

1 file changed

+19
-2
lines changed

py/compile.c

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1406,7 +1406,20 @@ STATIC void compile_for_stmt_optimised_range(compiler_t *comp, mp_parse_node_t p
14061406
// break/continue apply to outer loop (if any) in the else block
14071407
END_BREAK_CONTINUE_BLOCK
14081408

1409-
compile_node(comp, pn_else);
1409+
// Compile the else block. We must pop the iterator variables before
1410+
// executing the else code because it may contain break/continue statements.
1411+
uint end_label = 0;
1412+
if (!MP_PARSE_NODE_IS_NULL(pn_else)) {
1413+
// discard final value of "var", and possible "end" value
1414+
EMIT(pop_top);
1415+
if (end_on_stack) {
1416+
EMIT(pop_top);
1417+
}
1418+
compile_node(comp, pn_else);
1419+
end_label = comp_next_label(comp);
1420+
EMIT_ARG(jump, end_label);
1421+
EMIT_ARG(adjust_stack_size, 1 + end_on_stack);
1422+
}
14101423

14111424
EMIT_ARG(label_assign, break_label);
14121425

@@ -1417,6 +1430,10 @@ STATIC void compile_for_stmt_optimised_range(compiler_t *comp, mp_parse_node_t p
14171430
if (end_on_stack) {
14181431
EMIT(pop_top);
14191432
}
1433+
1434+
if (!MP_PARSE_NODE_IS_NULL(pn_else)) {
1435+
EMIT_ARG(label_assign, end_label);
1436+
}
14201437
}
14211438

14221439
STATIC void compile_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
@@ -1496,7 +1513,7 @@ STATIC void compile_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
14961513
// break/continue apply to outer loop (if any) in the else block
14971514
END_BREAK_CONTINUE_BLOCK
14981515

1499-
compile_node(comp, pns->nodes[3]); // else (not tested)
1516+
compile_node(comp, pns->nodes[3]); // else (may be empty)
15001517

15011518
EMIT_ARG(label_assign, break_label);
15021519
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy