mirror of
https://github.com/python/cpython.git
synced 2025-09-26 10:19:53 +00:00
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.
This commit is contained in:
parent
d74782b0ac
commit
2d01dc00bc
2 changed files with 5 additions and 33 deletions
|
@ -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,)
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue