Skip to content
Open
31 changes: 31 additions & 0 deletions Lib/test/test_compile.py
Original file line number Diff line number Diff line change
Expand Up @@ -960,6 +960,37 @@ def unused_code_at_end():
'RETURN_VALUE',
list(dis.get_instructions(unused_code_at_end))[-1].opname)

def test_parser_stack_overflow_in_loop_rule(self):
# gh-150001: A parser stack overflow inside an f-string must not be
# followed by a SyntaxWarning emitted with the MemoryError still set
def overflows(source):
try:
compile(source, '<input>', 'exec')
except MemoryError:
return True
except SyntaxError:
pass
return False

# Find the shallowest nesting that overflows the parser stack
lo, hi = 1, 100_000
while lo < hi:
mid = (lo + hi) // 2
if overflows(b'~' * mid + b'x'):
hi = mid
else:
lo = mid + 1

# Overflow at every point around that depth, including inside the
# f-string with invalid escape sequences
tail = b'f"\\}{x}\\}"'
with warnings.catch_warnings():
warnings.simplefilter('ignore', SyntaxWarning)
for depth in range(max(lo - 20, 1), lo + 20):
with self.subTest(depth=depth):
with self.assertRaises((MemoryError, SyntaxError)):
compile(b'~' * depth + tail, '<input>', 'exec')

@support.cpython_only
def test_docstring(self):
src = textwrap.dedent("""
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Fix a bug where parsing certain invalid Python code could raise a
:exc:`SystemError` instead of the expected :exc:`SyntaxError`. Patch by
Alexander Domenti.
Loading
Loading