diff --git a/Lib/test/test_ast/test_ast.py b/Lib/test/test_ast/test_ast.py index 0bb74582f3ecdf..7ac5a816bf0229 100644 --- a/Lib/test/test_ast/test_ast.py +++ b/Lib/test/test_ast/test_ast.py @@ -204,6 +204,26 @@ def test_compilation_of_ast_nodes_with_default_end_position_values(self): # Check that compilation doesn't crash. Note: this may crash explicitly only on debug mode. compile(tree, "", "exec") + def test_negative_locations_for_compile(self): + # See https://github.com/python/cpython/issues/130775 + alias = ast.alias(name='traceback', lineno=0, col_offset=0) + for attrs in ( + {'lineno': -2, 'col_offset': 0}, + {'lineno': 0, 'col_offset': -2}, + {'lineno': 0, 'col_offset': -2, 'end_col_offset': -2}, + {'lineno': -2, 'end_lineno': -2, 'col_offset': 0}, + ): + with self.subTest(attrs=attrs): + tree = ast.Module(body=[ + ast.Import(names=[alias], **attrs) + ], type_ignores=[]) + + # It used to crash on this step: + compile(tree, "", "exec") + + # This also must not crash: + ast.parse(tree, optimize=2) + def test_slice(self): slc = ast.parse("x[::]").body[0].value.slice self.assertIsNone(slc.upper) diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-03-03-20-02-45.gh-issue-130775.fEM6T-.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-03-03-20-02-45.gh-issue-130775.fEM6T-.rst new file mode 100644 index 00000000000000..53408cd427596c --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-03-03-20-02-45.gh-issue-130775.fEM6T-.rst @@ -0,0 +1 @@ +Do not crash on negative ``column`` and ``end_column`` in :mod:`ast` locations. diff --git a/Python/assemble.c b/Python/assemble.c index 98816aec783227..35453277dd84d1 100644 --- a/Python/assemble.c +++ b/Python/assemble.c @@ -290,17 +290,15 @@ write_location_info_entry(struct assembler* a, location loc, int isize) assert(len > THEORETICAL_MAX_ENTRY_SIZE); RETURN_IF_ERROR(_PyBytes_Resize(&a->a_linetable, len*2)); } - if (loc.lineno < 0) { + if (loc.lineno == NO_LOCATION.lineno) { write_location_info_none(a, isize); return SUCCESS; } int line_delta = loc.lineno - a->a_lineno; int column = loc.col_offset; int end_column = loc.end_col_offset; - assert(column >= -1); - assert(end_column >= -1); if (column < 0 || end_column < 0) { - if (loc.end_lineno == loc.lineno || loc.end_lineno == -1) { + if (loc.end_lineno == loc.lineno || loc.end_lineno < 0) { write_location_info_no_column(a, isize, line_delta); a->a_lineno = loc.lineno; return SUCCESS;