Skip to content

Commit c31943a

Browse files
authored
pythongh-113297: Fix segfault in compiler for with statement with 19 context managers (python#113327)
1 parent 9afb0e1 commit c31943a

File tree

3 files changed

+29
-1
lines changed

3 files changed

+29
-1
lines changed

Lib/test/test_syntax.py

+26
Original file line numberDiff line numberDiff line change
@@ -2017,6 +2017,7 @@ def f(x: *b)
20172017

20182018
import re
20192019
import doctest
2020+
import textwrap
20202021
import unittest
20212022

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

2283+
@support.cpython_only
2284+
def test_with_statement_many_context_managers(self):
2285+
# See gh-113297
2286+
2287+
def get_code(n):
2288+
code = textwrap.dedent("""
2289+
def bug():
2290+
with (
2291+
a
2292+
""")
2293+
for i in range(n):
2294+
code += f" as a{i}, a\n"
2295+
code += "): yield a"
2296+
return code
2297+
2298+
CO_MAXBLOCKS = 20 # static nesting limit of the compiler
2299+
2300+
for n in range(CO_MAXBLOCKS):
2301+
with self.subTest(f"within range: {n=}"):
2302+
compile(get_code(n), "<string>", "exec")
2303+
2304+
for n in range(CO_MAXBLOCKS, CO_MAXBLOCKS + 5):
2305+
with self.subTest(f"out of range: {n=}"):
2306+
self._check_error(get_code(n), "too many statically nested blocks")
2307+
22822308
def test_barry_as_flufl_with_syntax_errors(self):
22832309
# The "barry_as_flufl" rule can produce some "bugs-at-a-distance" if
22842310
# is reading the wrong token in the presence of syntax errors later
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix segfault in the compiler on with statement with 19 context managers.

Python/flowgraph.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -648,7 +648,7 @@ mark_except_handlers(basicblock *entryblock) {
648648

649649

650650
struct _PyCfgExceptStack {
651-
basicblock *handlers[CO_MAXBLOCKS+1];
651+
basicblock *handlers[CO_MAXBLOCKS+2];
652652
int depth;
653653
};
654654

@@ -661,6 +661,7 @@ push_except_block(struct _PyCfgExceptStack *stack, cfg_instr *setup) {
661661
if (opcode == SETUP_WITH || opcode == SETUP_CLEANUP) {
662662
target->b_preserve_lasti = 1;
663663
}
664+
assert(stack->depth <= CO_MAXBLOCKS);
664665
stack->handlers[++stack->depth] = target;
665666
return target;
666667
}

0 commit comments

Comments
 (0)