]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-130775: Allow negative locations in `ast` (#130795)
authorsobolevn <mail@sobolevn.me>
Mon, 7 Apr 2025 16:35:17 +0000 (19:35 +0300)
committerGitHub <noreply@github.com>
Mon, 7 Apr 2025 16:35:17 +0000 (19:35 +0300)
Co-authored-by: Victor Stinner <vstinner@python.org>
Lib/test/test_ast/test_ast.py
Misc/NEWS.d/next/Core_and_Builtins/2025-03-03-20-02-45.gh-issue-130775.fEM6T-.rst [new file with mode: 0644]
Python/assemble.c

index 70fbe792e9bdabbab3da0ffdb659d9e80e39b1e9..090544726c31a41a0e418cfe4cd4bb4044f9cd6b 100644 (file)
@@ -189,6 +189,26 @@ class AST_Tests(unittest.TestCase):
         # Check that compilation doesn't crash. Note: this may crash explicitly only on debug mode.
         compile(tree, "<string>", "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, "<string>", "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 (file)
index 0000000..53408cd
--- /dev/null
@@ -0,0 +1 @@
+Do not crash on negative ``column`` and ``end_column`` in :mod:`ast` locations.
index 5efaf0d84a1f3185e90e483bb535969fcf0f1227..5f7af682eca0eff69bb2eb54b9f757078d8760b0 100644 (file)
@@ -290,18 +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) {
-        assert(loc.lineno == NO_LOCATION.lineno);
+    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;