Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 5951f23

Browse files
Issue python#20440: Massive replacing unsafe attribute setting code with special
macro Py_SETREF.
1 parent 6ed42ea commit 5951f23

28 files changed

Lines changed: 94 additions & 128 deletions

Include/object.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -824,6 +824,29 @@ PyAPI_FUNC(void) _Py_AddToAllObjects(PyObject *, int force);
824824
#define Py_XINCREF(op) do { if ((op) == NULL) ; else Py_INCREF(op); } while (0)
825825
#define Py_XDECREF(op) do { if ((op) == NULL) ; else Py_DECREF(op); } while (0)
826826

827+
/* Safely decref `op` and set `op` to `op2`.
828+
*
829+
* As in case of Py_CLEAR "the obvious" code can be deadly:
830+
*
831+
* Py_XDECREF(op);
832+
* op = op2;
833+
*
834+
* The safe way is:
835+
*
836+
* Py_SETREF(op, op2);
837+
*
838+
* That arranges to set `op` to `op2` _before_ decref'ing, so that any code
839+
* triggered as a side-effect of `op` getting torn down no longer believes
840+
* `op` points to a valid object.
841+
*/
842+
843+
#define Py_SETREF(op, op2) \
844+
do { \
845+
PyObject *_py_tmp = (PyObject *)(op); \
846+
(op) = (op2); \
847+
Py_XDECREF(_py_tmp); \
848+
} while (0)
849+
827850
/*
828851
These are provided as conveniences to Python runtime embedders, so that
829852
they can have object code that is not dependent on Python compilation flags.

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ What's New in Python 2.7.12?
1010
Core and Builtins
1111
-----------------
1212

13+
- Issue #20440: Massive replacing unsafe attribute setting code with special
14+
macro Py_SETREF.
15+
1316
- Issue #25421: __sizeof__ methods of builtin types now use dynamic basic size.
1417
This allows sys.getsize() to work correctly with their subclasses with
1518
__slots__ defined.

Modules/_bsddb.c

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1607,9 +1607,8 @@ DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
16071607
}
16081608

16091609
/* Save a reference to the callback in the secondary DB. */
1610-
Py_XDECREF(secondaryDB->associateCallback);
16111610
Py_XINCREF(callback);
1612-
secondaryDB->associateCallback = callback;
1611+
Py_SETREF(secondaryDB->associateCallback, callback);
16131612
secondaryDB->primaryDBType = _DB_get_type(self);
16141613

16151614
/* PyEval_InitThreads is called here due to a quirk in python 1.5
@@ -2498,9 +2497,8 @@ static PyObject*
24982497
DB_set_private(DBObject* self, PyObject* private_obj)
24992498
{
25002499
/* We can set the private field even if db is closed */
2501-
Py_DECREF(self->private_obj);
25022500
Py_INCREF(private_obj);
2503-
self->private_obj = private_obj;
2501+
Py_SETREF(self->private_obj, private_obj);
25042502
RETURN_NONE();
25052503
}
25062504

@@ -6998,9 +6996,8 @@ static PyObject*
69986996
DBEnv_set_private(DBEnvObject* self, PyObject* private_obj)
69996997
{
70006998
/* We can set the private field even if dbenv is closed */
7001-
Py_DECREF(self->private_obj);
70026999
Py_INCREF(private_obj);
7003-
self->private_obj = private_obj;
7000+
Py_SETREF(self->private_obj, private_obj);
70047001
RETURN_NONE();
70057002
}
70067003

@@ -7253,9 +7250,8 @@ DBEnv_set_event_notify(DBEnvObject* self, PyObject* notifyFunc)
72537250
return NULL;
72547251
}
72557252

7256-
Py_XDECREF(self->event_notifyCallback);
72577253
Py_INCREF(notifyFunc);
7258-
self->event_notifyCallback = notifyFunc;
7254+
Py_SETREF(self->event_notifyCallback, notifyFunc);
72597255

