diff -r 8639ec6f3d06 Lib/test/crashers/borrowed_ref_2.py --- a/Lib/test/crashers/borrowed_ref_2.py Tue Mar 06 13:45:57 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -""" -_PyType_Lookup() returns a borrowed reference. -This attacks PyObject_GenericSetAttr(). - -NB. on my machine this crashes in 2.5 debug but not release. -""" - -class A(object): - pass - -class B(object): - def __del__(self): - print("hi") - del C.d - -class D(object): - def __set__(self, obj, value): - self.hello = 42 - -class C(object): - d = D() - - def g(): - pass - - -c = C() -a = A() -a.cycle = a -a.other = B() - -lst = [None] * 1000000 -i = 0 -del a -while 1: - c.d = 42 # segfaults in PyMethod_New(__func__=D.__set__, __self__=d) - lst[i] = c.g # consume the free list of instancemethod objects - i += 1 diff -r 8639ec6f3d06 Objects/object.c --- a/Objects/object.c Tue Mar 06 13:45:57 2012 +0100 +++ b/Objects/object.c Tue Mar 06 18:18:45 2012 +0100 @@ -1074,7 +1074,6 @@ _PyObject_GenericGetAttrWithDict(PyObjec 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(PyObjec 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(PyObjec 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(PyObjec "'%.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(PyObjec } 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(PyObjec "'%.50s' object attribute '%U' is read-only", tp->tp_name, name); done: + Py_XDECREF(descr); Py_DECREF(name); return res; }