Issue #20440: Massive replacing unsafe attribute setting code with special
macro Py_SETREF.
diff --git a/Modules/_csv.c b/Modules/_csv.c
index af901e2..fe85069 100644
--- a/Modules/_csv.c
+++ b/Modules/_csv.c
@@ -276,9 +276,8 @@
         else {
             if (PyUnicode_READY(src) == -1)
                 return -1;
-            Py_XDECREF(*target);
             Py_INCREF(src);
-            *target = src;
+            Py_SETREF(*target, src);
         }
     }
     return 0;
@@ -784,8 +783,7 @@
 static int
 parse_reset(ReaderObj *self)
 {
-    Py_XDECREF(self->fields);
-    self->fields = PyList_New(0);
+    Py_SETREF(self->fields, PyList_New(0));
     if (self->fields == NULL)
         return -1;
     self->field_len = 0;
diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c
index 00eb700..01fccca 100644
--- a/Modules/_ctypes/_ctypes.c
+++ b/Modules/_ctypes/_ctypes.c
@@ -391,8 +391,7 @@
         Py_DECREF((PyObject *)dict);
         return NULL;
     }
-    Py_DECREF(result->tp_dict);
-    result->tp_dict = (PyObject *)dict;
+    Py_SETREF(result->tp_dict, (PyObject *)dict);
     dict->format = _ctypes_alloc_format_string(NULL, "B");
     if (dict->format == NULL) {
         Py_DECREF(result);
@@ -871,8 +870,7 @@
         return -1;
     }
     Py_INCREF(proto);
-    Py_XDECREF(stgdict->proto);
-    stgdict->proto = proto;
+    Py_SETREF(stgdict->proto, proto);
     return 0;
 }
 
@@ -962,8 +960,7 @@
         Py_DECREF((PyObject *)stgdict);
         return NULL;
     }
-    Py_DECREF(result->tp_dict);
-    result->tp_dict = (PyObject *)stgdict;
+    Py_SETREF(result->tp_dict, (PyObject *)stgdict);
 
     return (PyObject *)result;
 }
@@ -1406,8 +1403,7 @@
     /* replace the class dict by our updated spam dict */
     if (-1 == PyDict_Update((PyObject *)stgdict, result->tp_dict))
         goto error;
-    Py_DECREF(result->tp_dict);
-    result->tp_dict = (PyObject *)stgdict;  /* steal the reference */
+    Py_SETREF(result->tp_dict, (PyObject *)stgdict);  /* steal the reference */
     stgdict = NULL;
 
     /* Special case for character arrays.
@@ -1820,8 +1816,7 @@
         Py_DECREF((PyObject *)stgdict);
         return NULL;
     }
-    Py_DECREF(result->tp_dict);
-    result->tp_dict = (PyObject *)stgdict;
+    Py_SETREF(result->tp_dict, (PyObject *)stgdict);
 
     return (PyObject *)result;
 }
@@ -1949,8 +1944,7 @@
         Py_DECREF((PyObject *)stgdict);
         return NULL;
     }
-    Py_DECREF(result->tp_dict);
-    result->tp_dict = (PyObject *)stgdict;
+    Py_SETREF(result->tp_dict, (PyObject *)stgdict);
 
     /* Install from_param class methods in ctypes base classes.
        Overrides the PyCSimpleType_from_param generic method.
@@ -2313,8 +2307,7 @@
         Py_DECREF((PyObject *)stgdict);
         return NULL;
     }
-    Py_DECREF(result->tp_dict);
-    result->tp_dict = (PyObject *)stgdict;
+    Py_SETREF(result->tp_dict, (PyObject *)stgdict);
 
     if (-1 == make_funcptrtype_dict(stgdict)) {
         Py_DECREF(result);
@@ -2458,8 +2451,7 @@
         return -1;
     }
     if (ob->b_objects == NULL || !PyDict_CheckExact(ob->b_objects)) {
-        Py_XDECREF(ob->b_objects);
-        ob->b_objects = keep; /* refcount consumed */
+        Py_SETREF(ob->b_objects, keep); /* refcount consumed */
         return 0;
     }
     key = unique_key(target, index);
