[Python-checkins] gh-99537: Use Py_SETREF() function in C code (#99656)

vstinner webhook-mailer at python.org
Tue Nov 22 08:22:31 EST 2022


https://github.com/python/cpython/commit/7e3f09cad9b783d8968aa79ff6a8ee57beb8b83e
commit: 7e3f09cad9b783d8968aa79ff6a8ee57beb8b83e
branch: main
author: Victor Stinner <vstinner at python.org>
committer: vstinner <vstinner at python.org>
date: 2022-11-22T14:22:22+01:00
summary:

gh-99537: Use Py_SETREF() function in C code (#99656)

Fix potential race condition in code patterns:

* Replace "Py_DECREF(var); var = new;" with "Py_SETREF(var, new);"
* Replace "Py_XDECREF(var); var = new;" with "Py_XSETREF(var, new);"
* Replace "Py_CLEAR(var); var = new;" with "Py_XSETREF(var, new);"

Other changes:

* Replace "old = var; var = new; Py_DECREF(var)"
  with "Py_SETREF(var, new);"
* Replace "old = var; var = new; Py_XDECREF(var)"
  with "Py_XSETREF(var, new);"
* And remove the "old" variable.

files:
M Doc/includes/custom2.c
M Doc/includes/custom3.c
M Doc/includes/custom4.c
M Modules/_collectionsmodule.c
M Modules/_datetimemodule.c
M Modules/_elementtree.c
M Modules/_functoolsmodule.c
M Modules/_io/stringio.c
M Modules/_io/textio.c
M Modules/_json.c
M Modules/_pickle.c
M Modules/_sqlite/cursor.c
M Modules/_testinternalcapi.c
M Modules/_tkinter.c
M Modules/_zoneinfo.c
M Modules/audioop.c
M Modules/cjkcodecs/multibytecodec.c
M Modules/itertoolsmodule.c
M Modules/mathmodule.c
M Modules/posixmodule.c

diff --git a/Doc/includes/custom2.c b/Doc/includes/custom2.c
index 6638b9fbc1d7..a3b2d6ab78d3 100644
--- a/Doc/includes/custom2.c
+++ b/Doc/includes/custom2.c
@@ -42,7 +42,7 @@ static int
 Custom_init(CustomObject *self, PyObject *args, PyObject *kwds)
 {
     static char *kwlist[] = {"first", "last", "number", NULL};
-    PyObject *first = NULL, *last = NULL, *tmp;
+    PyObject *first = NULL, *last = NULL;
 
     if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOi", kwlist,
                                      &first, &last,
@@ -50,14 +50,10 @@ Custom_init(CustomObject *self, PyObject *args, PyObject *kwds)
         return -1;
 
     if (first) {
-        tmp = self->first;
-        self->first = Py_NewRef(first);
-        Py_XDECREF(tmp);
+        Py_XSETREF(self->first, Py_NewRef(first));
     }
     if (last) {
-        tmp = self->last;
-        self->last = Py_NewRef(last);
-        Py_XDECREF(tmp);
+        Py_XSETREF(self->last, Py_NewRef(last));
     }
     return 0;
 }
diff --git a/Doc/includes/custom3.c b/Doc/includes/custom3.c
index 0faf2bd4be17..1a68bc4be8c3 100644
--- a/Doc/includes/custom3.c
+++ b/Doc/includes/custom3.c
@@ -42,7 +42,7 @@ static int
 Custom_init(CustomObject *self, PyObject *args, PyObject *kwds)
 {
     static char *kwlist[] = {"first", "last", "number", NULL};
-    PyObject *first = NULL, *last = NULL, *tmp;
+    PyObject *first = NULL, *last = NULL;
 
     if (!PyArg_ParseTupleAndKeywords(args, kwds, "|UUi", kwlist,
                                      &first, &last,
@@ -50,14 +50,10 @@ Custom_init(CustomObject *self, PyObject *args, PyObject *kwds)
         return -1;
 
     if (first) {
-        tmp = self->first;
-        self->first = Py_NewRef(first);
-        Py_DECREF(tmp);
+        Py_SETREF(self->first, Py_NewRef(first));
     }
     if (last) {
-        tmp = self->last;
-        self->last = Py_NewRef(last);
-        Py_DECREF(tmp);
+        Py_SETREF(self->last, Py_NewRef(last));
     }
     return 0;
 }
@@ -77,7 +73,6 @@ Custom_getfirst(CustomObject *self, void *closure)
 static int
 Custom_setfirst(CustomObject *self, PyObject *value, void *closure)
 {
-    PyObject *tmp;
     if (value == NULL) {
         PyErr_SetString(PyExc_TypeError, "Cannot delete the first attribute");
         return -1;
@@ -87,9 +82,7 @@ Custom_setfirst(CustomObject *self, PyObject *value, void *closure)
                         "The first attribute value must be a string");
         return -1;
     }
-    tmp = self->first;
-    self->first = Py_NewRef(value);
-    Py_DECREF(tmp);
+    Py_SETREF(self->first, Py_NewRef(value));
     return 0;
 }
 
@@ -102,7 +95,6 @@ Custom_getlast(CustomObject *self, void *closure)
 static int
 Custom_setlast(CustomObject *self, PyObject *value, void *closure)
 {
-    PyObject *tmp;
     if (value == NULL) {
         PyErr_SetString(PyExc_TypeError, "Cannot delete the last attribute");
         return -1;
@@ -112,9 +104,7 @@ Custom_setlast(CustomObject *self, PyObject *value, void *closure)
                         "The last attribute value must be a string");
         return -1;
     }
-    tmp = self->last;
-    self->last = Py_NewRef(value);
-    Py_DECREF(tmp);
+    Py_SETREF(self->last, Py_NewRef(value));
     return 0;
 }
 
diff --git a/Doc/includes/custom4.c b/Doc/includes/custom4.c
index b725bc0b6fae..b932d159d26e 100644
--- a/Doc/includes/custom4.c
+++ b/Doc/includes/custom4.c
@@ -58,7 +58,7 @@ static int
 Custom_init(CustomObject *self, PyObject *args, PyObject *kwds)
 {
     static char *kwlist[] = {"first", "last", "number", NULL};
-    PyObject *first = NULL, *last = NULL, *tmp;
+    PyObject *first = NULL, *last = NULL;
 
     if (!PyArg_ParseTupleAndKeywords(args, kwds, "|UUi", kwlist,
                                      &first, &last,
@@ -66,14 +66,10 @@ Custom_init(CustomObject *self, PyObject *args, PyObject *kwds)
         return -1;
 
     if (first) {
-        tmp = self->first;
-        self->first = Py_NewRef(first);
-        Py_DECREF(tmp);
+        Py_SETREF(self->first, Py_NewRef(first));
     }
     if (last) {
-        tmp = self->last;
-        self->last = Py_NewRef(last);
-        Py_DECREF(tmp);
+        Py_SETREF(self->last, Py_NewRef(last));
     }
     return 0;
 }
@@ -102,9 +98,7 @@ Custom_setfirst(CustomObject *self, PyObject *value, void *closure)
                         "The first attribute value must be a string");
         return -1;
     }
-    Py_INCREF(value);
-    Py_CLEAR(self->first);
-    self->first = value;
+    Py_XSETREF(self->first, Py_NewRef(value));
     return 0;
 }
 
@@ -126,9 +120,7 @@ Custom_setlast(CustomObject *self, PyObject *value, void *closure)
                         "The last attribute value must be a string");
         return -1;
     }
-    Py_INCREF(value);
-    Py_CLEAR(self->last);
-    self->last = value;
+    Py_XSETREF(self->last, Py_NewRef(value));
     return 0;
 }
 
diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c
index f1fd271f6d21..5fa583821889 100644
--- a/Modules/_collectionsmodule.c
+++ b/Modules/_collectionsmodule.c
@@ -1256,7 +1256,6 @@ deque_remove(dequeobject *deque, PyObject *value)
 static int
 deque_ass_item(dequeobject *deque, Py_ssize_t i, PyObject *v)
 {
-    PyObject *old_value;
     block *b;
     Py_ssize_t n, len=Py_SIZE(deque), halflen=(len+1)>>1, index=i;
 
@@ -1282,9 +1281,7 @@ deque_ass_item(dequeobject *deque, Py_ssize_t i, PyObject *v)
         while (--n >= 0)
             b = b->leftlink;
     }
-    old_value = b->data[i];
-    b->data[i] = Py_NewRef(v);
-    Py_DECREF(old_value);
+    Py_SETREF(b->data[i], Py_NewRef(v));
     return 0;
 }
 
diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c
index 20e8516fcde7..712abc3346fa 100644
--- a/Modules/_datetimemodule.c
+++ b/Modules/_datetimemodule.c
@@ -6247,13 +6247,10 @@ datetime_astimezone(PyDateTime_DateTime *self, PyObject *args, PyObject *kw)
     }
     else {
         /* Result is already aware - just replace tzinfo. */
-        temp = result->tzinfo;
-        result->tzinfo = Py_NewRef(PyDateTime_TimeZone_UTC);
-        Py_DECREF(temp);
+        Py_SETREF(result->tzinfo, Py_NewRef(PyDateTime_TimeZone_UTC));
     }
 
     /* Attach new tzinfo and let fromutc() do the rest. */
-    temp = result->tzinfo;
     if (tzinfo == Py_None) {
         tzinfo = local_timezone(result);
         if (tzinfo == NULL) {
@@ -6263,8 +6260,7 @@ datetime_astimezone(PyDateTime_DateTime *self, PyObject *args, PyObject *kw)
     }
     else
       Py_INCREF(tzinfo);
-    result->tzinfo = tzinfo;
-    Py_DECREF(temp);
+    Py_SETREF(result->tzinfo, tzinfo);
 
     temp = (PyObject *)result;
     result = (PyDateTime_DateTime *)
diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c
index 7b0977931f2a..3df93651654a 100644
--- a/Modules/_elementtree.c
+++ b/Modules/_elementtree.c
@@ -537,8 +537,7 @@ element_get_text(ElementObject* self)
             if (!tmp)
                 return NULL;
             self->text = tmp;
-            Py_DECREF(res);
-            res = tmp;
+            Py_SETREF(res, tmp);
         }
     }
 
@@ -559,8 +558,7 @@ element_get_tail(ElementObject* self)
             if (!tmp)
                 return NULL;
             self->tail = tmp;
-            Py_DECREF(res);
-            res = tmp;
+            Py_SETREF(res, tmp);
         }
     }
 
diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c
index 9b30f41ec699..4032ba79374f 100644
--- a/Modules/_functoolsmodule.c
+++ b/Modules/_functoolsmodule.c
@@ -1243,8 +1243,7 @@ lru_cache_clear_list(lru_list_elem *link)
 {
     while (link != NULL) {
         lru_list_elem *next = link->next;
-        Py_DECREF(link);
-        link = next;
+        Py_SETREF(link, next);
     }
 }
 
diff --git a/Modules/_io/stringio.c b/Modules/_io/stringio.c
index 5c3bf353680e..ae6c3125a2d9 100644
--- a/Modules/_io/stringio.c
+++ b/Modules/_io/stringio.c
@@ -193,8 +193,7 @@ write_str(stringio *self, PyObject *obj)
     if (self->writenl) {
         PyObject *translated = PyUnicode_Replace(
             decoded, &_Py_STR(newline), self->writenl, -1);
-        Py_DECREF(decoded);
-        decoded = translated;
+        Py_SETREF(decoded, translated);
     }
     if (decoded == NULL)
         return -1;
diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c
index 8b5d00fe4aaf..ff903e9341de 100644
--- a/Modules/_io/textio.c
+++ b/Modules/_io/textio.c
@@ -320,8 +320,7 @@ _PyIncrementalNewlineDecoder_decode(PyObject *myself,
         out = PyUnicode_DATA(modified);
         PyUnicode_WRITE(kind, out, 0, '\r');
         memcpy(out + kind, PyUnicode_DATA(output), kind * output_len);
-        Py_DECREF(output);
-        output = modified; /* output remains ready */
+        Py_SETREF(output, modified); /* output remains ready */
         self->pendingcr = 0;
         output_len++;
     }
@@ -336,8 +335,7 @@ _PyIncrementalNewlineDecoder_decode(PyObject *myself,
             PyObject *modified = PyUnicode_Substring(output, 0, output_len -1);
             if (modified == NULL)
                 goto error;
-            Py_DECREF(output);
-            output = modified;
+            Py_SETREF(output, modified);
             self->pendingcr = 1;
         }
     }
@@ -865,8 +863,7 @@ _textiowrapper_set_decoder(textio *self, PyObject *codec_info,
             self->decoder, self->readtranslate ? Py_True : Py_False, NULL);
         if (incrementalDecoder == NULL)
             return -1;
-        Py_CLEAR(self->decoder);
-        self->decoder = incrementalDecoder;
+        Py_XSETREF(self->decoder, incrementalDecoder);
     }
 
     return 0;
diff --git a/Modules/_json.c b/Modules/_json.c
index 06f232f7d7de..81431aa1041c 100644
--- a/Modules/_json.c
+++ b/Modules/_json.c
@@ -709,9 +709,7 @@ _parse_object_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ss
             if (memokey == NULL) {
                 goto bail;
             }
-            Py_INCREF(memokey);
-            Py_DECREF(key);
-            key = memokey;
+            Py_SETREF(key, Py_NewRef(memokey));
             idx = next_idx;
 
             /* skip whitespace between key and : delimiter, read :, skip whitespace */
diff --git a/Modules/_pickle.c b/Modules/_pickle.c
index db62094c5a5a..1e118e9cd10b 100644
--- a/Modules/_pickle.c
+++ b/Modules/_pickle.c
@@ -1829,8 +1829,7 @@ get_deep_attribute(PyObject *obj, PyObject *names, PyObject **pparent)
     n = PyList_GET_SIZE(names);
     for (i = 0; i < n; i++) {
         PyObject *name = PyList_GET_ITEM(names, i);
-        Py_XDECREF(parent);
-        parent = obj;
+        Py_XSETREF(parent, obj);
         (void)_PyObject_LookupAttr(parent, name, &obj);
         if (obj == NULL) {
             Py_DECREF(parent);
@@ -3717,9 +3716,7 @@ save_global(PicklerObject *self, PyObject *obj, PyObject *name)
     else {
   gen_global:
         if (parent == module) {
-            Py_INCREF(lastname);
-            Py_DECREF(global_name);
-            global_name = lastname;
+            Py_SETREF(global_name, Py_NewRef(lastname));
         }
         if (self->proto >= 4) {
             const char stack_global_op = STACK_GLOBAL;
diff --git a/Modules/_sqlite/cursor.c b/Modules/_sqlite/cursor.c
index 7844b6e26cdb..a4e22bb4a2b5 100644
--- a/Modules/_sqlite/cursor.c
+++ b/Modules/_sqlite/cursor.c
@@ -1123,8 +1123,7 @@ pysqlite_cursor_iternext(pysqlite_Cursor *self)
         PyObject *factory = self->row_factory;
         PyObject *args[] = { (PyObject *)self, row, };
         PyObject *new_row = PyObject_Vectorcall(factory, args, 2, NULL);
-        Py_DECREF(row);
-        row = new_row;
+        Py_SETREF(row, new_row);
     }
     return row;
 }
diff --git a/Modules/_testinternalcapi.c b/Modules/_testinternalcapi.c
index cec114cb5919..b14b8ac3c740 100644
--- a/Modules/_testinternalcapi.c
+++ b/Modules/_testinternalcapi.c
@@ -523,8 +523,7 @@ set_eval_frame_record(PyObject *self, PyObject *list)
         PyErr_SetString(PyExc_TypeError, "argument must be a list");
         return NULL;
     }
-    Py_CLEAR(record_list);
-    record_list = Py_NewRef(list);
+    Py_XSETREF(record_list, Py_NewRef(list));
     _PyInterpreterState_SetEvalFrameFunc(PyInterpreterState_Get(), record_eval);
     Py_RETURN_NONE;
 }
diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c
index a5d5428eaf50..6ff7d2bfced2 100644
--- a/Modules/_tkinter.c
+++ b/Modules/_tkinter.c
@@ -1105,8 +1105,7 @@ fromBignumObj(TkappObject *tkapp, Tcl_Obj *value)
     PyMem_Free(bytes);
     if (res != NULL && bigValue.sign == MP_NEG) {
         PyObject *res2 = PyNumber_Negative(res);
-        Py_DECREF(res);
-        res = res2;
+        Py_SETREF(res, res2);
     }
     mp_clear(&bigValue);
     return res;
diff --git a/Modules/_zoneinfo.c b/Modules/_zoneinfo.c
index 34f5abd343ec..c0fef13ba17d 100644
--- a/Modules/_zoneinfo.c
+++ b/Modules/_zoneinfo.c
@@ -1074,8 +1074,7 @@ load_data(PyZoneInfo_ZoneInfo *self, PyObject *file_obj)
         // that the dstoff is set correctly in that case.
         if (PyObject_IsTrue(tti->dstoff)) {
             _ttinfo *tti_after = &(self->tzrule_after.std);
-            Py_DECREF(tti_after->dstoff);
-            tti_after->dstoff = Py_NewRef(tti->dstoff);
+            Py_SETREF(tti_after->dstoff, Py_NewRef(tti->dstoff));
         }
     }
 
diff --git a/Modules/audioop.c b/Modules/audioop.c
index 6d484e8bba3e..9325f82f9a17 100644
--- a/Modules/audioop.c
+++ b/Modules/audioop.c
@@ -1471,8 +1471,7 @@ audioop_ratecv_impl(PyObject *module, Py_buffer *fragment, int width,
                 len = (Py_ssize_t)(ncp - PyBytes_AsString(str));
                 rv = PyBytes_FromStringAndSize
                     (PyBytes_AsString(str), len);
-                Py_DECREF(str);
-                str = rv;
+                Py_SETREF(str, rv);
                 if (str == NULL)
                     goto exit;
                 rv = Py_BuildValue("(O(iO))", str, d, samps);
diff --git a/Modules/cjkcodecs/multibytecodec.c b/Modules/cjkcodecs/multibytecodec.c
index 6d67fce1da03..8b6232695d4c 100644
--- a/Modules/cjkcodecs/multibytecodec.c
+++ b/Modules/cjkcodecs/multibytecodec.c
@@ -980,8 +980,7 @@ _multibytecodec_MultibyteIncrementalEncoder_setstate_impl(MultibyteIncrementalEn
         goto errorexit;
     }
 
-    Py_CLEAR(self->pending);
-    self->pending = pending;
+    Py_XSETREF(self->pending, pending);
     memcpy(self->state.c, statebytes+1+statebytes[0],
            sizeof(self->state.c));
 
@@ -1438,8 +1437,7 @@ mbstreamreader_iread(MultibyteStreamReaderObject *self,
             memcpy(ctrdata + self->pendingsize,
                     PyBytes_AS_STRING(cres),
                     PyBytes_GET_SIZE(cres));
-            Py_DECREF(cres);
-            cres = ctr;
+            Py_SETREF(cres, ctr);
             self->pendingsize = 0;
         }
 
diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c
index 65d014250522..4b0a4d88c435 100644
--- a/Modules/itertoolsmodule.c
+++ b/Modules/itertoolsmodule.c
@@ -834,8 +834,7 @@ teedataobject_safe_decref(PyObject *obj)
            Py_REFCNT(obj) == 1) {
         PyObject *nextlink = ((teedataobject *)obj)->nextlink;
         ((teedataobject *)obj)->nextlink = NULL;
-        Py_DECREF(obj);
-        obj = nextlink;
+        Py_SETREF(obj, nextlink);
     }
     Py_XDECREF(obj);
 }
diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c
index 16a2f45c8b84..83eb338be9b8 100644
--- a/Modules/mathmodule.c
+++ b/Modules/mathmodule.c
@@ -2069,8 +2069,7 @@ factorial_odd_part(unsigned long n)
         Py_DECREF(partial);
         if (tmp == NULL)
             goto error;
-        Py_DECREF(inner);
-        inner = tmp;
+        Py_SETREF(inner, tmp);
         /* Now inner is the product of all odd integers j in the range (0,
            n/2**i], giving the inner product in the formula above. */
 
@@ -2078,8 +2077,7 @@ factorial_odd_part(unsigned long n)
         tmp = PyNumber_Multiply(outer, inner);
         if (tmp == NULL)
             goto error;
-        Py_DECREF(outer);
-        outer = tmp;
+        Py_SETREF(outer, tmp);
     }
     Py_DECREF(inner);
     return outer;
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
index 6d65ae97c9e3..98fc264aff6b 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -1202,8 +1202,7 @@ path_converter(PyObject *o, void *p)
         }
 
         /* still owns a reference to the original object */
-        Py_DECREF(o);
-        o = res;
+        Py_SETREF(o, res);
     }
 
     if (is_unicode) {



More information about the Python-checkins mailing list