72607256
/* This is to workaround a problem with un-initialized threads (see
72617257
comment in DB_associate) */
@@ -7413,9 +7409,8 @@ DBEnv_rep_set_transport(DBEnvObject* self, PyObject* args)
74137409
MYDB_END_ALLOW_THREADS;
74147410
RETURN_IF_ERR();
74157411

7416-
Py_DECREF(self->rep_transport);
74177412
Py_INCREF(rep_transport);
7418-
self->rep_transport = rep_transport;
7413+
Py_SETREF(self->rep_transport, rep_transport);
74197414
RETURN_NONE();
74207415
}
74217416

Modules/_csv.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -276,9 +276,8 @@ _set_str(const char *name, PyObject **target, PyObject *src, const char *dflt)
276276
return -1;
277277
}
278278
else {
279-
Py_XDECREF(*target);
280279
Py_INCREF(src);
281-
*target = src;
280+
Py_SETREF(*target, src);
282281
}
283282
}
284283
return 0;
@@ -770,8 +769,7 @@ parse_process_char(ReaderObj *self, char c)
770769
static int
771770
parse_reset(ReaderObj *self)
772771
{
773-
Py_XDECREF(self->fields);
774-
self->fields = PyList_New(0);
772+
Py_SETREF(self->fields, PyList_New(0));
775773
if (self->fields == NULL)
776774
return -1;
777775
self->field_len = 0;

Modules/_ctypes/_ctypes.c

Lines changed: 11 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -424,8 +424,7 @@ StructUnionType_new(PyTypeObject *type, PyObject *args, PyObject *kwds, int isSt
424424
Py_DECREF((PyObject *)dict);
425425
return NULL;
426426
}
427-
Py_DECREF(result->tp_dict);
428-
result->tp_dict = (PyObject *)dict;
427+
Py_SETREF(result->tp_dict, (PyObject *)dict);
429428
dict->format = _ctypes_alloc_format_string(NULL, "B");
430429
if (dict->format == NULL) {
431430
Py_DECREF(result);
@@ -903,8 +902,7 @@ PyCPointerType_SetProto(StgDictObject *stgdict, PyObject *proto)
903902
return -1;
904903
}
905904
Py_INCREF(proto);
906-
Py_XDECREF(stgdict->proto);
907-
stgdict->proto = proto;
905+
Py_SETREF(stgdict->proto, proto);
908906
return 0;
909907
}
910908

@@ -994,8 +992,7 @@ PyCPointerType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
994992
Py_DECREF((PyObject *)stgdict);
995993
return NULL;
996994
}
997-
Py_DECREF(result->tp_dict);
998-
result->tp_dict = (PyObject *)stgdict;
995+
Py_SETREF(result->tp_dict, (PyObject *)stgdict);
999996

1000997
return (PyObject *)result;
1001998
}
@@ -1460,8 +1457,7 @@ PyCArrayType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
14601457
Py_DECREF((PyObject *)stgdict);
14611458
return NULL;
14621459
}
1463-
Py_DECREF(result->tp_dict);
1464-
result->tp_dict = (PyObject *)stgdict;
1460+
Py_SETREF(result->tp_dict, (PyObject *)stgdict);
14651461

14661462
/* Special case for character arrays.
14671463
A permanent annoyance: char arrays are also strings!
@@ -1884,8 +1880,7 @@ static PyObject *CreateSwappedType(PyTypeObject *type, PyObject *args, PyObject
18841880
Py_DECREF((PyObject *)stgdict);
18851881
return NULL;
18861882
}
1887-
Py_DECREF(result->tp_dict);
1888-
result->tp_dict = (PyObject *)stgdict;
1883+
Py_SETREF(result->tp_dict, (PyObject *)stgdict);
18891884

18901885
return (PyObject *)result;
18911886
}
@@ -2393,8 +2388,7 @@ PyCFuncPtrType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
23932388
Py_DECREF((PyObject *)stgdict);
23942389
return NULL;
23952390
}
2396-
Py_DECREF(result->tp_dict);
2397-
result->tp_dict = (PyObject *)stgdict;
2391+
Py_SETREF(result->tp_dict, (PyObject *)stgdict);
23982392

23992393
if (-1 == make_funcptrtype_dict(stgdict)) {
24002394
Py_DECREF(result);
@@ -2536,8 +2530,7 @@ KeepRef(CDataObject *target, Py_ssize_t index, PyObject *keep)
25362530
}
25372531
ob = PyCData_GetContainer(target);
25382532
if (ob->b_objects == NULL || !PyDict_CheckExact(ob->b_objects)) {
2539-
Py_XDECREF(ob->b_objects);
2540-
ob->b_objects = keep; /* refcount consumed */
2533+
Py_SETREF(ob->b_objects, keep); /* refcount consumed */
25412534
return 0;
25422535
}
25432536
key = unique_key(target, index);
@@ -3059,9 +3052,8 @@ PyCFuncPtr_set_errcheck(PyCFuncPtrObject *self, PyObject *ob)
30593052
"the errcheck attribute must be callable");
30603053
return -1;
30613054
}
3062-
Py_XDECREF(self->errcheck);
30633055
Py_XINCREF(ob);
3064-
self->errcheck = ob;
3056+
Py_SETREF(self->errcheck, ob);
30653057
return 0;
30663058
}
30673059

@@ -3090,9 +3082,8 @@ PyCFuncPtr_set_restype(PyCFuncPtrObject *self, PyObject *ob)
30903082
return -1;
30913083
}
30923084
Py_XDECREF(self->checker);
3093-
Py_XDECREF(self->restype);
30943085
Py_INCREF(ob);
3095-
self->restype = ob;
3086+
Py_SETREF(self->restype, ob);
30963087
self->checker = PyObject_GetAttrString(ob, "_check_retval_");
30973088
if (self->checker == NULL)
30983089
PyErr_Clear();
@@ -3130,11 +3121,9 @@ PyCFuncPtr_set_argtypes(PyCFuncPtrObject *self, PyObject *ob)
31303121
converters = converters_from_argtypes(ob);
31313122
if (!converters)
31323123
return -1;
3133-
Py_XDECREF(self->converters);
3134-
self->converters = converters;
3135-
Py_XDECREF(self->argtypes);
3124+
Py_SETREF(self->converters, converters);
31363125
Py_INCREF(ob);
3137-
self->argtypes = ob;
3126+
Py_SETREF(self->argtypes, ob);
31383127
}
31393128
return 0;
31403129
}

Modules/_curses_panel.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -283,9 +283,8 @@ PyCursesPanel_replace_panel(PyCursesPanelObject *self, PyObject *args)
283283
PyErr_SetString(PyCursesError, "replace_panel() returned ERR");
284284
return NULL;
285285
}
286-
Py_DECREF(po->wo);
287-
po->wo = temp;
288-
Py_INCREF(po->wo);
286+
Py_INCREF(temp);
287+
Py_SETREF(po->wo, temp);
289288
Py_INCREF(Py_None);
290289
return Py_None;
291290
}

Modules/_json.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1717,8 +1717,7 @@ scanner_init(PyObject *self, PyObject *args, PyObject *kwds)
17171717
}
17181718
else if (PyUnicode_Check(s->encoding)) {
17191719
PyObject *tmp = PyUnicode_AsEncodedString(s->encoding, NULL, NULL);
1720-
Py_DECREF(s->encoding);
1721-
s->encoding = tmp;
1720+
Py_SETREF(s->encoding, tmp);
17221721
}
17231722
if (s->encoding == NULL)
17241723
goto bail;

Modules/_sqlite/connection.c

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -228,8 +228,8 @@ void pysqlite_flush_statement_cache(pysqlite_Connection* self)
228228
node = node->next;
229229
}
230230

231-
Py_DECREF(self->statement_cache);
232-
self->statement_cache = (pysqlite_Cache*)PyObject_CallFunction((PyObject*)&pysqlite_CacheType, "O", self);
231+
Py_SETREF(self->statement_cache,
232+
(pysqlite_Cache *)PyObject_CallFunction((PyObject *)&pysqlite_CacheType, "O", self));
233233
Py_DECREF(self);
234234
self->statement_cache->decref_factory = 0;
235235
}
@@ -346,9 +346,8 @@ PyObject* pysqlite_connection_cursor(pysqlite_Connection* self, PyObject* args,
346346
_pysqlite_drop_unused_cursor_references(self);
347347

348348
if (cursor && self->row_factory != Py_None) {
349-
Py_XDECREF(((pysqlite_Cursor*)cursor)->row_factory);
350349
Py_INCREF(self->row_factory);
351-
((pysqlite_Cursor*)cursor)->row_factory = self->row_factory;
350+
Py_SETREF(((pysqlite_Cursor *)cursor)->row_factory, self->row_factory);
352351
}
353352

354353
return cursor;
@@ -816,8 +815,7 @@ static void _pysqlite_drop_unused_statement_references(pysqlite_Connection* self
816815
}
817816
}
818817

819-
Py_DECREF(self->statements);
820-
self->statements = new_list;
818+
Py_SETREF(self->statements, new_list);
821819
}
822820

823821
static void _pysqlite_drop_unused_cursor_references(pysqlite_Connection* self)
@@ -848,8 +846,7 @@ static void _pysqlite_drop_unused_cursor_references(pysqlite_Connection* self)
848846
}
849847
}
850848

851-
Py_DECREF(self->cursors);
852-
self->cursors = new_list;
849+
Py_SETREF(self->cursors, new_list);
853850
}
854851

855852
PyObject* pysqlite_connection_create_function(pysqlite_Connection* self, PyObject* args, PyObject* kwargs)

Modules/_sqlite/cursor.c

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -172,8 +172,7 @@ int pysqlite_build_row_cast_map(pysqlite_Cursor* self)
172172
return 0;
173173
}
174174

175-
Py_XDECREF(self->row_cast_map);
176-
self->row_cast_map = PyList_New(0);
175+
Py_SETREF(self->row_cast_map, PyList_New(0));
177176

178177
for (i = 0; i < sqlite3_column_count(self->statement->st); i++) {
179178
converter = NULL;
@@ -544,9 +543,8 @@ PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject*
544543
}
545544

546545
/* reset description and rowcount */
547-
Py_DECREF(self->description);
548546
Py_INCREF(Py_None);
549-
self->description = Py_None;
547+
Py_SETREF(self->description, Py_None);
550548
self->rowcount = -1L;
551549

552550
func_args = PyTuple_New(1);
@@ -571,8 +569,8 @@ PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject*
571569
}
572570

573571
if (self->statement->in_use) {
574-
Py_DECREF(self->statement);
575-
self->statement = PyObject_New(pysqlite_Statement, &pysqlite_StatementType);
572+
Py_SETREF(self->statement,
573+
PyObject_New(pysqlite_Statement, &pysqlite_StatementType));
576574
if (!self->statement) {
577575
goto error;
578576
}
@@ -683,8 +681,7 @@ PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject*
683681
numcols = sqlite3_column_count(self->statement->st);
684682
Py_END_ALLOW_THREADS
685683

686-
Py_DECREF(self->description);
687-
self->description = PyTuple_New(numcols);
684+
Py_SETREF(self->description, PyTuple_New(numcols));
688685
if (!self->description) {
689686
goto error;
690687
}

Modules/_sre.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2054,8 +2054,7 @@ deepcopy(PyObject** object, PyObject* memo)
20542054
if (!copy)
20552055
return 0;
20562056

2057-
Py_DECREF(*object);
2058-
*object = copy;
2057+
Py_SETREF(*object, copy);
20592058

20602059
return 1; /* success */
20612060
}

0 commit comments

Comments
 (0)