diff options
author | Victor Stinner <victor.stinner@gmail.com> | 2012-03-08 23:44:13 (GMT) |
---|---|---|
committer | Victor Stinner <victor.stinner@gmail.com> | 2012-03-08 23:44:13 (GMT) |
commit | 2d01dc00bc4ca3eb0cf1cc1ee44859a4eaf165d9 (patch) | |
tree | 477cdcbe6c0848ad892859fbbaad3c0ff8a5d718 | |
parent | d74782b0ac7dc5c7b8b7ca575829f2f33af66684 (diff) | |
download | cpython-2d01dc00bc4ca3eb0cf1cc1ee44859a4eaf165d9.zip cpython-2d01dc00bc4ca3eb0cf1cc1ee44859a4eaf165d9.tar.gz cpython-2d01dc00bc4ca3eb0cf1cc1ee44859a4eaf165d9.tar.bz2 |
Issue #14211: _PyObject_GenericSetAttrWithDict() keeps a strong reference to
the descriptor because it may be destroyed before being used, destroyed during
the update of the dict for example.
-rw-r--r-- | Lib/test/crashers/borrowed_ref_1.py | 29 | ||||
-rw-r--r-- | Objects/object.c | 9 |
2 files changed, 5 insertions, 33 deletions
diff --git a/Lib/test/crashers/borrowed_ref_1.py b/Lib/test/crashers/borrowed_ref_1.py deleted file mode 100644 index b82f464..0000000 --- a/Lib/test/crashers/borrowed_ref_1.py +++ /dev/null @@ -1,29 +0,0 @@ -""" -_PyType_Lookup() returns a borrowed reference. -This attacks the call in dictobject.c. -""" - -class A(object): - pass - -class B(object): - def __del__(self): - print('hi') - del D.__missing__ - -class D(dict): - class __missing__: - def __init__(self, *args): - pass - - -d = D() -a = A() -a.cycle = a -a.other = B() -del a - -prev = None -while 1: - d[5] - prev = (prev,) diff --git a/Objects/object.c b/Objects/object.c index 70d320c..08ad68f 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -1074,7 +1074,6 @@ _PyObject_GenericGetAttrWithDict(PyObject *obj, PyObject *name, PyObject *dict) f = descr->ob_type->tp_descr_get; if (f != NULL && PyDescr_IsData(descr)) { res = f(descr, obj, (PyObject *)obj->ob_type); - Py_DECREF(descr); goto done; } } @@ -1105,7 +1104,6 @@ _PyObject_GenericGetAttrWithDict(PyObject *obj, PyObject *name, PyObject *dict) res = PyDict_GetItem(dict, name); if (res != NULL) { Py_INCREF(res); - Py_XDECREF(descr); Py_DECREF(dict); goto done; } @@ -1114,13 +1112,12 @@ _PyObject_GenericGetAttrWithDict(PyObject *obj, PyObject *name, PyObject *dict) if (f != NULL) { res = f(descr, obj, (PyObject *)Py_TYPE(obj)); - Py_DECREF(descr); goto done; } if (descr != NULL) { res = descr; - /* descr was already increfed above */ + descr = NULL; goto done; } @@ -1128,6 +1125,7 @@ _PyObject_GenericGetAttrWithDict(PyObject *obj, PyObject *name, PyObject *dict) "'%.50s' object has no attribute '%U'", tp->tp_name, name); done: + Py_XDECREF(descr); Py_DECREF(name); return res; } @@ -1163,6 +1161,8 @@ _PyObject_GenericSetAttrWithDict(PyObject *obj, PyObject *name, } descr = _PyType_Lookup(tp, name); + Py_XINCREF(descr); + f = NULL; if (descr != NULL) { f = descr->ob_type->tp_descr_set; @@ -1212,6 +1212,7 @@ _PyObject_GenericSetAttrWithDict(PyObject *obj, PyObject *name, "'%.50s' object attribute '%U' is read-only", tp->tp_name, name); done: + Py_XDECREF(descr); Py_DECREF(name); return res; } |