[Python-checkins] [3.8] bpo-41909: Enable previously disabled recursion checks. (GH-22536) (GH-22551)

Serhiy Storchaka webhook-mailer at python.org
Sun Oct 4 18:28:04 EDT 2020


https://github.com/python/cpython/commit/09a7b3b618cd02694a0bc8abfa24c75f0e659407
commit: 09a7b3b618cd02694a0bc8abfa24c75f0e659407
branch: 3.8
author: Serhiy Storchaka <storchaka at gmail.com>
committer: GitHub <noreply at github.com>
date: 2020-10-05T01:28:00+03:00
summary:

[3.8] bpo-41909: Enable previously disabled recursion checks. (GH-22536) (GH-22551)

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.
(cherry picked from commit 9ece9cd65cdeb0a1f6e60475bbd0219161c348ac)

files:
A Misc/NEWS.d/next/Core and Builtins/2020-10-04-10-55-12.bpo-41909.BqHPcm.rst
M Lib/test/test_isinstance.py
M Objects/abstract.c
M Objects/unicodeobject.c

diff --git a/Lib/test/test_isinstance.py b/Lib/test/test_isinstance.py
index 53639e984e48a..31b38996930cc 100644
--- a/Lib/test/test_isinstance.py
+++ b/Lib/test/test_isinstance.py
@@ -271,6 +271,16 @@ def __bases__(self):
 
         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 0000000000000..388cfea065eed
--- /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 12237d570f743..9c42d817b4211 100644
--- a/Objects/abstract.c
+++ b/Objects/abstract.c
@@ -2316,9 +2316,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 4c2b42f959b83..01df54da0051d 100644
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -15285,9 +15285,7 @@ PyUnicode_InternInPlace(PyObject **p)
             return;
         }
     }
-    Py_ALLOW_RECURSION
     t = PyDict_SetDefault(interned, s, s);
-    Py_END_ALLOW_RECURSION
     if (t == NULL) {
         PyErr_Clear();
         return;



More information about the Python-checkins mailing list