Skip to content

Commit

Permalink
pythongh-113297: Fix segfault in compiler for with statement with 19 …
Browse files Browse the repository at this point in the history
…context managers (python#113327)
  • Loading branch information
iritkatriel authored Dec 22, 2023
1 parent 9afb0e1 commit c31943a
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 1 deletion.
26 changes: 26 additions & 0 deletions Lib/test/test_syntax.py
Original file line number Diff line number Diff line change
Expand Up @@ -2017,6 +2017,7 @@ def f(x: *b)

import re
import doctest
import textwrap
import unittest

from test import support
Expand Down Expand Up @@ -2279,6 +2280,31 @@ def test_nested_named_except_blocks(self):
code += f"{' '*4*12}pass"
self._check_error(code, "too many statically nested blocks")

@support.cpython_only
def test_with_statement_many_context_managers(self):
# See gh-113297

def get_code(n):
code = textwrap.dedent("""
def bug():
with (
a
""")
for i in range(n):
code += f" as a{i}, a\n"
code += "): yield a"
return code

CO_MAXBLOCKS = 20 # static nesting limit of the compiler

for n in range(CO_MAXBLOCKS):
with self.subTest(f"within range: {n=}"):
compile(get_code(n), "<string>", "exec")

for n in range(CO_MAXBLOCKS, CO_MAXBLOCKS + 5):
with self.subTest(f"out of range: {n=}"):
self._check_error(get_code(n), "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
# is reading the wrong token in the presence of syntax errors later
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix segfault in the compiler on with statement with 19 context managers.
3 changes: 2 additions & 1 deletion Python/flowgraph.c
Original file line number Diff line number Diff line change
Expand Up @@ -648,7 +648,7 @@ mark_except_handlers(basicblock *entryblock) {


struct _PyCfgExceptStack {
basicblock *handlers[CO_MAXBLOCKS+1];
basicblock *handlers[CO_MAXBLOCKS+2];
int depth;
};

Expand All @@ -661,6 +661,7 @@ push_except_block(struct _PyCfgExceptStack *stack, cfg_instr *setup) {
if (opcode == SETUP_WITH || opcode == SETUP_CLEANUP) {
target->b_preserve_lasti = 1;
}
assert(stack->depth <= CO_MAXBLOCKS);
stack->handlers[++stack->depth] = target;
return target;
}
Expand Down

0 comments on commit c31943a

Please sign in to comment.