https://github.com/python/cpython/commit/12d2b95adff88a3395227ec7b28b2c81d879f455
commit: 12d2b95adff88a3395227ec7b28b2c81d879f455
branch: 3.14
author: Sam Gross <[email protected]>
committer: colesbury <[email protected]>
date: 2025-12-11T20:08:45Z
summary:
[3.14] gh-142589: Fix PyUnstable_Object_IsUniqueReferencedTemporary (gh-142593)
(#142597)
PyUnstable_Object_IsUniqueReferencedTemporary wasn't handling tagged
ints on the evaluation stack properly.
(cherry picked from commit a26c831bc486b6e607cee6a5923bad52b97c2341)
files:
A Misc/NEWS.d/next/C_API/2025-12-11-13-01-49.gh-issue-142589.nNAqgw.rst
M Lib/test/test_capi/test_object.py
M Modules/_testcapi/object.c
M Objects/object.c
diff --git a/Lib/test/test_capi/test_object.py
b/Lib/test/test_capi/test_object.py
index 98a9a096cfee4d..807b62c19863e7 100644
--- a/Lib/test/test_capi/test_object.py
+++ b/Lib/test/test_capi/test_object.py
@@ -247,5 +247,12 @@ def func(x):
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
index 00000000000000..529277b951ada3
--- /dev/null
+++ b/Misc/NEWS.d/next/C_API/2025-12-11-13-01-49.gh-issue-142589.nNAqgw.rst
@@ -0,0 +1,2 @@
+Fix :c:func:`PyUnstable_Object_IsUniqueReferencedTemporary()` handling of
+tagged ints on the interpreter stack.
diff --git a/Modules/_testcapi/object.c b/Modules/_testcapi/object.c
index 798ef97c495aeb..4d53b3c678a470 100644
--- a/Modules/_testcapi/object.c
+++ b/Modules/_testcapi/object.c
@@ -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},
diff --git a/Objects/object.c b/Objects/object.c
index 8dc3ab9643cbb2..b88110faf921a3 100644
--- a/Objects/object.c
+++ b/Objects/object.c
@@ -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;
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]