[Python-checkins] bpo-34441: Fix ABC.__subclasscheck__ crash on classes with invalid __subclasses__ (GH-8835)

Berker Peksag webhook-mailer at python.org
Mon Aug 20 16:04:24 EDT 2018


https://github.com/python/cpython/commit/cdbf50cba1664f72ae6621a89c324a32fea70377
commit: cdbf50cba1664f72ae6621a89c324a32fea70377
branch: master
author: Alexey Izbyshev <izbyshev at ispras.ru>
committer: Berker Peksag <berker.peksag at gmail.com>
date: 2018-08-20T23:04:19+03:00
summary:

bpo-34441: Fix ABC.__subclasscheck__ crash on classes with invalid __subclasses__ (GH-8835)

The missing NULL check was reported by Svace static analyzer.

files:
A Misc/NEWS.d/next/Library/2018-08-20-16-48-32.bpo-34441._zx9lU.rst
M Lib/test/test_abc.py
M Modules/_abc.c

diff --git a/Lib/test/test_abc.py b/Lib/test/test_abc.py
index 6fc3c95e4a64..9f5afb241aea 100644
--- a/Lib/test/test_abc.py
+++ b/Lib/test/test_abc.py
@@ -410,6 +410,36 @@ class C:
             with self.assertRaises(TypeError):
                 issubclass(C(), A)
 
+            # bpo-34441: Check that issubclass() doesn't crash on bogus
+            # classes.
+            bogus_subclasses = [
+                None,
+                lambda x: [],
+                lambda: 42,
+                lambda: [42],
+            ]
+
+            for i, func in enumerate(bogus_subclasses):
+                class S(metaclass=abc_ABCMeta):
+                    __subclasses__ = func
+
+                with self.subTest(i=i):
+                    with self.assertRaises(TypeError):
+                        issubclass(int, S)
+
+            # Also check that issubclass() propagates exceptions raised by
+            # __subclasses__.
+            exc_msg = "exception from __subclasses__"
+
+            def raise_exc():
+                raise Exception(exc_msg)
+
+            class S(metaclass=abc_ABCMeta):
+                __subclasses__ = raise_exc
+
+            with self.assertRaisesRegex(Exception, exc_msg):
+                issubclass(int, S)
+
         def test_all_new_methods_are_called(self):
             class A(metaclass=abc_ABCMeta):
                 pass
diff --git a/Misc/NEWS.d/next/Library/2018-08-20-16-48-32.bpo-34441._zx9lU.rst b/Misc/NEWS.d/next/Library/2018-08-20-16-48-32.bpo-34441._zx9lU.rst
new file mode 100644
index 000000000000..6db095bdf0c6
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2018-08-20-16-48-32.bpo-34441._zx9lU.rst
@@ -0,0 +1,3 @@
+Fix crash when an ``ABC``-derived class with invalid ``__subclasses__`` is
+passed as the second argument to :func:`issubclass()`. Patch by Alexey
+Izbyshev.
diff --git a/Modules/_abc.c b/Modules/_abc.c
index 562a2e6d730d..ce9140fd03cc 100644
--- a/Modules/_abc.c
+++ b/Modules/_abc.c
@@ -665,6 +665,9 @@ _abc__abc_subclasscheck_impl(PyObject *module, PyObject *self,
 
     /* 6. Check if it's a subclass of a subclass (recursive). */
     subclasses = PyObject_CallMethod(self, "__subclasses__", NULL);
+    if (subclasses == NULL) {
+        goto end;
+    }
     if (!PyList_Check(subclasses)) {
         PyErr_SetString(PyExc_TypeError, "__subclasses__() must return a list");
         goto end;



More information about the Python-checkins mailing list