Issue #20440: Massive replacing unsafe attribute setting code with special
macro Py_SETREF.
diff --git a/Modules/_bsddb.c b/Modules/_bsddb.c
index 408efc3..9cebaf4 100644
--- a/Modules/_bsddb.c
+++ b/Modules/_bsddb.c
@@ -1607,9 +1607,8 @@
     }
 
     /* Save a reference to the callback in the secondary DB. */
-    Py_XDECREF(secondaryDB->associateCallback);
     Py_XINCREF(callback);
-    secondaryDB->associateCallback = callback;
+    Py_SETREF(secondaryDB->associateCallback, callback);
     secondaryDB->primaryDBType = _DB_get_type(self);
 
     /* PyEval_InitThreads is called here due to a quirk in python 1.5
@@ -2498,9 +2497,8 @@
 DB_set_private(DBObject* self, PyObject* private_obj)
 {
     /* We can set the private field even if db is closed */
-    Py_DECREF(self->private_obj);
     Py_INCREF(private_obj);
-    self->private_obj = private_obj;
+    Py_SETREF(self->private_obj, private_obj);
     RETURN_NONE();
 }
 
@@ -6998,9 +6996,8 @@
 DBEnv_set_private(DBEnvObject* self, PyObject* private_obj)
 {
     /* We can set the private field even if dbenv is closed */
-    Py_DECREF(self->private_obj);
     Py_INCREF(private_obj);
-    self->private_obj = private_obj;
+    Py_SETREF(self->private_obj, private_obj);
     RETURN_NONE();
 }
 
@@ -7253,9 +7250,8 @@
             return NULL;
     }
 
-    Py_XDECREF(self->event_notifyCallback);
     Py_INCREF(notifyFunc);
-    self->event_notifyCallback = notifyFunc;
+    Py_SETREF(self->event_notifyCallback, notifyFunc);
 
     /* This is to workaround a problem with un-initialized threads (see
        comment in DB_associate) */
@@ -7413,9 +7409,8 @@
     MYDB_END_ALLOW_THREADS;
     RETURN_IF_ERR();
 
-    Py_DECREF(self->rep_transport);
     Py_INCREF(rep_transport);
-    self->rep_transport = rep_transport;
+    Py_SETREF(self->rep_transport, rep_transport);
     RETURN_NONE();
 }
 
diff --git a/Modules/_csv.c b/Modules/_csv.c
index 884e051..9271413 100644
--- a/Modules/_csv.c
+++ b/Modules/_csv.c
@@ -276,9 +276,8 @@
             return -1;
         }
         else {
-            Py_XDECREF(*target);
             Py_INCREF(src);
-            *target = src;
+            Py_SETREF(*target, src);
         }
     }
     return 0;
@@ -770,8 +769,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 96ffa9d..8e7e6e4 100644
--- a/Modules/_ctypes/_ctypes.c
+++ b/Modules/_ctypes/_ctypes.c
@@ -424,8 +424,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);
@@ -903,8 +902,7 @@
         return -1;
     }
     Py_INCREF(proto);
-    Py_XDECREF(stgdict->proto);
-    stgdict->proto = proto;
+    Py_SETREF(stgdict->proto, proto);
     return 0;
 }
 
@@ -994,8 +992,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;
 }
@@ -1460,8 +1457,7 @@
         Py_DECREF((PyObject *)stgdict);
         return NULL;
     }
