From 5a30620e68ebb911eef4d583de3776d782148637 Mon Sep 17 00:00:00 2001 From: jdemeyer Date: Fri, 19 Oct 2018 23:50:06 +0200 Subject: bpo-25750: Add test on bad descriptor __get__() (GH-9084) --- Lib/test/test_descr.py | 21 +++++++++++++++++++++ Modules/_testcapimodule.c | 23 +++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index b96d35c..b38cb76 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -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">") + @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): diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index add642f..4381e93 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -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}, -- cgit v0.12