summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/test/test_isinstance.py10
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2020-10-04-10-55-12.bpo-41909.BqHPcm.rst2
-rw-r--r--Objects/abstract.c2
-rw-r--r--Objects/unicodeobject.c2
4 files changed, 12 insertions, 4 deletions
diff --git a/Lib/test/test_isinstance.py b/Lib/test/test_isinstance.py
index 91e79c2..109c3f8 100644
--- a/Lib/test/test_isinstance.py
+++ b/Lib/test/test_isinstance.py
@@ -303,6 +303,16 @@ class TestIsInstanceIsSubclass(unittest.TestCase):
self.assertEqual(True, issubclass(B(), int))
+ def test_infinite_recursion_in_bases(self):
+ class X:
+ @property
+ def __bases__(self):
+ return self.__bases__
+
+ self.assertRaises(RecursionError, issubclass, X(), int)
+ self.assertRaises(RecursionError, issubclass, int, X())
+ self.assertRaises(RecursionError, isinstance, 1, X())
+
def blowstack(fxn, arg, compare_to):
# Make sure that calling isinstance with a deeply nested tuple for its
diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-10-04-10-55-12.bpo-41909.BqHPcm.rst b/Misc/NEWS.d/next/Core and Builtins/2020-10-04-10-55-12.bpo-41909.BqHPcm.rst
new file mode 100644
index 0000000..388cfea
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2020-10-04-10-55-12.bpo-41909.BqHPcm.rst
@@ -0,0 +1,2 @@
+Fixed stack overflow in :func:`issubclass` and :func:`isinstance` when
+getting the ``__bases__`` attribute leads to infinite recursion.
diff --git a/Objects/abstract.c b/Objects/abstract.c
index c471f18..c30fb4e 100644
--- a/Objects/abstract.c
+++ b/Objects/abstract.c
@@ -2336,9 +2336,7 @@ abstract_get_bases(PyObject *cls)
_Py_IDENTIFIER(__bases__);
PyObject *bases;
- Py_ALLOW_RECURSION
(void)_PyObject_LookupAttrId(cls, &PyId___bases__, &bases);
- Py_END_ALLOW_RECURSION
if (bases != NULL && !PyTuple_Check(bases)) {
Py_DECREF(bases);
return NULL;
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
index cf72238..6ae06a5 100644
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -15734,9 +15734,7 @@ PyUnicode_InternInPlace(PyObject **p)
}
PyObject *t;
- Py_ALLOW_RECURSION
t = PyDict_SetDefault(interned, s, s);
- Py_END_ALLOW_RECURSION
if (t == NULL) {
PyErr_Clear();