From 3249dec02484674830177488c8f01d8d04873928 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sun, 1 May 2011 23:19:15 +0200 Subject: [PATCH] Issue #9756: When calling a method descriptor or a slot wrapper descriptor, the check of the object type doesn't read the __class__ attribute anymore. Fix a crash if a class override its __class__ attribute (e.g. a proxy of the str type). --- Lib/test/test_descr.py | 16 ++++++++++++++++ Misc/NEWS | 5 +++++ Objects/descrobject.c | 9 ++++++--- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index bd88f453377..aafe428bd0c 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -4235,6 +4235,22 @@ order (MRO) for bases """ with self.assertRaises(AttributeError): del X.__abstractmethods__ + def test_proxy_call(self): + class FakeStr: + __class__ = str + + fake_str = FakeStr() + # isinstance() reads __class__ + self.assertTrue(isinstance(fake_str, str)) + + # call a method descriptor + with self.assertRaises(TypeError): + str.split(fake_str) + + # call a slot wrapper descriptor + with self.assertRaises(TypeError): + str.__add__(fake_str, "abc") + class DictProxyTests(unittest.TestCase): def setUp(self): diff --git a/Misc/NEWS b/Misc/NEWS index b4ba3b67cb0..41bda2a6a78 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,11 @@ What's New in Python 3.1.4? Core and Builtins ----------------- +- Issue #9756: When calling a method descriptor or a slot wrapper descriptor, + the check of the object type doesn't read the __class__ attribute anymore. + Fix a crash if a class override its __class__ attribute (e.g. a proxy of the + str type). + - Issue #6780: fix starts/endswith error message to mention that tuples are accepted too. diff --git a/Objects/descrobject.c b/Objects/descrobject.c index 5f118ce09ed..9eda4bdd7da 100644 --- a/Objects/descrobject.c +++ b/Objects/descrobject.c @@ -226,7 +226,8 @@ methoddescr_call(PyMethodDescrObject *descr, PyObject *args, PyObject *kwds) return NULL; } self = PyTuple_GET_ITEM(args, 0); - if (!PyObject_IsInstance(self, (PyObject *)(descr->d_type))) { + if (!_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self), + (PyObject *)(descr->d_type))) { PyErr_Format(PyExc_TypeError, "descriptor '%V' " "requires a '%.100s' object " @@ -284,7 +285,8 @@ wrapperdescr_call(PyWrapperDescrObject *descr, PyObject *args, PyObject *kwds) return NULL; } self = PyTuple_GET_ITEM(args, 0); - if (!PyObject_IsInstance(self, (PyObject *)(descr->d_type))) { + if (!_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self), + (PyObject *)(descr->d_type))) { PyErr_Format(PyExc_TypeError, "descriptor '%V' " "requires a '%.100s' object " @@ -1065,7 +1067,8 @@ PyWrapper_New(PyObject *d, PyObject *self) assert(PyObject_TypeCheck(d, &PyWrapperDescr_Type)); descr = (PyWrapperDescrObject *)d; - assert(PyObject_IsInstance(self, (PyObject *)(descr->d_type))); + assert(_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self), + (PyObject *)(descr->d_type))); wp = PyObject_GC_New(wrapperobject, &wrappertype); if (wp != NULL) {