]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
GH-145247: Use _PyTuple_FromPair[Steal] in Objects (#145884)
authorSergey Miryanov <sergey.miryanov@gmail.com>
Sat, 28 Mar 2026 00:01:01 +0000 (05:01 +0500)
committerGitHub <noreply@github.com>
Sat, 28 Mar 2026 00:01:01 +0000 (00:01 +0000)
Co-authored-by: Victor Stinner <vstinner@python.org>
Objects/codeobject.c
Objects/dictobject.c
Objects/enumobject.c
Objects/floatobject.c
Objects/frameobject.c
Objects/listobject.c
Objects/longobject.c
Objects/odictobject.c
Objects/stringlib/unicode_format.h
Objects/typeobject.c
Objects/typevarobject.c

index 891aa4ee78c0f27103ae0c76bb56050a5ea6716c..ad1116890e23ce82cc98731ad8b584a593801f84 100644 (file)
@@ -3052,7 +3052,7 @@ _PyCode_ConstantKey(PyObject *op)
     else if (PyBool_Check(op) || PyBytes_CheckExact(op)) {
         /* Make booleans different from integers 0 and 1.
          * Avoid BytesWarning from comparing bytes with strings. */
-        key = PyTuple_Pack(2, Py_TYPE(op), op);
+        key = _PyTuple_FromPair((PyObject *)Py_TYPE(op), op);
     }
     else if (PyFloat_CheckExact(op)) {
         double d = PyFloat_AS_DOUBLE(op);
@@ -3062,7 +3062,7 @@ _PyCode_ConstantKey(PyObject *op)
         if (d == 0.0 && copysign(1.0, d) < 0.0)
             key = PyTuple_Pack(3, Py_TYPE(op), op, Py_None);
         else
-            key = PyTuple_Pack(2, Py_TYPE(op), op);
+            key = _PyTuple_FromPair((PyObject *)Py_TYPE(op), op);
     }
     else if (PyComplex_CheckExact(op)) {
         Py_complex z;
@@ -3086,7 +3086,7 @@ _PyCode_ConstantKey(PyObject *op)
             key = PyTuple_Pack(3, Py_TYPE(op), op, Py_None);
         }
         else {
-            key = PyTuple_Pack(2, Py_TYPE(op), op);
+            key = _PyTuple_FromPair((PyObject *)Py_TYPE(op), op);
         }
     }
     else if (PyTuple_CheckExact(op)) {
@@ -3111,7 +3111,7 @@ _PyCode_ConstantKey(PyObject *op)
             PyTuple_SET_ITEM(tuple, i, item_key);
         }
 
-        key = PyTuple_Pack(2, tuple, op);
+        key = _PyTuple_FromPair(tuple, op);
         Py_DECREF(tuple);
     }
     else if (PyFrozenSet_CheckExact(op)) {
@@ -3145,7 +3145,7 @@ _PyCode_ConstantKey(PyObject *op)
         if (set == NULL)
             return NULL;
 
-        key = PyTuple_Pack(2, set, op);
+        key = _PyTuple_FromPair(set, op);
         Py_DECREF(set);
         return key;
     }
@@ -3176,7 +3176,7 @@ _PyCode_ConstantKey(PyObject *op)
             goto slice_exit;
         }
 
-        key = PyTuple_Pack(2, slice_key, op);
+        key = _PyTuple_FromPair(slice_key, op);
         Py_DECREF(slice_key);
     slice_exit:
         Py_XDECREF(start_key);
@@ -3190,7 +3190,7 @@ _PyCode_ConstantKey(PyObject *op)
         if (obj_id == NULL)
             return NULL;
 
-        key = PyTuple_Pack(2, obj_id, op);
+        key = _PyTuple_FromPair(obj_id, op);
         Py_DECREF(obj_id);
     }
     return key;
