mirror of
https://github.com/python/cpython
synced 2024-10-05 02:17:14 +00:00
[3.12] gh-113297: Fix segfault in compiler for with statement with 19 context managers (#113327) (#113404)
This commit is contained in:
parent
4882d508be
commit
9d72a5cae7
|
@ -26,7 +26,7 @@ typedef struct {
|
|||
|
||||
|
||||
typedef struct {
|
||||
struct _PyCfgBasicblock_ *handlers[CO_MAXBLOCKS+1];
|
||||
struct _PyCfgBasicblock_ *handlers[CO_MAXBLOCKS+2];
|
||||
int depth;
|
||||
} _PyCfgExceptStack;
|
||||
|
||||
|
|
|
@ -1995,6 +1995,7 @@ def f(x: *b)
|
|||
|
||||
import re
|
||||
import doctest
|
||||
import textwrap
|
||||
import unittest
|
||||
|
||||
from test import support
|
||||
|
@ -2241,6 +2242,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
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Fix segfault in the compiler on with statement with 19 context managers.
|
|
@ -645,6 +645,7 @@ push_except_block(ExceptStack *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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue