]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.14] gh-142589: Fix PyUnstable_Object_IsUniqueReferencedTemporary (gh-142593) ...
authorSam Gross <colesbury@gmail.com>
Thu, 11 Dec 2025 20:08:45 +0000 (15:08 -0500)
committerGitHub <noreply@github.com>
Thu, 11 Dec 2025 20:08:45 +0000 (20:08 +0000)
PyUnstable_Object_IsUniqueReferencedTemporary wasn't handling tagged
ints on the evaluation stack properly.
(cherry picked from commit a26c831bc486b6e607cee6a5923bad52b97c2341)

Lib/test/test_capi/test_object.py
Misc/NEWS.d/next/C_API/2025-12-11-13-01-49.gh-issue-142589.nNAqgw.rst [new file with mode: 0644]
Modules/_testcapi/object.c
Objects/object.c

index 98a9a096cfee4d888fa6668526a9c3b9fe6a1a25..807b62c19863e70f3cf399799103199c6fb5e27f 100644 (file)
@@ -247,5 +247,12 @@ class CAPITest(unittest.TestCase):
 
         func(object())
 
+        # Test that a newly created object in C is not considered
+        # a uniquely referenced temporary, because it's not on the stack.
+        # gh-142586: do the test in a loop over a list to test for handling
+        # tagged ints on the stack.
+        for i in [0, 1, 2]:
+            self.assertFalse(_testcapi.pyobject_is_unique_temporary_new_object())
+
 if __name__ == "__main__":
     unittest.main()
diff --git a/Misc/NEWS.d/next/C_API/2025-12-11-13-01-49.gh-issue-142589.nNAqgw.rst b/Misc/NEWS.d/next/C_API/2025-12-11-13-01-49.gh-issue-142589.nNAqgw.rst
new file mode 100644 (file)
index 0000000..529277b
--- /dev/null
@@ -0,0 +1,2 @@
+Fix :c:func:`PyUnstable_Object_IsUniqueReferencedTemporary()` handling of
+tagged ints on the interpreter stack.
index 798ef97c495aeb453978122da2caf0882dbf03b8..4d53b3c678a470d694d45ba27cdb3269e2659a55 100644 (file)
@@ -138,6 +138,15 @@ pyobject_is_unique_temporary(PyObject *self, PyObject *obj)
     return PyLong_FromLong(result);
 }
 
+static PyObject *
+pyobject_is_unique_temporary_new_object(PyObject *self, PyObject *unused)
+{
+    PyObject *obj = PyList_New(0);
+    int result = PyUnstable_Object_IsUniqueReferencedTemporary(obj);
+    Py_DECREF(obj);
+    return PyLong_FromLong(result);
+}
+
 static int MyObject_dealloc_called = 0;
 
 static void
@@ -493,6 +502,7 @@ static PyMethodDef test_methods[] = {
     {"pyobject_clear_weakrefs_no_callbacks", pyobject_clear_weakrefs_no_callbacks, METH_O},
     {"pyobject_enable_deferred_refcount", pyobject_enable_deferred_refcount, METH_O},
     {"pyobject_is_unique_temporary", pyobject_is_unique_temporary, METH_O},
+    {"pyobject_is_unique_temporary_new_object", pyobject_is_unique_temporary_new_object, METH_NOARGS},
     {"test_py_try_inc_ref", test_py_try_inc_ref, METH_NOARGS},
     {"test_xincref_doesnt_leak",test_xincref_doesnt_leak,        METH_NOARGS},
     {"test_incref_doesnt_leak", test_incref_doesnt_leak,         METH_NOARGS},
index 8dc3ab9643cbb2a905652fd326c2edf3d5bb749d..b88110faf921a390974c23b0d7735090eac2fa42 100644 (file)
@@ -2631,8 +2631,12 @@ PyUnstable_Object_IsUniqueReferencedTemporary(PyObject *op)
     _PyStackRef *stackpointer = frame->stackpointer;
     while (stackpointer > base) {
         stackpointer--;
-        if (op == PyStackRef_AsPyObjectBorrow(*stackpointer)) {
-            return PyStackRef_IsHeapSafe(*stackpointer);
+        _PyStackRef ref = *stackpointer;
+        if (PyStackRef_IsTaggedInt(ref)) {
+            continue;
+        }
+        if (op == PyStackRef_AsPyObjectBorrow(ref)) {
+            return PyStackRef_IsHeapSafe(ref);
         }
     }
     return 0;