mirror of
https://github.com/python/cpython.git
synced 2025-08-09 19:38:42 +00:00
[3.12] gh-116767: fix crash on 'async with' with many context managers (GH-118348) (#118477)
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.
(cherry picked from commit c1bf4874c1
)
This commit is contained in:
parent
f5406ef454
commit
ebef3c5ba4
4 changed files with 50 additions and 7 deletions
|
@ -2269,13 +2269,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")
|
||||
|
||||
|
@ -2407,7 +2434,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