]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.14] gh-146250: Fix memory leak in re-initialization of `SyntaxError` (GH-146251...
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Mon, 30 Mar 2026 16:14:58 +0000 (18:14 +0200)
committerGitHub <noreply@github.com>
Mon, 30 Mar 2026 16:14:58 +0000 (16:14 +0000)
Co-authored-by: Brij Kapadia <97006829+bkap123@users.noreply.github.com>
Lib/test/test_exceptions.py
Misc/NEWS.d/next/Core_and_Builtins/2026-03-21-11-55-16.gh-issue-146250.ahl3O2.rst [new file with mode: 0644]
Objects/exceptions.c

index 4f5ffe66eaf585a6daeca397b3c7c4ed459a9d78..117bf4b94d79b4afe64097677f6a0903ef14abcd 100644 (file)
@@ -2508,6 +2508,30 @@ class SyntaxErrorTests(unittest.TestCase):
         args = ("bad.py", 1, 2, "abcdefg", 1)
         self.assertRaises(TypeError, SyntaxError, "bad bad", args)
 
+    def test_syntax_error_memory_leak(self):
+        # gh-146250: memory leak with re-initialization of SyntaxError
+        e = SyntaxError("msg", ("file.py", 1, 2, "txt", 2, 3))
+        e.__init__("new_msg", ("new_file.py", 2, 3, "new_txt", 3, 4))
+        self.assertEqual(e.msg, "new_msg")
+        self.assertEqual(e.args, ("new_msg", ("new_file.py", 2, 3, "new_txt", 3, 4)))
+        self.assertEqual(e.filename, "new_file.py")
+        self.assertEqual(e.lineno, 2)
+        self.assertEqual(e.offset, 3)
+        self.assertEqual(e.text, "new_txt")
+        self.assertEqual(e.end_lineno, 3)
+        self.assertEqual(e.end_offset, 4)
+
+        e = SyntaxError("msg", ("file.py", 1, 2, "txt", 2, 3))
+        e.__init__("new_msg", ("new_file.py", 2, 3, "new_txt"))
+        self.assertEqual(e.msg, "new_msg")
+        self.assertEqual(e.args, ("new_msg", ("new_file.py", 2, 3, "new_txt")))
+        self.assertEqual(e.filename, "new_file.py")
+        self.assertEqual(e.lineno, 2)
+        self.assertEqual(e.offset, 3)
+        self.assertEqual(e.text, "new_txt")
+        self.assertIsNone(e.end_lineno)
+        self.assertIsNone(e.end_offset)
+
 
 class TestInvalidExceptionMatcher(unittest.TestCase):
     def test_except_star_invalid_exception_type(self):
diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-21-11-55-16.gh-issue-146250.ahl3O2.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-21-11-55-16.gh-issue-146250.ahl3O2.rst
new file mode 100644 (file)
index 0000000..fff07b3
--- /dev/null
@@ -0,0 +1 @@
+Fixed a memory leak in :exc:`SyntaxError` when re-initializing it.
index 848786dfb447fafecf4775dcb9ea003c7e17d68c..59c695347d3d09e3d4fd3480ce9770d7bb360dd1 100644 (file)
@@ -2729,23 +2729,25 @@ SyntaxError_init(PyObject *op, PyObject *args, PyObject *kwds)
             return -1;
         }
 
-        self->end_lineno = NULL;
-        self->end_offset = NULL;
+        PyObject *filename, *lineno, *offset, *text;
+        PyObject *end_lineno = NULL;
+        PyObject *end_offset = NULL;
+        PyObject *metadata = NULL;
         if (!PyArg_ParseTuple(info, "OOOO|OOO",
-                              &self->filename, &self->lineno,
-                              &self->offset, &self->text,
-                              &self->end_lineno, &self->end_offset, &self->metadata)) {
+                              &filename, &lineno,
+                              &offset, &text,
+                              &end_lineno, &end_offset, &metadata)) {
             Py_DECREF(info);
             return -1;
         }
 
-        Py_INCREF(self->filename);
-        Py_INCREF(self->lineno);
-        Py_INCREF(self->offset);
-        Py_INCREF(self->text);
-        Py_XINCREF(self->end_lineno);
-        Py_XINCREF(self->end_offset);
-        Py_XINCREF(self->metadata);
+        Py_XSETREF(self->filename, Py_NewRef(filename));
+        Py_XSETREF(self->lineno, Py_NewRef(lineno));
+        Py_XSETREF(self->offset, Py_NewRef(offset));
+        Py_XSETREF(self->text, Py_NewRef(text));
+        Py_XSETREF(self->end_lineno, Py_XNewRef(end_lineno));
+        Py_XSETREF(self->end_offset, Py_XNewRef(end_offset));
+        Py_XSETREF(self->metadata, Py_XNewRef(metadata));
         Py_DECREF(info);
 
         if (self->end_lineno != NULL && self->end_offset == NULL) {