]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-25750: Add test on bad descriptor __get__() (GH-9084)
authorjdemeyer <jdemeyer@cage.ugent.be>
Fri, 19 Oct 2018 21:50:06 +0000 (23:50 +0200)
committerVictor Stinner <vstinner@redhat.com>
Fri, 19 Oct 2018 21:50:06 +0000 (23:50 +0200)
Lib/test/test_descr.py
Modules/_testcapimodule.c

index b96d35cc729913ef7809b540a9926ead0cb5d46f..b38cb765cdc010987909eb17c0b798db8649ce2f 100644 (file)
@@ -13,6 +13,11 @@ import weakref
 from copy import deepcopy
 from test import support
 
+try:
+    import _testcapi
+except ImportError:
+    _testcapi = None
+
 
 class OperatorsTest(unittest.TestCase):
 
@@ -4757,6 +4762,22 @@ order (MRO) for bases """
         self.assertRegex(repr(method),
             r"<bound method qualname of <object object at .*>>")
 
+    @unittest.skipIf(_testcapi is None, 'need the _testcapi module')
+    def test_bpo25750(self):
+        # bpo-25750: calling a descriptor (implemented as built-in
+        # function with METH_FASTCALL) should not crash CPython if the
+        # descriptor deletes itself from the class.
+        class Descr:
+            __get__ = _testcapi.bad_get
+
+        class X:
+            descr = Descr()
+            def __new__(cls):
+                cls.descr = None
+                # Create this large list to corrupt some unused memory
+                cls.lst = [2**i for i in range(10000)]
+        X.descr
+
 
 class DictProxyTests(unittest.TestCase):
     def setUp(self):
index add642f223afdc49dbf420dd04afb8bcc3c11c2c..4381e93ca913a10163c303ccfbcab84a1e9eb07c 100644 (file)
@@ -4550,6 +4550,28 @@ new_hamt(PyObject *self, PyObject *args)
 }
 
 
+/* def bad_get(self, obj, cls):
+       cls()
+       return repr(self)
+*/
+static PyObject*
+bad_get(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+    if (nargs != 3) {
+        PyErr_SetString(PyExc_TypeError, "bad_get requires exactly 3 arguments");
+        return NULL;
+    }
+
+    PyObject *res = PyObject_CallObject(args[2], NULL);
+    if (res == NULL) {
+        return NULL;
+    }
+    Py_DECREF(res);
+
+    return PyObject_Repr(args[0]);
+}
+
+
 static PyObject *
 encode_locale_ex(PyObject *self, PyObject *args)
 {
@@ -5017,6 +5039,7 @@ static PyMethodDef TestMethods[] = {
     {"get_mapping_items", get_mapping_items, METH_O},
     {"test_pythread_tss_key_state", test_pythread_tss_key_state, METH_VARARGS},
     {"hamt", new_hamt, METH_NOARGS},
+    {"bad_get", bad_get, METH_FASTCALL},
     {"EncodeLocaleEx", encode_locale_ex, METH_VARARGS},
     {"DecodeLocaleEx", decode_locale_ex, METH_VARARGS},
     {"get_coreconfig", get_coreconfig, METH_NOARGS},