@@ -2962,9 +2954,8 @@
                         "the errcheck attribute must be callable");
         return -1;
     }
-    Py_XDECREF(self->errcheck);
     Py_XINCREF(ob);
-    self->errcheck = ob;
+    Py_SETREF(self->errcheck, ob);
     return 0;
 }
 
@@ -2993,9 +2984,8 @@
         return -1;
     }
     Py_XDECREF(self->checker);
-    Py_XDECREF(self->restype);
     Py_INCREF(ob);
-    self->restype = ob;
+    Py_SETREF(self->restype, ob);
     self->checker = PyObject_GetAttrString(ob, "_check_retval_");
     if (self->checker == NULL)
         PyErr_Clear();
@@ -3033,11 +3023,9 @@
         converters = converters_from_argtypes(ob);
         if (!converters)
             return -1;
-        Py_XDECREF(self->converters);
-        self->converters = converters;
-        Py_XDECREF(self->argtypes);
+        Py_SETREF(self->converters, converters);
         Py_INCREF(ob);
-        self->argtypes = ob;
+        Py_SETREF(self->argtypes, ob);
     }
     return 0;
 }
@@ -5164,9 +5152,8 @@
         return -1;
 
     bself = (PyBaseExceptionObject *)self;
-    Py_DECREF(bself->args);
-    bself->args = args;
-    Py_INCREF(bself->args);
+    Py_INCREF(args);
+    Py_SETREF(bself->args, args);
 
     return 0;
 }
diff --git a/Modules/_curses_panel.c b/Modules/_curses_panel.c
index 87b9c05..759b731 100644
--- a/Modules/_curses_panel.c
+++ b/Modules/_curses_panel.c
@@ -312,9 +312,8 @@
         PyErr_SetString(_curses_panelstate_global->PyCursesError, "replace_panel() returned ERR");
         return NULL;
     }
-    Py_DECREF(po->wo);
-    po->wo = temp;
-    Py_INCREF(po->wo);
+    Py_INCREF(temp);
+    Py_SETREF(po->wo, temp);
     Py_INCREF(Py_None);
     return Py_None;
 }
diff --git a/Modules/_io/bytesio.c b/Modules/_io/bytesio.c
index eef3b3d..99e71bc 100644
--- a/Modules/_io/bytesio.c
+++ b/Modules/_io/bytesio.c
@@ -969,8 +969,7 @@
     if (initvalue && initvalue != Py_None) {
         if (PyBytes_CheckExact(initvalue)) {
             Py_INCREF(initvalue);
-            Py_XDECREF(self->buf);
-            self->buf = initvalue;
+            Py_SETREF(self->buf, initvalue);
             self->string_size = PyBytes_GET_SIZE(initvalue);
         }
         else {
diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c
index a08ebfe..7018f9f 100644
--- a/Modules/_sqlite/connection.c
+++ b/Modules/_sqlite/connection.c
@@ -204,8 +204,8 @@
         node = node->next;
     }
 
-    Py_DECREF(self->statement_cache);
-    self->statement_cache = (pysqlite_Cache*)PyObject_CallFunction((PyObject*)&pysqlite_CacheType, "O", self);
+    Py_SETREF(self->statement_cache,
+              (pysqlite_Cache *)PyObject_CallFunction((PyObject *)&pysqlite_CacheType, "O", self));
     Py_DECREF(self);
     self->statement_cache->decref_factory = 0;
 }
@@ -318,9 +318,8 @@
     _pysqlite_drop_unused_cursor_references(self);
 
     if (cursor && self->row_factory != Py_None) {
-        Py_XDECREF(((pysqlite_Cursor*)cursor)->row_factory);
         Py_INCREF(self->row_factory);
-        ((pysqlite_Cursor*)cursor)->row_factory = self->row_factory;
+        Py_SETREF(((pysqlite_Cursor *)cursor)->row_factory, self->row_factory);
     }
 
     return cursor;