-    Py_DECREF(result->tp_dict);
-    result->tp_dict = (PyObject *)stgdict;
+    Py_SETREF(result->tp_dict, (PyObject *)stgdict);
 
     /* Special case for character arrays.
        A permanent annoyance: char arrays are also strings!
@@ -1884,8 +1880,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;
 }
@@ -2393,8 +2388,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);
@@ -2536,8 +2530,7 @@
     }
     ob = PyCData_GetContainer(target);
     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);
@@ -3059,9 +3052,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;
 }
 
@@ -3090,9 +3082,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();
@@ -3130,11 +3121,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;
 }
diff --git a/Modules/_curses_panel.c b/Modules/_curses_panel.c
index bdd5cf0..d61281e 100644
--- a/Modules/_curses_panel.c
+++ b/Modules/_curses_panel.c
@@ -283,9 +283,8 @@
         PyErr_SetString(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/_json.c b/Modules/_json.c
index 5dac038..fede6b1 100644
--- a/Modules/_json.c
+++ b/Modules/_json.c
@@ -1717,8 +1717,7 @@
     }
     else if (PyUnicode_Check(s->encoding)) {
         PyObject *tmp = PyUnicode_AsEncodedString(s->encoding, NULL, NULL);
-        Py_DECREF(s->encoding);
-        s->encoding = tmp;
+        Py_SETREF(s->encoding, tmp);
     }
     if (s->encoding == NULL)
         goto bail;
diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c
index 79a7a00..c67d10c 100644
--- a/Modules/_sqlite/connection.c
+++ b/Modules/_sqlite/connection.c
@@ -228,8 +228,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;
 }
@@ -346,9 +346,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;
@@ -816,8 +815,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)
@@ -848,8 +846,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 3b84484..81db988 100644
--- a/Modules/_sqlite/cursor.c
+++ b/Modules/_sqlite/cursor.c
@@ -172,8 +172,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;
@@ -544,9 +543,8 @@
     }
 
     /* 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);
@@ -571,8 +569,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;
         }
@@ -683,8 +681,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 8ef8c2c..829fb6b 100644
--- a/Modules/_sre.c
+++ b/Modules/_sre.c
@@ -2054,8 +2054,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 89f2aaa..9116d9f 100644
--- a/Modules/_ssl.c
+++ b/Modules/_ssl.c
@@ -1467,8 +1467,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 {
diff --git a/Modules/bz2module.c b/Modules/bz2module.c
index ae749ee..fe417c5 100644
--- a/Modules/bz2module.c
+++ b/Modules/bz2module.c
@@ -1953,9 +1953,8 @@
             self->running = 0;
             input_left += bzs->avail_in;
             if (input_left != 0) {
-                Py_DECREF(self->unused_data);
-                self->unused_data =
-                    PyString_FromStringAndSize(bzs->next_in, input_left);
+                Py_SETREF(self->unused_data,
+                          PyString_FromStringAndSize(bzs->next_in, input_left));
                 if (self->unused_data == NULL)
                     goto error;
             }
diff --git a/Modules/cPickle.c b/Modules/cPickle.c
index ce9283a..a00108e 100644
--- a/Modules/cPickle.c
+++ b/Modules/cPickle.c
@@ -689,8 +689,7 @@
     }
     if (! str) return -1;
 
-    Py_XDECREF(self->last_string);
-    self->last_string = str;
+    Py_SETREF(self->last_string, str);
 
     if (! (*s = PyString_AsString(str))) return -1;
 
@@ -716,8 +715,7 @@
     if ((str_size = PyString_Size(str)) < 0)
         return -1;
 
-    Py_XDECREF(self->last_string);
-    self->last_string = str;
+    Py_SETREF(self->last_string, str);
 
     if (! (*s = PyString_AsString(str)))
         return -1;
@@ -3228,9 +3226,8 @@
                         "attribute deletion is not supported");
         return -1;
     }
-    Py_XDECREF(p->pers_func);
     Py_INCREF(v);
-    p->pers_func = v;
+    Py_SETREF(p->pers_func, v);
     return 0;
 }
 
@@ -3242,9 +3239,8 @@
                         "attribute deletion is not supported");
         return -1;
     }
-    Py_XDECREF(p->inst_pers_func);
     Py_INCREF(v);
-    p->inst_pers_func = v;
+    Py_SETREF(p->inst_pers_func, v);
     return 0;
 }
 
@@ -3270,9 +3266,8 @@
         PyErr_SetString(PyExc_TypeError, "memo must be a dictionary");
         return -1;
     }
-    Py_XDECREF(p->memo);
     Py_INCREF(v);
-    p->memo = v;
+    Py_SETREF(p->memo, v);
     return 0;
 }
 
@@ -5667,16 +5662,14 @@
 {
 
     if (!strcmp(name, "persistent_load")) {
-        Py_XDECREF(self->pers_func);
-        self->pers_func = value;
         Py_XINCREF(value);
+        Py_SETREF(self->pers_func, value);
         return 0;
     }
 
     if (!strcmp(name, "find_global")) {
-        Py_XDECREF(self->find_class);
-        self->find_class = value;
         Py_XINCREF(value);
+        Py_SETREF(self->find_class, value);
         return 0;
     }
 
@@ -5692,9 +5685,8 @@
                             "memo must be a dictionary");
             return -1;
         }
-        Py_XDECREF(self->memo);
-        self->memo = value;
         Py_INCREF(value);
+        Py_SETREF(self->memo, value);
         return 0;
     }
 
diff --git a/Modules/cdmodule.c b/Modules/cdmodule.c
index 9ee9b0b..9ef8727 100644
--- a/Modules/cdmodule.c
+++ b/Modules/cdmodule.c
@@ -628,12 +628,10 @@
     CDsetcallback(self->ob_cdparser, (CDDATATYPES) type, CD_callback,
                   (void *) self);
 #endif
-    Py_XDECREF(self->ob_cdcallbacks[type].ob_cdcallback);
     Py_INCREF(func);
-    self->ob_cdcallbacks[type].ob_cdcallback = func;
-    Py_XDECREF(self->ob_cdcallbacks[type].ob_cdcallbackarg);
+    Py_SETREF(self->ob_cdcallbacks[type].ob_cdcallback, func);
     Py_INCREF(funcarg);
-    self->ob_cdcallbacks[type].ob_cdcallbackarg = funcarg;
+    Py_SETREF(self->ob_cdcallbacks[type].ob_cdcallbackarg, funcarg);
 
 /*
     if (type == cd_audio) {
diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c
index c3cf1c0..9b9e1da 100644
--- a/Modules/itertoolsmodule.c
+++ b/Modules/itertoolsmodule.c
@@ -494,8 +494,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 184b3a9..c0e17f3 100644
--- a/Modules/signalmodule.c
+++ b/Modules/signalmodule.c
@@ -621,8 +621,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/zlibmodule.c b/Modules/zlibmodule.c
index 519af94..b31d521 100644
--- a/Modules/zlibmodule.c
+++ b/Modules/zlibmodule.c
@@ -491,8 +491,7 @@
                       PyString_AS_STRING(self->unused_data), old_size);
             Py_MEMCPY(PyString_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;
         }
     }
@@ -504,8 +503,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;
 }