]> granicus.if.org Git - python/commitdiff
bpo-34441: Fix ABC.__subclasscheck__ crash on classes with invalid __subclasses__...
authorAlexey Izbyshev <izbyshev@ispras.ru>
Mon, 20 Aug 2018 20:04:19 +0000 (23:04 +0300)
committerBerker Peksag <berker.peksag@gmail.com>
Mon, 20 Aug 2018 20:04:19 +0000 (23:04 +0300)
The missing NULL check was reported by Svace static analyzer.

Lib/test/test_abc.py
Misc/NEWS.d/next/Library/2018-08-20-16-48-32.bpo-34441._zx9lU.rst [new file with mode: 0644]
Modules/_abc.c

index 6fc3c95e4a645efad99d218a5008f41267d3d8be..9f5afb241aea3a16d6bf3acb4f75b929ce0acf3b 100644 (file)
@@ -410,6 +410,36 @@ def test_factory(abc_ABCMeta, abc_get_cache_token):
             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 (file)
index 0000000..6db095b
--- /dev/null
@@ -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.
index 562a2e6d730dd398bd7ea0a8258b04ad34222d5e..ce9140fd03ccc47aeb2942470fd44404cfc887a5 100644 (file)
@@ -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;