@@ -795,8 +794,7 @@
         }
     }
 
-    Py_DECREF(self->statements);
-    self->statements = new_list;
+    Py_SETREF(self->statements, new_list);
 }
 
 static void _pysqlite_drop_unused_cursor_references(pysqlite_Connection* self)
@@ -827,8 +825,7 @@
         }
     }
 
-    Py_DECREF(self->cursors);
-    self->cursors = new_list;
+    Py_SETREF(self->cursors, new_list);
 }
 
 PyObject* pysqlite_connection_create_function(pysqlite_Connection* self, PyObject* args, PyObject* kwargs)
diff --git a/Modules/_sqlite/cursor.c b/Modules/_sqlite/cursor.c
index c1599c0..d909738 100644
--- a/Modules/_sqlite/cursor.c
+++ b/Modules/_sqlite/cursor.c
@@ -170,8 +170,7 @@
         return 0;
     }
 
-    Py_XDECREF(self->row_cast_map);
-    self->row_cast_map = PyList_New(0);
+    Py_SETREF(self->row_cast_map, PyList_New(0));
 
     for (i = 0; i < sqlite3_column_count(self->statement->st); i++) {
         converter = NULL;
@@ -510,9 +509,8 @@
         goto error;
 
     /* reset description and rowcount */
-    Py_DECREF(self->description);
     Py_INCREF(Py_None);
-    self->description = Py_None;
+    Py_SETREF(self->description, Py_None);
     self->rowcount = -1L;
 
     func_args = PyTuple_New(1);
@@ -537,8 +535,8 @@
     }
 
     if (self->statement->in_use) {
-        Py_DECREF(self->statement);
-        self->statement = PyObject_New(pysqlite_Statement, &pysqlite_StatementType);
+        Py_SETREF(self->statement,
+                  PyObject_New(pysqlite_Statement, &pysqlite_StatementType));
         if (!self->statement) {
             goto error;
         }
@@ -654,8 +652,7 @@
                 numcols = sqlite3_column_count(self->statement->st);
                 Py_END_ALLOW_THREADS
 
-                Py_DECREF(self->description);
-                self->description = PyTuple_New(numcols);
+                Py_SETREF(self->description, PyTuple_New(numcols));
                 if (!self->description) {
                     goto error;
                 }
diff --git a/Modules/_sre.c b/Modules/_sre.c
index 957ccbc..150229d 100644
--- a/Modules/_sre.c
+++ b/Modules/_sre.c
@@ -756,8 +756,7 @@
     if (!copy)
         return 0;
 
-    Py_DECREF(*object);
-    *object = copy;
+    Py_SETREF(*object, copy);
 
     return 1; /* success */
 }
diff --git a/Modules/_ssl.c b/Modules/_ssl.c
index 67402fe..8818d26 100644
--- a/Modules/_ssl.c
+++ b/Modules/_ssl.c
@@ -1589,8 +1589,7 @@
         return -1;
 #else
         Py_INCREF(value);