index 08e40bf84c42fa7b194668b79e0c5b42d652c4d2..a6c40454d52a711e81885922695a0b155735f43e 100644 (file)
@@ -5454,7 +5454,7 @@ dictiter_new(PyDictObject *dict, PyTypeObject *itertype)
     }
     if (itertype == &PyDictIterItem_Type ||
         itertype == &PyDictRevIterItem_Type) {
-        di->di_result = PyTuple_Pack(2, Py_None, Py_None);
+        di->di_result = _PyTuple_FromPairSteal(Py_None, Py_None);
         if (di->di_result == NULL) {
             Py_DECREF(di);
             return NULL;
@@ -6020,14 +6020,7 @@ dictiter_iternextitem(PyObject *self)
             _PyTuple_Recycle(result);
         }
         else {
-            result = PyTuple_New(2);
-            if (result == NULL) {
-                Py_DECREF(key);
-                Py_DECREF(value);
-                return NULL;
-            }
-            PyTuple_SET_ITEM(result, 0, key);
-            PyTuple_SET_ITEM(result, 1, value);
+            result = _PyTuple_FromPairSteal(key, value);
         }
         return result;
     }
@@ -6146,12 +6139,7 @@ dictreviter_iter_lock_held(PyDictObject *d, PyObject *self)
             _PyTuple_Recycle(result);
         }
         else {
-            result = PyTuple_New(2);
-            if (result == NULL) {
-                return NULL;
-            }
-            PyTuple_SET_ITEM(result, 0, Py_NewRef(key));
-            PyTuple_SET_ITEM(result, 1, Py_NewRef(value));
+            result = _PyTuple_FromPair(key, value);
         }
         return result;
     }
@@ -6644,18 +6632,22 @@ dictitems_xor_lock_held(PyObject *d1, PyObject *d2)
         else {
             Py_INCREF(val1);
             to_delete = PyObject_RichCompareBool(val1, val2, Py_EQ);
+            Py_CLEAR(val1);
             if (to_delete < 0) {
                 goto error;
             }
         }
 
         if (to_delete) {
+            Py_CLEAR(val2);
             if (_PyDict_DelItem_KnownHash(temp_dict, key, hash) < 0) {
                 goto error;
             }
+            Py_CLEAR(key);
         }
         else {
-            PyObject *pair = PyTuple_Pack(2, key, val2);
+            PyObject *pair = _PyTuple_FromPairSteal(key, val2);
+            key = val2 = NULL;
             if (pair == NULL) {
                 goto error;
             }
@@ -6665,11 +6657,7 @@ dictitems_xor_lock_held(PyObject *d1, PyObject *d2)
             }
             Py_DECREF(pair);
         }
-        Py_DECREF(key);
-        Py_XDECREF(val1);
-        Py_DECREF(val2);
     }
-    key = val1 = val2 = NULL;
 
     PyObject *remaining_pairs = PyObject_CallMethodNoArgs(
             temp_dict, &_Py_ID(items));
index 70e7cce6aba0082a1400563e49caefccf71f30d5..597b4c94dbf0d3ed57b58c27fe66a75296a54242 100644 (file)
@@ -78,7 +78,7 @@ enum_new_impl(PyTypeObject *type, PyObject *iterable, PyObject *start)
         Py_DECREF(en);
         return NULL;
     }
-    en->en_result = PyTuple_Pack(2, Py_None, Py_None);
+    en->en_result = _PyTuple_FromPairSteal(Py_None, Py_None);
     if (en->en_result == NULL) {
         Py_DECREF(en);
         return NULL;
@@ -226,15 +226,7 @@ enum_next_long(enumobject *en, PyObject* next_item)
         _PyTuple_Recycle(result);
         return result;
     }
-    result = PyTuple_New(2);
-    if (result == NULL) {
-        Py_DECREF(next_index);
-        Py_DECREF(next_item);
-        return NULL;
-    }
-    PyTuple_SET_ITEM(result, 0, next_index);
-    PyTuple_SET_ITEM(result, 1, next_item);
-    return result;
+    return _PyTuple_FromPairSteal(next_index, next_item);
 }
 
 static PyObject *
@@ -276,15 +268,7 @@ enum_next(PyObject *op)
         _PyTuple_Recycle(result);
         return result;
     }
-    result = PyTuple_New(2);
-    if (result == NULL) {
-        Py_DECREF(next_index);
-        Py_DECREF(next_item);
-        return NULL;
-    }
-    PyTuple_SET_ITEM(result, 0, next_index);
-    PyTuple_SET_ITEM(result, 1, next_item);
-    return result;
+    return _PyTuple_FromPairSteal(next_index, next_item);
 }
 
 static PyObject *
index 18871a4f3c51a95751cd1130a1935960c5c15c0c..d91468dddded9bf6b7902378e2e441b41d09fa67 100644 (file)
@@ -16,6 +16,7 @@
 #include "pycore_pystate.h"       // _PyInterpreterState_GET()
 #include "pycore_stackref.h"      // PyStackRef_AsPyObjectBorrow()
 #include "pycore_structseq.h"     // _PyStructSequence_FiniBuiltin()
+#include "pycore_tuple.h"         // _PyTuple_FromPair
 
 #include <float.h>                // DBL_MAX
 #include <stdlib.h>               // strtol()
@@ -1539,8 +1540,9 @@ float_as_integer_ratio_impl(PyObject *self)
         if (denominator == NULL)
             goto error;
     }
+    Py_DECREF(py_exponent);
 
-    result_pair = PyTuple_Pack(2, numerator, denominator);
+    return _PyTuple_FromPairSteal(numerator, denominator);
 
 error:
     Py_XDECREF(py_exponent);
index 8911de6f2bfc5b7a040424f0cddfced85fe1506d..5ae85c5bca61b94cbd22e72a7e1e0837731e36be 100644 (file)
@@ -13,6 +13,7 @@
 #include "pycore_object.h"        // _PyObject_GC_UNTRACK()
 #include "pycore_opcode_metadata.h" // _PyOpcode_Caches
 #include "pycore_optimizer.h"     // _Py_Executors_InvalidateDependency()
+#include "pycore_tuple.h"         // _PyTuple_FromPair
 #include "pycore_unicodeobject.h" // _PyUnicode_Equal()
 
 #include "frameobject.h"          // PyFrameLocalsProxyObject
@@ -630,22 +631,16 @@ framelocalsproxy_items(PyObject *self, PyObject *Py_UNUSED(ignored))
         PyObject *value = framelocalsproxy_getval(frame->f_frame, co, i);
 
         if (value) {
-            PyObject *pair = PyTuple_Pack(2, name, value);
+            PyObject *pair = _PyTuple_FromPairSteal(Py_NewRef(name), value);
             if (pair == NULL) {
-                Py_DECREF(items);
-                Py_DECREF(value);
-                return NULL;
-            }
-
-            if (PyList_Append(items, pair) < 0) {
-                Py_DECREF(items);
-                Py_DECREF(pair);
-                Py_DECREF(value);
-                return NULL;
+                goto error;
             }
 
+            int rc = PyList_Append(items, pair);
             Py_DECREF(pair);
-            Py_DECREF(value);
+            if (rc < 0) {
+                goto error;
+            }
         }
     }
 
@@ -655,23 +650,24 @@ framelocalsproxy_items(PyObject *self, PyObject *Py_UNUSED(ignored))
         PyObject *key = NULL;
         PyObject *value = NULL;
         while (PyDict_Next(frame->f_extra_locals, &j, &key, &value)) {
-            PyObject *pair = PyTuple_Pack(2, key, value);
+            PyObject *pair = _PyTuple_FromPair(key, value);
             if (pair == NULL) {
-                Py_DECREF(items);
-                return NULL;
-            }
-
-            if (PyList_Append(items, pair) < 0) {
-                Py_DECREF(items);
-                Py_DECREF(pair);
-                return NULL;
+                goto error;
             }
 
+            int rc = PyList_Append(items, pair);
             Py_DECREF(pair);
+            if (rc < 0) {
+                goto error;
+            }
         }
     }
 
     return items;
