From ab0f37454e1ccfc36f572f92eeb68a644bf89337 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Sun, 9 Nov 2025 13:41:08 +0100 Subject: [PATCH] gh-140530: fix a reference leak in an error path for `raise exc from cause` (#140908) Fix a reference leak in `raise E from T` when `T` is an exception subtype for which `T.__new__` does not return an exception instance. (cherry picked from commit 0c77e7c23b5c270a3142105542c56c59b59c52a0) --- Lib/test/test_raise.py | 18 +++++++----------- ...5-11-02-12-47-38.gh-issue-140530.S934bp.rst | 2 ++ Python/ceval.c | 1 + 3 files changed, 10 insertions(+), 11 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2025-11-02-12-47-38.gh-issue-140530.S934bp.rst diff --git a/Lib/test/test_raise.py b/Lib/test/test_raise.py index 6d26a61bee4292..ca253585e1a8aa 100644 --- a/Lib/test/test_raise.py +++ b/Lib/test/test_raise.py @@ -186,18 +186,14 @@ def test_class_cause(self): self.fail("No exception raised") def test_class_cause_nonexception_result(self): - class ConstructsNone(BaseException): - @classmethod + # See https://github.com/python/cpython/issues/140530. + class ConstructMortal(BaseException): def __new__(*args, **kwargs): - return None - try: - raise IndexError from ConstructsNone - except TypeError as e: - self.assertIn("should have returned an instance of BaseException", str(e)) - except IndexError: - self.fail("Wrong kind of exception raised") - else: - self.fail("No exception raised") + return ["mortal value"] + + msg = ".*should have returned an instance of BaseException.*" + with self.assertRaisesRegex(TypeError, msg): + raise IndexError from ConstructMortal def test_instance_cause(self): cause = KeyError() diff --git a/Misc/NEWS.d/next/Core and Builtins/2025-11-02-12-47-38.gh-issue-140530.S934bp.rst b/Misc/NEWS.d/next/Core and Builtins/2025-11-02-12-47-38.gh-issue-140530.S934bp.rst new file mode 100644 index 00000000000000..e3af493893afcb --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2025-11-02-12-47-38.gh-issue-140530.S934bp.rst @@ -0,0 +1,2 @@ +Fix a reference leak when ``raise exc from cause`` fails. Patch by Bénédikt +Tran. diff --git a/Python/ceval.c b/Python/ceval.c index a73b362e58a47b..0be6c57c1cf1dd 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1962,6 +1962,7 @@ do_raise(PyThreadState *tstate, PyObject *exc, PyObject *cause) "calling %R should have returned an instance of " "BaseException, not %R", cause, Py_TYPE(fixed_cause)); + Py_DECREF(fixed_cause); goto raise_error; } Py_DECREF(cause);