summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/test/test_generators.py26
-rw-r--r--Misc/ACKS1
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2019-12-21-14-18-32.bpo-39091.dOexgQ.rst1
-rw-r--r--Python/errors.c20
4 files changed, 44 insertions, 4 deletions
diff --git a/Lib/test/test_generators.py b/Lib/test/test_generators.py
index ebf8bb7..53d579e 100644
--- a/Lib/test/test_generators.py
+++ b/Lib/test/test_generators.py
@@ -270,6 +270,32 @@ class ExceptionTest(unittest.TestCase):
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 97a360c..f845c1c 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 0000000..c3b4e81
--- /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 1f84215..eeb84e8 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