]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-142589: Fix PyUnstable_Object_IsUniqueReferencedTemporary (gh-142593)
authorSam Gross <colesbury@gmail.com>
Thu, 11 Dec 2025 19:41:03 +0000 (14:41 -0500)
committerGitHub <noreply@github.com>
Thu, 11 Dec 2025 19:41:03 +0000 (14:41 -0500)
PyUnstable_Object_IsUniqueReferencedTemporary wasn't handling tagged
ints on the evaluation stack properly.

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 c5040913e9e1f1110bfce92cf2dc55105315abae..67572ab1ba268d0223ed572209621a5a082637ae 100644 (file)
@@ -251,6 +251,13 @@ 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())
+
     def pyobject_dump(self, obj, release_gil=False):
         pyobject_dump = _testcapi.pyobject_dump
 
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 4c9632c07a99f4450b34e638f30a0d8cda98612f..a4f76c409c6f78bd5613a63792c9125262f6ee3c 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
@@ -517,6 +526,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 fcea3503de8213bf3633f8ec5cf86321c80a368b..36a37bb0bbea4dfb59a505bd4b1bef2c42622542 100644 (file)
@@ -2759,8 +2759,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;