[Python-checkins] bpo-39091: Fix segfault when Exception constructor returns non-exception for gen.throw. (GH-17658) (GH-27572)

ambv webhook-mailer at python.org
Tue Aug 3 06:11:06 EDT 2021


https://github.com/python/cpython/commit/8ce7f2f4ef04e19209f1dfd2a0cf50ddcd0e999f
commit: 8ce7f2f4ef04e19209f1dfd2a0cf50ddcd0e999f
branch: 3.10
author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com>
committer: ambv <lukasz at langa.pl>
date: 2021-08-03T12:10:38+02:00
summary:

bpo-39091: Fix segfault when Exception constructor returns non-exception for gen.throw. (GH-17658) (GH-27572)

Co-authored-by: Benjamin Peterson <benjamin at python.org>
(cherry picked from commit 83ca46b7784b7357d82ec47b33295e09ed7380cb)

Co-authored-by: Noah <33094578+coolreader18 at users.noreply.github.com>

files:
A Misc/NEWS.d/next/Core and Builtins/2019-12-21-14-18-32.bpo-39091.dOexgQ.rst
M Lib/test/test_generators.py
M Misc/ACKS
M Python/errors.c

diff --git a/Lib/test/test_generators.py b/Lib/test/test_generators.py
index ebf8bb7e320982..53d579e723c470 100644
--- a/Lib/test/test_generators.py
+++ b/Lib/test/test_generators.py
@@ -270,6 +270,32 @@ def gen():
         self.assertEqual(next(g), "done")
         self.assertEqual(sys.exc_info(), (None, None, None))
 
+    def test_except_throw_bad_exception(self):
+        class E(Exception):
+            def __new__(cls, *args, **kwargs):
+                return cls
+
+        def boring_generator():
+            yield
+
+        gen = boring_generator()
+
+        err_msg = 'should have returned an instance of BaseException'
+
+        with self.assertRaisesRegex(TypeError, err_msg):
+            gen.throw(E)
+
+        self.assertRaises(StopIteration, next, gen)
+
+        def generator():
+            with self.assertRaisesRegex(TypeError, err_msg):
+                yield
+
+        gen = generator()
+        next(gen)
+        with self.assertRaises(StopIteration):
+            gen.throw(E)
+
     def test_stopiteration_error(self):
         # See also PEP 479.
 
diff --git a/Misc/ACKS b/Misc/ACKS
index 3f0506ecf758e5..3e750c08bfd001 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -1300,6 +1300,7 @@ Peter Otten
 Michael Otteneder
 Richard Oudkerk
 Russel Owen
+Noah Oxer
 Joonas Paalasmaa
 Yaroslav Pankovych
 Martin Packman
diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-12-21-14-18-32.bpo-39091.dOexgQ.rst b/Misc/NEWS.d/next/Core and Builtins/2019-12-21-14-18-32.bpo-39091.dOexgQ.rst
new file mode 100644
index 00000000000000..c3b4e810d658b2
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2019-12-21-14-18-32.bpo-39091.dOexgQ.rst	
@@ -0,0 +1 @@
+Fix crash when using passing a non-exception to a generator's ``throw()`` method. Patch by Noah Oxer
diff --git a/Python/errors.c b/Python/errors.c
index f743d3089e20ba..d4b9db1aba34ee 100644
--- a/Python/errors.c
+++ b/Python/errors.c
@@ -85,17 +85,29 @@ _PyErr_GetTopmostException(PyThreadState *tstate)
 }
 
 static PyObject*
-_PyErr_CreateException(PyObject *exception, PyObject *value)
+_PyErr_CreateException(PyObject *exception_type, PyObject *value)
 {
+    PyObject *exc;
+
     if (value == NULL || value == Py_None) {
-        return _PyObject_CallNoArg(exception);
+        exc = _PyObject_CallNoArg(exception_type);
     }
     else if (PyTuple_Check(value)) {
-        return PyObject_Call(exception, value, NULL);
+        exc = PyObject_Call(exception_type, value, NULL);
     }
     else {
-        return PyObject_CallOneArg(exception, value);
+        exc = PyObject_CallOneArg(exception_type, value);
+    }
+
+    if (exc != NULL && !PyExceptionInstance_Check(exc)) {
+        PyErr_Format(PyExc_TypeError,
+                     "calling %R should have returned an instance of "
+                     "BaseException, not %s",
+                     exception_type, Py_TYPE(exc)->tp_name);
+        Py_CLEAR(exc);
     }
+
+    return exc;
 }
 
 void



More information about the Python-checkins mailing list