mirror of https://github.com/python/cpython
closes bpo-39091: Fix segfault when Exception constructor returns non-exception for gen.throw. (#17658)
Co-authored-by: Benjamin Peterson <benjamin@python.org>
This commit is contained in:
parent
54f185b6d3
commit
83ca46b778
|
@ -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.
|
||||
|
||||
|
|
|
@ -1300,6 +1300,7 @@ Peter Otten
|
|||
Michael Otteneder
|
||||
Richard Oudkerk
|
||||
Russel Owen
|
||||
Noah Oxer
|
||||
Joonas Paalasmaa
|
||||
Yaroslav Pankovych
|
||||
Martin Packman
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Fix crash when using passing a non-exception to a generator's ``throw()`` method. Patch by Noah Oxer
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue