From 2ef486a2b634fab2312851388ebc924ac096e091 Mon Sep 17 00:00:00 2001 From: Sergey Miryanov Date: Sat, 7 Nov 2026 11:23:41 +0500 Subject: [PATCH] GH-159101: Fix UAF when tp_finalize changes the base class (GH-159888) (cherry picked from commit 6c5596c7199792ea1e8cf26f65da8cd0023c0473) Co-authored-by: Sergey Miryanov Co-authored-by: Peter Bierma --- .../2026-10-20-20-38-38.gh-issue-159101.vFwrZY.rst | 2 ++ Objects/object.c | 8 ++++---- Objects/typeobject.c | 4 ++++ 3 files changed, 10 insertions(+), 4 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-10-20-20-38-38.gh-issue-159101.vFwrZY.rst diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-10-20-20-38-38.gh-issue-159101.vFwrZY.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-10-20-20-38-38.gh-issue-159101.vFwrZY.rst new file mode 100644 index 000000000000000..33beb8d571d7eca --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-10-20-20-38-38.gh-issue-159101.vFwrZY.rst @@ -0,0 +1,2 @@ +Fix use-after-free when :meth:`~object.__del__` changes the base class. Patch by +Sergey Miryanov. diff --git a/Objects/object.c b/Objects/object.c index b0bfaf0a5c4195b..d189bed0c6492b2 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -581,13 +581,13 @@ PyObject_CallFinalizer(PyObject *self) if (tp->tp_finalize == NULL) return; /* tp_finalize should only be called once. */ - if (_PyType_IS_GC(tp) && _PyGC_FINALIZED(self)) - return; - - tp->tp_finalize(self); if (_PyType_IS_GC(tp)) { + if (_PyGC_FINALIZED(self)) + return; + _PyGC_SET_FINALIZED(self); } + tp->tp_finalize(self); } int diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 519f3cb85483d46..8c62ff06c02ce93 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -2701,6 +2701,10 @@ subtype_dealloc(PyObject *self) } _PyObject_GC_UNTRACK(self); } + + /* Extract the type again; tp_finalize may have changed it */ + type = Py_TYPE(self); + /* If we added a weaklist, we clear it. Do this *before* calling tp_del, clearing slots, or clearing the instance dict.