mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +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;
|
f = descr->ob_type->tp_descr_get;
|
||||||
if (f != NULL && PyDescr_IsData(descr)) {
|
if (f != NULL && PyDescr_IsData(descr)) {
|
||||||
res = f(descr, obj, (PyObject *)obj->ob_type);
|
res = f(descr, obj, (PyObject *)obj->ob_type);
|
||||||
Py_DECREF(descr);
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1105,7 +1104,6 @@ _PyObject_GenericGetAttrWithDict(PyObject *obj, PyObject *name, PyObject *dict)
|
||||||
res = PyDict_GetItem(dict, name);
|
res = PyDict_GetItem(dict, name);
|
||||||
if (res != NULL) {
|
if (res != NULL) {
|
||||||
Py_INCREF(res);
|
Py_INCREF(res);
|
||||||
Py_XDECREF(descr);
|
|
||||||
Py_DECREF(dict);
|
Py_DECREF(dict);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
@ -1114,13 +1112,12 @@ _PyObject_GenericGetAttrWithDict(PyObject *obj, PyObject *name, PyObject *dict)
|
||||||
|
|
||||||
if (f != NULL) {
|
if (f != NULL) {
|
||||||
res = f(descr, obj, (PyObject *)Py_TYPE(obj));
|
res = f(descr, obj, (PyObject *)Py_TYPE(obj));
|
||||||
Py_DECREF(descr);
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (descr != NULL) {
|
if (descr != NULL) {
|
||||||
res = descr;
|
res = descr;
|
||||||
/* descr was already increfed above */
|
descr = NULL;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1128,6 +1125,7 @@ _PyObject_GenericGetAttrWithDict(PyObject *obj, PyObject *name, PyObject *dict)
|
||||||
"'%.50s' object has no attribute '%U'",
|
"'%.50s' object has no attribute '%U'",
|
||||||
tp->tp_name, name);
|
tp->tp_name, name);
|
||||||
done:
|
done:
|
||||||
|
Py_XDECREF(descr);
|
||||||
Py_DECREF(name);
|
Py_DECREF(name);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -1163,6 +1161,8 @@ _PyObject_GenericSetAttrWithDict(PyObject *obj, PyObject *name,
|
||||||
}
|
}
|
||||||
|
|
||||||
descr = _PyType_Lookup(tp, name);
|
descr = _PyType_Lookup(tp, name);
|
||||||
|
Py_XINCREF(descr);
|
||||||
|
|
||||||
f = NULL;
|
f = NULL;
|
||||||
if (descr != NULL) {
|
if (descr != NULL) {
|
||||||
f = descr->ob_type->tp_descr_set;
|
f = descr->ob_type->tp_descr_set;
|
||||||
|
@ -1212,6 +1212,7 @@ _PyObject_GenericSetAttrWithDict(PyObject *obj, PyObject *name,
|
||||||
"'%.50s' object attribute '%U' is read-only",
|
"'%.50s' object attribute '%U' is read-only",
|
||||||
tp->tp_name, name);
|
tp->tp_name, name);
|
||||||
done:
|
done:
|
||||||
|
Py_XDECREF(descr);
|
||||||
Py_DECREF(name);
|
Py_DECREF(name);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue