Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 3249dec

Browse files
author
Victor Stinner
committed
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).
1 parent 9c4f09d commit 3249dec

3 files changed

Lines changed: 27 additions & 3 deletions

File tree

Lib/test/test_descr.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4235,6 +4235,22 @@ class X(object):
42354235
with self.assertRaises(AttributeError):
42364236
del X.__abstractmethods__
42374237

4238+
def test_proxy_call(self):
4239+
class FakeStr:
4240+
__class__ = str
4241+
4242+
fake_str = FakeStr()
4243+
# isinstance() reads __class__
4244+
self.assertTrue(isinstance(fake_str, str))
4245+
4246+
# call a method descriptor
4247+
with self.assertRaises(TypeError):
4248+
str.split(fake_str)
4249+
4250+
# call a slot wrapper descriptor
4251+
with self.assertRaises(TypeError):
4252+
str.__add__(fake_str, "abc")
4253+
42384254

42394255
class DictProxyTests(unittest.TestCase):
42404256
def setUp(self):

Misc/NEWS

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ What's New in Python 3.1.4?
1010
Core and Builtins
1111
-----------------
1212

13+
- Issue #9756: When calling a method descriptor or a slot wrapper descriptor,
14+
the check of the object type doesn't read the __class__ attribute anymore.
15+
Fix a crash if a class override its __class__ attribute (e.g. a proxy of the
16+
str type).
17+
1318
- Issue #6780: fix starts/endswith error message to mention that tuples are
1419
accepted too.
1520

Objects/descrobject.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,8 @@ methoddescr_call(PyMethodDescrObject *descr, PyObject *args, PyObject *kwds)
226226
return NULL;
227227
}
228228
self = PyTuple_GET_ITEM(args, 0);
229-
if (!PyObject_IsInstance(self, (PyObject *)(descr->d_type))) {
229+
if (!_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self),
230+
(PyObject *)(descr->d_type))) {
230231
PyErr_Format(PyExc_TypeError,
231232
"descriptor '%V' "
232233
"requires a '%.100s' object "
@@ -284,7 +285,8 @@ wrapperdescr_call(PyWrapperDescrObject *descr, PyObject *args, PyObject *kwds)
284285
return NULL;
285286
}
286287
self = PyTuple_GET_ITEM(args, 0);
287-
if (!PyObject_IsInstance(self, (PyObject *)(descr->d_type))) {
288+
if (!_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self),
289+
(PyObject *)(descr->d_type))) {
288290
PyErr_Format(PyExc_TypeError,
289291
"descriptor '%V' "
290292
"requires a '%.100s' object "
@@ -1065,7 +1067,8 @@ PyWrapper_New(PyObject *d, PyObject *self)
10651067

10661068
assert(PyObject_TypeCheck(d, &PyWrapperDescr_Type));
10671069
descr = (PyWrapperDescrObject *)d;
1068-
assert(PyObject_IsInstance(self, (PyObject *)(descr->d_type)));
1070+
assert(_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self),
1071+
(PyObject *)(descr->d_type)));
10691072

10701073
wp = PyObject_GC_New(wrapperobject, &wrappertype);
10711074
if (wp != NULL) {

0 commit comments

Comments
 (0)