summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@gmail.com>2012-03-08 23:44:13 (GMT)
committerVictor Stinner <victor.stinner@gmail.com>2012-03-08 23:44:13 (GMT)
commit2d01dc00bc4ca3eb0cf1cc1ee44859a4eaf165d9 (patch)
tree477cdcbe6c0848ad892859fbbaad3c0ff8a5d718
parentd74782b0ac7dc5c7b8b7ca575829f2f33af66684 (diff)
downloadcpython-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.py29
-rw-r--r--Objects/object.c9
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;
}