mirror of
https://github.com/python/cpython.git
synced 2025-10-17 20:28:43 +00:00
gh-116767: fix crash on 'async with' with many context managers (GH-118348)
Account for `add_stopiteration_handler` pushing a block for `async with`. To allow generator functions that previously almost hit the `CO_MAXBLOCKS` limit by nesting non-async blocks, the limit is increased by 1. This increase allows one more block in non-generator functions.
This commit is contained in:
parent
f6fab21721
commit
c1bf4874c1
4 changed files with 50 additions and 7 deletions
|
@ -2392,13 +2392,40 @@ if x:
|
|||
code += "): yield a"
|
||||
return code
|
||||
|
||||
CO_MAXBLOCKS = 20 # static nesting limit of the compiler
|
||||
CO_MAXBLOCKS = 21 # static nesting limit of the compiler
|
||||
MAX_MANAGERS = CO_MAXBLOCKS - 1 # One for the StopIteration block
|
||||
|
||||
for n in range(CO_MAXBLOCKS):
|
||||
for n in range(MAX_MANAGERS):
|
||||
with self.subTest(f"within range: {n=}"):
|
||||
compile(get_code(n), "<string>", "exec")
|
||||
|
||||
for n in range(CO_MAXBLOCKS, CO_MAXBLOCKS + 5):
|
||||
for n in range(MAX_MANAGERS, MAX_MANAGERS + 5):
|
||||
with self.subTest(f"out of range: {n=}"):
|
||||
self._check_error(get_code(n), "too many statically nested blocks")
|
||||
|
||||
@support.cpython_only
|
||||
def test_async_with_statement_many_context_managers(self):
|
||||
# See gh-116767
|
||||
|
||||
def get_code(n):
|
||||
code = [ textwrap.dedent("""
|
||||
async def bug():
|
||||
async with (
|
||||
a
|
||||
""") ]
|
||||
for i in range(n):
|
||||
code.append(f" as a{i}, a\n")
|
||||
code.append("): yield a")
|
||||
return "".join(code)
|
||||
|
||||
CO_MAXBLOCKS = 21 # static nesting limit of the compiler
|
||||
MAX_MANAGERS = CO_MAXBLOCKS - 1 # One for the StopIteration block
|
||||
|
||||
for n in range(MAX_MANAGERS):
|
||||
with self.subTest(f"within range: {n=}"):
|
||||
compile(get_code(n), "<string>", "exec")
|
||||
|
||||
for n in range(MAX_MANAGERS, MAX_MANAGERS + 5):
|
||||
with self.subTest(f"out of range: {n=}"):
|
||||
self._check_error(get_code(n), "too many statically nested blocks")
|
||||
|
||||
|
@ -2536,7 +2563,8 @@ while 1:
|
|||
while 20:
|
||||
while 21:
|
||||
while 22:
|
||||
break
|
||||
while 23:
|
||||
break
|
||||
"""
|
||||
self._check_error(source, "too many statically nested blocks")
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue