Issue #20440: Massive replacing unsafe attribute setting code with special
macro Py_SETREF.
diff --git a/Objects/descrobject.c b/Objects/descrobject.c
index 886a451..c7271ef 100644
--- a/Objects/descrobject.c
+++ b/Objects/descrobject.c
@@ -1332,8 +1332,7 @@
         PyObject *get_doc = PyObject_GetAttrString(get, "__doc__");
         if (get_doc) {
             if (Py_TYPE(self) == &PyProperty_Type) {
-                Py_XDECREF(prop->prop_doc);
-                prop->prop_doc = get_doc;
+                Py_SETREF(prop->prop_doc, get_doc);
             }
             else {
                 /* If this is a property subclass, put __doc__
diff --git a/Objects/exceptions.c b/Objects/exceptions.c
index e165528..9d61a9a 100644
--- a/Objects/exceptions.c
+++ b/Objects/exceptions.c
@@ -58,9 +58,8 @@
     if (!_PyArg_NoKeywords(Py_TYPE(self)->tp_name, kwds))
         return -1;
 
-    Py_DECREF(self->args);
-    self->args = args;
-    Py_INCREF(self->args);
+    Py_INCREF(args);
+    Py_SETREF(self->args, args);
 
     if (PyTuple_GET_SIZE(self->args) == 1) {
         Py_CLEAR(self->message);
@@ -627,8 +626,7 @@
         if (!subslice)
             return -1;
 
-        Py_DECREF(self->args);  /* replacing args */
-        self->args = subslice;
+        Py_SETREF(self->args, subslice);
     }
     return 0;
 }
diff --git a/Objects/fileobject.c b/Objects/fileobject.c
index 55e074b..9ae068c 100644
--- a/Objects/fileobject.c
+++ b/Objects/fileobject.c
@@ -574,10 +574,8 @@
         oerrors = Py_None;
         Py_INCREF(Py_None);
     }
-    Py_DECREF(file->f_encoding);
-    file->f_encoding = str;
-    Py_DECREF(file->f_errors);
-    file->f_errors = oerrors;
+    Py_SETREF(file->f_encoding, str);
+    Py_SETREF(file->f_errors, oerrors);
     return 1;
 }
 
diff --git a/Objects/frameobject.c b/Objects/frameobject.c
index f9e4a0e..6ca390b 100644
--- a/Objects/frameobject.c
+++ b/Objects/frameobject.c
@@ -859,8 +859,7 @@
             }
         } else if (values[j] != value) {
             Py_XINCREF(value);
-            Py_XDECREF(values[j]);
-            values[j] = value;
+            Py_SETREF(values[j], value);
         }
         Py_XDECREF(value);
     }
diff --git a/Objects/funcobject.c b/Objects/funcobject.c
index 51b6c9d..da54069 100644
--- a/Objects/funcobject.c
+++ b/Objects/funcobject.c
@@ -116,8 +116,7 @@
         PyErr_SetString(PyExc_SystemError, "non-tuple default args");
         return -1;
     }
-    Py_XDECREF(((PyFunctionObject *) op) -> func_defaults);
-    ((PyFunctionObject *) op) -> func_defaults = defaults;
+    Py_SETREF(((PyFunctionObject *)op)->func_defaults, defaults);
     return 0;
 }
 
@@ -149,8 +148,7 @@
                      closure->ob_type->tp_name);
         return -1;
     }
-    Py_XDECREF(((PyFunctionObject *) op) -> func_closure);
-    ((PyFunctionObject *) op) -> func_closure = closure;
+    Py_SETREF(((PyFunctionObject *)op)->func_closure, closure);
     return 0;
 }
 
@@ -430,8 +428,7 @@
 
     if (name != Py_None) {
         Py_INCREF(name);
-        Py_DECREF(newfunc->func_name);
-        newfunc->func_name = name;
+        Py_SETREF(newfunc->func_name, name);
     }
     if (defaults != Py_None) {
         Py_INCREF(defaults);
diff --git a/Objects/stringobject.c b/Objects/stringobject.c
index 14c5177..f585ffc 100644
--- a/Objects/stringobject.c
+++ b/Objects/stringobject.c
@@ -3865,8 +3865,7 @@
         return;
     }
     v = string_concat((PyStringObject *) *pv, w);
-    Py_DECREF(*pv);
-    *pv = v;
+    Py_SETREF(*pv, v);
 }
 
 void
@@ -4751,8 +4750,7 @@
     t = PyDict_GetItem(interned, (PyObject *)s);
     if (t) {
         Py_INCREF(t);
-        Py_DECREF(*p);
-        *p = t;
+        Py_SETREF(*p, t);
         return;
     }
 
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 38548fd..91709bc 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -166,9 +166,8 @@
            are borrowed reference */
         for (i = 0; i < (1 << MCACHE_SIZE_EXP); i++) {
             method_cache[i].value = NULL;
-            Py_XDECREF(method_cache[i].name);
-            method_cache[i].name = Py_None;
             Py_INCREF(Py_None);
+            Py_SETREF(method_cache[i].name, Py_None);
         }
         /* mark all version tags as invalid */
         PyType_Modified(&PyBaseObject_Type);
@@ -2527,8 +2526,7 @@
         method_cache[h].version = type->tp_version_tag;
         method_cache[h].value = res;  /* borrowed */
         Py_INCREF(name);
-        Py_DECREF(method_cache[h].name);
-        method_cache[h].name = name;
+        Py_SETREF(method_cache[h].name, name);
     }
     return res;
 }
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
index 2925651..9f503bd 100644
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -436,8 +436,7 @@
             return -1;
         Py_UNICODE_COPY(w->str, v->str,
                         length < v->length ? length : v->length);
-        Py_DECREF(*unicode);
-        *unicode = w;
+        Py_SETREF(*unicode, w);
         return 0;
     }