diff --git a/ChangeLog b/ChangeLog index 47bb4d19b..379a2a748 100644 --- a/ChangeLog +++ b/ChangeLog @@ -7,6 +7,10 @@ What's New in astroid 4.0.0? ============================ Release date: TBA +* Prevent crash when parsing deeply nested parentheses causing MemoryError in python's built-in ast. + + Closes #2643 + * Fix crash when inferring namedtuple with invalid field name looking like f-string formatting. Closes #2519 diff --git a/astroid/builder.py b/astroid/builder.py index 6205f83d4..a107fed99 100644 --- a/astroid/builder.py +++ b/astroid/builder.py @@ -181,7 +181,7 @@ def _data_build( node, parser_module = _parse_string( data, type_comments=True, modname=modname ) - except (TypeError, ValueError, SyntaxError) as exc: + except (TypeError, ValueError, SyntaxError, MemoryError) as exc: raise AstroidSyntaxError( "Parsing Python code failed:\n{error}", source=data, diff --git a/tests/test_regrtest.py b/tests/test_regrtest.py index 1b16662c6..0ff3b6f52 100644 --- a/tests/test_regrtest.py +++ b/tests/test_regrtest.py @@ -2,6 +2,7 @@ # For details: https://github.com/pylint-dev/astroid/blob/main/LICENSE # Copyright (c) https://github.com/pylint-dev/astroid/blob/main/CONTRIBUTORS.txt +import platform import sys import textwrap import unittest @@ -13,7 +14,7 @@ from astroid.builder import AstroidBuilder, _extract_single_node, extract_node from astroid.const import PY312_PLUS from astroid.context import InferenceContext -from astroid.exceptions import InferenceError +from astroid.exceptions import AstroidSyntaxError, InferenceError from astroid.manager import AstroidManager from astroid.raw_building import build_module from astroid.util import Uninferable @@ -561,3 +562,15 @@ def test_regression_infer_namedtuple_invalid_fieldname_error() -> None: node = extract_node(code) inferred = next(node.infer()) assert inferred.value == Uninferable + + +def test_regression_parse_deeply_nested_parentheses() -> None: + """Regression test for issue #2643.""" + with pytest.raises(AstroidSyntaxError, match="Parsing Python code failed:") as ctx: + extract_node( + "A=((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((c,j=t" + ) + expected = ( + SyntaxError if platform.python_implementation() == "PyPy" else MemoryError + ) + assert isinstance(ctx.value.error, expected)