]> granicus.if.org Git - python/commitdiff
Issue #14211: _PyObject_GenericSetAttrWithDict() keeps a strong reference to
authorVictor Stinner <victor.stinner@gmail.com>
Thu, 8 Mar 2012 23:44:13 +0000 (00:44 +0100)
committerVictor Stinner <victor.stinner@gmail.com>
Thu, 8 Mar 2012 23:44:13 +0000 (00:44 +0100)
the descriptor because it may be destroyed before being used, destroyed during
the update of the dict for example.

Lib/test/crashers/borrowed_ref_1.py [deleted file]
Objects/object.c

diff --git a/Lib/test/crashers/borrowed_ref_1.py b/Lib/test/crashers/borrowed_ref_1.py
deleted file mode 100644 (file)
index b82f464..0000000
+++ /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,)
index 70d320ca35364adce45a9f4505c95cd4bfa36bff..08ad68f05ab3e0ff1e9ab909d8143fea3d042dd4 100644 (file)
@@ -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;
 }