summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>2008-01-24 17:58:05 (GMT)
committerGuido van Rossum <guido@python.org>2008-01-24 17:58:05 (GMT)
commit37edeab77875ef35ea54b92d5ba8a94df7deb3f7 (patch)
tree04730c76af49de3afc7da67fe4b7670aa8e745d6
parent4e3f12486fe0e4d6caf3c46e501a15283cf1c95e (diff)
downloadcpython-37edeab77875ef35ea54b92d5ba8a94df7deb3f7.zip
cpython-37edeab77875ef35ea54b92d5ba8a94df7deb3f7.tar.gz
cpython-37edeab77875ef35ea54b92d5ba8a94df7deb3f7.tar.bz2
Fix test67.py from issue #1303614.
-rw-r--r--Lib/test/crashers/loosing_dict_ref.py21
-rw-r--r--Lib/test/test_descr.py24
-rw-r--r--Objects/object.c5
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 f44370b..0000000
--- 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 08dfcdf..61be8a8 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 dbe5658..698ba47 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;
}
}