-        Py_DECREF(self->ctx);
-        self->ctx = (PySSLContext *) value;
+        Py_SETREF(self->ctx, (PySSLContext *)value);
         SSL_set_SSL_CTX(self->ssl, self->ctx->ctx);
 #endif
     } else {
@@ -1647,8 +1646,7 @@
 static int
 PySSL_set_owner(PySSLSocket *self, PyObject *value, void *c)
 {
-    Py_XDECREF(self->owner);
-    self->owner = PyWeakref_NewRef(value, NULL);
+    Py_SETREF(self->owner, PyWeakref_NewRef(value, NULL));
     if (self->owner == NULL)
         return -1;
     return 0;
diff --git a/Modules/faulthandler.c b/Modules/faulthandler.c
index 530ddc7..1ed22bf 100644
--- a/Modules/faulthandler.c
+++ b/Modules/faulthandler.c
@@ -380,9 +380,8 @@
     if (tstate == NULL)
         return NULL;
 
-    Py_XDECREF(fatal_error.file);
     Py_XINCREF(file);
-    fatal_error.file = file;
+    Py_SETREF(fatal_error.file, file);
     fatal_error.fd = fd;
     fatal_error.all_threads = all_threads;
     fatal_error.interp = tstate->interp;
@@ -599,9 +598,8 @@
     /* Cancel previous thread, if running */
     cancel_dump_traceback_later();
 
-    Py_XDECREF(thread.file);
     Py_XINCREF(file);
-    thread.file = file;
+    Py_SETREF(thread.file, file);
     thread.fd = fd;
     thread.timeout_us = timeout_us;
     thread.repeat = repeat;
@@ -778,9 +776,8 @@
         user->previous = previous;
     }
 
-    Py_XDECREF(user->file);
     Py_XINCREF(file);
-    user->file = file;
+    Py_SETREF(user->file, file);
     user->fd = fd;
     user->all_threads = all_threads;
     user->chain = chain;
diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c
index 9c210ea..1c9a173 100644
--- a/Modules/itertoolsmodule.c
+++ b/Modules/itertoolsmodule.c
@@ -636,8 +636,7 @@
         link = teedataobject_jumplink(to->dataobj);
         if (link == NULL)
             return NULL;
-        Py_DECREF(to->dataobj);
-        to->dataobj = (teedataobject *)link;
+        Py_SETREF(to->dataobj, (teedataobject *)link);
         to->index = 0;
     }
     value = teedataobject_getitem(to->dataobj, to->index);
diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c
index 70f3052..da454de 100644
--- a/Modules/signalmodule.c
+++ b/Modules/signalmodule.c
@@ -1266,8 +1266,7 @@
     if (Handlers[SIGINT].func == DefaultHandler) {
         /* Install default int handler */
         Py_INCREF(IntHandler);
-        Py_DECREF(Handlers[SIGINT].func);
-        Handlers[SIGINT].func = IntHandler;
+        Py_SETREF(Handlers[SIGINT].func, IntHandler);
         old_siginthandler = PyOS_setsig(SIGINT, signal_handler);
     }
 
diff --git a/Modules/zipimport.c b/Modules/zipimport.c
index 06abb31..7220faf 100644
--- a/Modules/zipimport.c
+++ b/Modules/zipimport.c
@@ -155,8 +155,7 @@
             tmp = PyUnicode_FromFormat("%U%c", self->prefix, SEP);
             if (tmp == NULL)
                 goto error;
-            Py_DECREF(self->prefix);
-            self->prefix = tmp;
+            Py_SETREF(self->prefix, tmp);
         }
     }
     else
diff --git a/Modules/zlibmodule.c b/Modules/zlibmodule.c
index 37307be..a15fdb2 100644
--- a/Modules/zlibmodule.c
+++ b/Modules/zlibmodule.c
@@ -667,8 +667,7 @@
                       PyBytes_AS_STRING(self->unused_data), old_size);
             Py_MEMCPY(PyBytes_AS_STRING(new_data) + old_size,
                       self->zst.next_in, self->zst.avail_in);
-            Py_DECREF(self->unused_data);
-            self->unused_data = new_data;
+            Py_SETREF(self->unused_data, new_data);
             self->zst.avail_in = 0;
         }
     }
@@ -680,8 +679,7 @@
                 (char *)self->zst.next_in, self->zst.avail_in);
         if (new_data == NULL)
             return -1;
-        Py_DECREF(self->unconsumed_tail);
-        self->unconsumed_tail = new_data;
+        Py_SETREF(self->unconsumed_tail, new_data);
     }
     return 0;
 }