+
+error:
+    Py_DECREF(items);
+    return NULL;
 }
 
 static Py_ssize_t
index 654b8130e70840f7b0e2c9f36625219789340796..5c9fd55bab1b22d9491567ec3e6d1e257c4fc900 100644 (file)
@@ -1437,9 +1437,9 @@ list_extend_dictitems(PyListObject *self, PyDictObject *dict)
     PyObject **dest = self->ob_item + m;
     Py_ssize_t pos = 0;
     Py_ssize_t i = 0;
-    PyObject *key_value[2];
-    while (_PyDict_Next((PyObject *)dict, &pos, &key_value[0], &key_value[1], NULL)) {
-        PyObject *item = PyTuple_FromArray(key_value, 2);
+    PyObject *key, *value;
+    while (_PyDict_Next((PyObject *)dict, &pos, &key, &value, NULL)) {
+        PyObject *item = _PyTuple_FromPair(key, value);
         if (item == NULL) {
             Py_SET_SIZE(self, m + i);
             return -1;
index 7ce5d0535b884ea639784d8547555bee2e3a5a52..f1971f0fca993c5ba86eafb62090a92f72042ba6 100644 (file)
@@ -12,6 +12,7 @@
 #include "pycore_runtime.h"       // _PY_NSMALLPOSINTS
 #include "pycore_stackref.h"
 #include "pycore_structseq.h"     // _PyStructSequence_FiniBuiltin()
+#include "pycore_tuple.h"         // _PyTuple_FromPairSteal
 #include "pycore_unicodeobject.h" // _PyUnicode_Equal()
 
 #include <float.h>                // DBL_MANT_DIG
@@ -4878,23 +4879,12 @@ static PyObject *
 long_divmod(PyObject *a, PyObject *b)
 {
     PyLongObject *div, *mod;
-    PyObject *z;
-
     CHECK_BINOP(a, b);
 
     if (l_divmod((PyLongObject*)a, (PyLongObject*)b, &div, &mod) < 0) {
         return NULL;
     }
-    z = PyTuple_New(2);
-    if (z != NULL) {
-        PyTuple_SET_ITEM(z, 0, (PyObject *) div);
-        PyTuple_SET_ITEM(z, 1, (PyObject *) mod);
-    }
-    else {
-        Py_DECREF(div);
-        Py_DECREF(mod);
-    }
-    return z;
+    return _PyTuple_FromPairSteal((PyObject *)div, (PyObject *)mod);
 }
 
 
@@ -6118,7 +6108,7 @@ PyObject *
 _PyLong_DivmodNear(PyObject *a, PyObject *b)
 {
     PyLongObject *quo = NULL, *rem = NULL;
-    PyObject *twice_rem, *result, *temp;
+    PyObject *twice_rem, *temp;
     int quo_is_odd, quo_is_neg;
     Py_ssize_t cmp;
 
@@ -6184,14 +6174,7 @@ _PyLong_DivmodNear(PyObject *a, PyObject *b)
             goto error;
     }
 
-    result = PyTuple_New(2);
-    if (result == NULL)
-        goto error;
-
-    /* PyTuple_SET_ITEM steals references */
-    PyTuple_SET_ITEM(result, 0, (PyObject *)quo);
-    PyTuple_SET_ITEM(result, 1, (PyObject *)rem);
-    return result;
+    return _PyTuple_FromPairSteal((PyObject *)quo, (PyObject *)rem);
 
   error:
     Py_XDECREF(quo);
@@ -6368,14 +6351,11 @@ static PyObject *
 int_as_integer_ratio_impl(PyObject *self)
 /*[clinic end generated code: output=e60803ae1cc8621a input=384ff1766634bec2]*/
 {
-    PyObject *ratio_tuple;
     PyObject *numerator = long_long(self);
     if (numerator == NULL) {
         return NULL;
     }
-    ratio_tuple = PyTuple_Pack(2, numerator, _PyLong_GetOne());
-    Py_DECREF(numerator);
-    return ratio_tuple;
+    return _PyTuple_FromPairSteal(numerator, _PyLong_GetOne());
 }
 
 /*[clinic input]
index 25928028919c9c6d6380079f0e5a25f9203583dc..e3ec0ae470c5d8498c10613eed9d22f33718a3a5 100644 (file)
@@ -1156,7 +1156,7 @@ static PyObject *
 OrderedDict_popitem_impl(PyODictObject *self, int last)
 /*[clinic end generated code: output=98e7d986690d49eb input=8aafc7433e0a40e7]*/
 {
-    PyObject *key, *value, *item = NULL;
+    PyObject *key, *value;
     _ODictNode *node;
 
     /* pull the item */
@@ -1169,12 +1169,11 @@ OrderedDict_popitem_impl(PyODictObject *self, int last)
     node = last ? _odict_LAST(self) : _odict_FIRST(self);
     key = Py_NewRef(_odictnode_KEY(node));
     value = _odict_popkey_hash((PyObject *)self, key, NULL, _odictnode_HASH(node));
-    if (value == NULL)
+    if (value == NULL) {
+        Py_DECREF(key);
         return NULL;
-    item = PyTuple_Pack(2, key, value);
-    Py_DECREF(key);
-    Py_DECREF(value);
-    return item;
+    }
+    return _PyTuple_FromPairSteal(key, value);
 }
 
 /* keys() */
@@ -1807,7 +1806,7 @@ odictiter_iternext_lock_held(PyObject *op)
         if (!PyErr_Occurred())
             PyErr_SetObject(PyExc_KeyError, key);
         Py_DECREF(key);
-        goto done;
+        goto error;
     }
 
     /* Handle the values case. */
@@ -1828,21 +1827,19 @@ odictiter_iternext_lock_held(PyObject *op)
         // bpo-42536: The GC may have untracked this result tuple. Since we're
         // recycling it, make sure it's tracked again:
         _PyTuple_Recycle(result);
+        PyTuple_SET_ITEM(result, 0, key);  /* steals reference */
+        PyTuple_SET_ITEM(result, 1, value);  /* steals reference */
     }
     else {
-        result = PyTuple_New(2);
+        result = _PyTuple_FromPairSteal(key, value);
         if (result == NULL) {
-            Py_DECREF(key);
-            Py_DECREF(value);
-            goto done;
+            goto error;
         }
     }
 
-    PyTuple_SET_ITEM(result, 0, key);  /* steals reference */
-    PyTuple_SET_ITEM(result, 1, value);  /* steals reference */
     return result;
 
-done:
+error:
     Py_CLEAR(di->di_current);
     Py_CLEAR(di->di_odict);
     return NULL;
@@ -1933,7 +1930,7 @@ odictiter_new(PyODictObject *od, int kind)
         return NULL;
 
     if ((kind & _odict_ITER_ITEMS) == _odict_ITER_ITEMS) {
-        di->di_result = PyTuple_Pack(2, Py_None, Py_None);
+        di->di_result = _PyTuple_FromPairSteal(Py_None, Py_None);
         if (di->di_result == NULL) {
             Py_DECREF(di);
             return NULL;
index ff32db65b11a0b1ea5c4bbeac3905706cb108bc4..c9c46283840d1888614bea6724ee0e4d1677c97b 100644 (file)
@@ -4,6 +4,7 @@
 
 #include "pycore_complexobject.h" // _PyComplex_FormatAdvancedWriter()
 #include "pycore_floatobject.h"   // _PyFloat_FormatAdvancedWriter()
+#include "pycore_tuple.h"         // _PyTuple_FromPairSteal
 
 /************************************************************************/
 /***********   Global data structures and forward declarations  *********/
@@ -1172,7 +1173,7 @@ fieldnameiter_next(PyObject *op)
 
         is_attr_obj = PyBool_FromLong(is_attr);
         if (is_attr_obj == NULL)
-            goto done;
+            goto error;
 
         /* either an integer or a string */
         if (idx != -1)
@@ -1180,12 +1181,12 @@ fieldnameiter_next(PyObject *op)
         else
             obj = SubString_new_object(&name);
         if (obj == NULL)
-            goto done;
+            goto error;
 
         /* return a tuple of values */
-        result = PyTuple_Pack(2, is_attr_obj, obj);
+        return _PyTuple_FromPairSteal(is_attr_obj, obj);
 
-    done:
+    error:
         Py_XDECREF(is_attr_obj);
         Py_XDECREF(obj);
         return result;
@@ -1262,7 +1263,7 @@ formatter_field_name_split(PyObject *Py_UNUSED(module), PyObject *self)
        first_obj in that case. */
     if (!field_name_split((PyObject*)self, 0, PyUnicode_GET_LENGTH(self),
                           &first, &first_idx, &it->it_field, NULL))
-        goto done;
+        goto error;
 
     /* first becomes an integer, if possible; else a string */
     if (first_idx != -1)
@@ -1271,12 +1272,12 @@ formatter_field_name_split(PyObject *Py_UNUSED(module), PyObject *self)
         /* convert "first" into a string object */
         first_obj = SubString_new_object(&first);
     if (first_obj == NULL)
-        goto done;
+        goto error;
 
     /* return a tuple of values */
-    result = PyTuple_Pack(2, first_obj, it);
+    return _PyTuple_FromPairSteal(first_obj, (PyObject *)it);
 
-done:
+error:
     Py_XDECREF(it);
     Py_XDECREF(first_obj);
     return result;
index 66f6c3fb3c0aad6591b9a30e03ae1ebfc475df6a..3374051c42af8a7f944e55d547498e08012684b2 100644 (file)
@@ -19,6 +19,7 @@
 #include "pycore_pyerrors.h"      // _PyErr_Occurred()
 #include "pycore_pystate.h"       // _PyThreadState_GET()
 #include "pycore_symtable.h"      // _Py_Mangle()
+#include "pycore_tuple.h"         // _PyTuple_FromPair
 #include "pycore_typeobject.h"    // struct type_cache
 #include "pycore_unicodeobject.h" // _PyUnicode_Copy
 #include "pycore_unionobject.h"   // _Py_union_type_or
@@ -1811,7 +1812,7 @@ mro_hierarchy_for_complete_type(PyTypeObject *type, PyObject *temp)
         tuple = PyTuple_Pack(3, type, new_mro, old_mro);
     }
     else {
-        tuple = PyTuple_Pack(2, type, new_mro);
+        tuple = _PyTuple_FromPair((PyObject *)type, new_mro);
     }
 
     if (tuple != NULL) {
@@ -7855,7 +7856,7 @@ object_getstate_default(PyObject *obj, int required)
         if (PyDict_GET_SIZE(slots) > 0) {
             PyObject *state2;
 
-            state2 = PyTuple_Pack(2, state, slots);
+            state2 = _PyTuple_FromPair(state, slots);
             Py_DECREF(state);
             if (state2 == NULL) {
                 Py_DECREF(slotnames);
index 0a260f4c10278c206db04a991f3fc77616edbce0..a206bd7b5dd40495a40e1f22bd02bfe23991348c 100644 (file)
@@ -2,6 +2,7 @@
 #include "Python.h"
 #include "pycore_interpframe.h"   // _PyInterpreterFrame
 #include "pycore_object.h"        // _PyObject_GC_TRACK/UNTRACK, PyAnnotateFormat
+#include "pycore_tuple.h"         // _PyTuple_FromPair
 #include "pycore_typevarobject.h"
 #include "pycore_unicodeobject.h" // _PyUnicode_EqualToASCIIString()
 #include "pycore_unionobject.h"   // _Py_union_type_or, _Py_union_from_tuple
@@ -373,7 +374,7 @@ type_check(PyObject *arg, const char *msg)
 static PyObject *
 make_union(PyObject *self, PyObject *other)
 {
-    PyObject *args = PyTuple_Pack(2, self, other);
+    PyObject *args = _PyTuple_FromPair(self, other);
     if (args == NULL) {
         return NULL;
     }