summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/test/test_descr.py20
-rw-r--r--Objects/object.c22
2 files changed, 35 insertions, 7 deletions
diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py
index 353d0f2..e7e4a8f 100644
--- a/Lib/test/test_descr.py
+++ b/Lib/test/test_descr.py
@@ -365,6 +365,26 @@ def test_dir():
# object.
vereq(dir(None), dir(Ellipsis))
+ # Nasty test case for proxied objects
+ class Wrapper(object):
+ def __init__(self, obj):
+ self.__obj = obj
+ def __repr__(self):
+ return "Wrapper(%s)" % repr(self.__obj)
+ def __getitem__(self, key):
+ return Wrapper(self.__obj[key])
+ def __len__(self):
+ return len(self.__obj)
+ def __getattr__(self, name):
+ return Wrapper(getattr(self.__obj, name))
+
+ class C(object):
+ def __getclass(self):
+ return Wrapper(type(self))
+ __class__ = property(__getclass)
+
+ dir(C()) # This used to segfault
+
binops = {
'add': '+',
'sub': '-',
diff --git a/Objects/object.c b/Objects/object.c
index 85fd35f..1bd8db9 100644
--- a/Objects/object.c
+++ b/Objects/object.c
@@ -1520,14 +1520,22 @@ merge_class_dict(PyObject* dict, PyObject* aclass)
if (bases == NULL)
PyErr_Clear();
else {
+ /* We have no guarantee that bases is a real tuple */
int i, n;
- assert(PyTuple_Check(bases));
- n = PyTuple_GET_SIZE(bases);
- for (i = 0; i < n; i++) {
- PyObject *base = PyTuple_GET_ITEM(bases, i);
- if (merge_class_dict(dict, base) < 0) {
- Py_DECREF(bases);
- return -1;
+ n = PySequence_Size(bases); /* This better be right */
+ if (n < 0)
+ PyErr_Clear();
+ else {
+ for (i = 0; i < n; i++) {
+ PyObject *base = PySequence_GetItem(bases, i);
+ if (base == NULL) {
+ Py_DECREF(bases);
+ return -1;
+ }
+ if (merge_class_dict(dict, base) < 0) {
+ Py_DECREF(bases);
+ return -1;
+ }
}
}
Py_DECREF(bases);