]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-41909: Enable previously disabled recursion checks. (GH-22536)
authorSerhiy Storchaka <storchaka@gmail.com>
Sun, 4 Oct 2020 21:55:57 +0000 (00:55 +0300)
committerGitHub <noreply@github.com>
Sun, 4 Oct 2020 21:55:57 +0000 (00:55 +0300)
Enable recursion checks which were disabled when get __bases__ of
non-type objects in issubclass() and isinstance() and when intern
strings. It fixes a stack overflow when getting __bases__ leads
to infinite recursion.

Originally recursion checks was disabled for PyDict_GetItem() which
silences all errors including the one raised in case of detected
recursion and can return incorrect result. But now the code uses
PyDict_GetItemWithError() and PyDict_SetDefault() instead.

Lib/test/test_isinstance.py
Misc/NEWS.d/next/Core and Builtins/2020-10-04-10-55-12.bpo-41909.BqHPcm.rst [new file with mode: 0644]
Objects/abstract.c
Objects/unicodeobject.c

index 91e79c295481db85396ef7e7eac54a2b759d4b3a..109c3f84a5c426dc45a1277bdc992b10421ae2e4 100644 (file)
@@ -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 (file)
index 0000000..388cfea
--- /dev/null
@@ -0,0 +1,2 @@
+Fixed stack overflow in :func:`issubclass` and :func:`isinstance` when
+getting the ``__bases__`` attribute leads to infinite recursion.
index c471f184f6c8487aca9a917d59242b593a9ca15a..c30fb4eb6a604e2047074b3b900b81878e7baa3a 100644 (file)
@@ -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;
index cf72238a8d058548a1359ebc9e010d163a1e19ef..6ae06a508c6140a61d4a8ac2fb5619aad7cafa50 100644 (file)
@@ -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();