diff options
-rw-r--r-- | Lib/test/crashers/loosing_dict_ref.py | 21 | ||||
-rw-r--r-- | Lib/test/test_descr.py | 24 | ||||
-rw-r--r-- | Objects/object.c | 5 |
3 files changed, 29 insertions, 21 deletions
diff --git a/Lib/test/crashers/loosing_dict_ref.py b/Lib/test/crashers/loosing_dict_ref.py deleted file mode 100644 index f44370b9a5..0000000000 --- a/Lib/test/crashers/loosing_dict_ref.py +++ /dev/null @@ -1,21 +0,0 @@ - -# http://python.org/sf/1303614 - -class Strange(object): - def __hash__(self): - return hash('hello') - - def __eq__(self, other): - x.__dict__ = {} # the old x.__dict__ is deallocated - return False - - -class X(object): - pass - -if __name__ == '__main__': - v = 123 - x = X() - x.__dict__ = {Strange(): 42, - 'hello': v+456} - x.hello # segfault: the above dict is accessed after it's deallocated diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index 08dfcdfc0a..61be8a8281 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -4504,6 +4504,29 @@ def test_borrowed_ref_4_segfault(): finally: __builtin__.__import__ = orig_import +def test_losing_dict_ref_segfault(): + # This used to segfault; + # derived from issue #1303614, test67.py + if verbose: + print "Testing losing dict ref segfault..." + + class Strange(object): + def __hash__(self): + return hash('hello') + + def __eq__(self, other): + x.__dict__ = {} # the old x.__dict__ is deallocated + return False + + class X(object): + pass + + v = 123 + x = X() + x.__dict__ = {Strange(): 42, 'hello': v+456} + x.hello + + def test_main(): weakref_segfault() # Must be first, somehow wrapper_segfault() @@ -4606,6 +4629,7 @@ def test_main(): test_weakref_in_del_segfault() test_borrowed_ref_3_segfault() test_borrowed_ref_4_segfault() + test_losing_dict_ref_segfault() if verbose: print "All OK" diff --git a/Objects/object.c b/Objects/object.c index dbe5658fac..698ba47601 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -1349,12 +1349,15 @@ PyObject_GenericGetAttr(PyObject *obj, PyObject *name) dictptr = (PyObject **) ((char *)obj + dictoffset); dict = *dictptr; if (dict != NULL) { + Py_INCREF(dict); res = PyDict_GetItem(dict, name); if (res != NULL) { Py_INCREF(res); Py_XDECREF(descr); + Py_DECREF(dict); goto done; } + Py_DECREF(dict); } } @@ -1435,12 +1438,14 @@ PyObject_GenericSetAttr(PyObject *obj, PyObject *name, PyObject *value) *dictptr = dict; } if (dict != NULL) { + Py_INCREF(dict); if (value == NULL) res = PyDict_DelItem(dict, name); else res = PyDict_SetItem(dict, name, value); if (res < 0 && PyErr_ExceptionMatches(PyExc_KeyError)) PyErr_SetObject(PyExc_AttributeError, name); + Py_DECREF(dict); goto done; } } |