Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit b0be6b3

Browse filesBrowse files
authored
bpo-29587: _PyErr_ChainExceptions() checks exception (GH-19902)
_PyErr_ChainExceptions() now ensures that the first parameter is an exception type, as done by _PyErr_SetObject(). * The following function now check PyExceptionInstance_Check() in an assertion using a new _PyBaseExceptionObject_cast() helper function: * PyException_GetTraceback(), PyException_SetTraceback() * PyException_GetCause(), PyException_SetCause() * PyException_GetContext(), PyException_SetContext() * PyExceptionClass_Name() now checks PyExceptionClass_Check() with an assertion. * Remove XXX comment and add gi_exc_state variable to _gen_throw(). * Remove comment from test_generators
1 parent 4e30ed3 commit b0be6b3
Copy full SHA for b0be6b3

File tree

Expand file treeCollapse file tree

4 files changed

+45
-24
lines changed
Filter options
Expand file treeCollapse file tree

4 files changed

+45
-24
lines changed

‎Lib/test/test_generators.py

Copy file name to clipboardExpand all lines: Lib/test/test_generators.py
-3Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -342,9 +342,6 @@ def g():
342342
try:
343343
yield
344344
except Exception:
345-
# Without the `gi_exc_state.exc_type != Py_None` in
346-
# _gen_throw(), this line was causing a crash ("Segmentation
347-
# fault (core dumped)") on e.g. Fedora 32.
348345
raise RuntimeError
349346

350347
gen = g()

‎Objects/exceptions.c

Copy file name to clipboardExpand all lines: Objects/exceptions.c
+25-11Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -304,22 +304,33 @@ static PyGetSetDef BaseException_getset[] = {
304304
};
305305

306306

307+
static inline PyBaseExceptionObject*
308+
_PyBaseExceptionObject_cast(PyObject *exc)
309+
{
310+
assert(PyExceptionInstance_Check(exc));
311+
return (PyBaseExceptionObject *)exc;
312+
}
313+
314+
307315
PyObject *
308-
PyException_GetTraceback(PyObject *self) {
309-
PyBaseExceptionObject *base_self = (PyBaseExceptionObject *)self;
316+
PyException_GetTraceback(PyObject *self)
317+
{
318+
PyBaseExceptionObject *base_self = _PyBaseExceptionObject_cast(self);
310319
Py_XINCREF(base_self->traceback);
311320
return base_self->traceback;
312321
}
313322

314323

315324
int
316-
PyException_SetTraceback(PyObject *self, PyObject *tb) {
317-
return BaseException_set_tb((PyBaseExceptionObject *)self, tb, NULL);
325+
PyException_SetTraceback(PyObject *self, PyObject *tb)
326+
{
327+
return BaseException_set_tb(_PyBaseExceptionObject_cast(self), tb, NULL);
318328
}
319329

320330
PyObject *
321-
PyException_GetCause(PyObject *self) {
322-
PyObject *cause = ((PyBaseExceptionObject *)self)->cause;
331+
PyException_GetCause(PyObject *self)
332+
{
333+
PyObject *cause = _PyBaseExceptionObject_cast(self)->cause;
323334
Py_XINCREF(cause);
324335
return cause;
325336
}
@@ -328,13 +339,15 @@ PyException_GetCause(PyObject *self) {
328339
void
329340
PyException_SetCause(PyObject *self, PyObject *cause)
330341
{
331-
((PyBaseExceptionObject *)self)->suppress_context = 1;
332-
Py_XSETREF(((PyBaseExceptionObject *)self)->cause, cause);
342+
PyBaseExceptionObject *base_self = _PyBaseExceptionObject_cast(self);
343+
base_self->suppress_context = 1;
344+
Py_XSETREF(base_self->cause, cause);
333345
}
334346

335347
PyObject *
336-
PyException_GetContext(PyObject *self) {
337-
PyObject *context = ((PyBaseExceptionObject *)self)->context;
348+
PyException_GetContext(PyObject *self)
349+
{
350+
PyObject *context = _PyBaseExceptionObject_cast(self)->context;
338351
Py_XINCREF(context);
339352
return context;
340353
}
@@ -343,14 +356,15 @@ PyException_GetContext(PyObject *self) {
343356
void
344357
PyException_SetContext(PyObject *self, PyObject *context)
345358
{
346-
Py_XSETREF(((PyBaseExceptionObject *)self)->context, context);
359+
Py_XSETREF(_PyBaseExceptionObject_cast(self)->context, context);
347360
}
348361

349362
#undef PyExceptionClass_Name
350363

351364
const char *
352365
PyExceptionClass_Name(PyObject *ob)
353366
{
367+
assert(PyExceptionClass_Check(ob));
354368
return ((PyTypeObject*)ob)->tp_name;
355369
}
356370

‎Objects/genobject.c

Copy file name to clipboardExpand all lines: Objects/genobject.c
+9-9Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -512,15 +512,15 @@ _gen_throw(PyGenObject *gen, int close_on_genexit,
512512
}
513513

514514
PyErr_Restore(typ, val, tb);
515-
/* XXX It seems like we shouldn't have to check not equal to Py_None
516-
here because exc_type should only ever be a class. But not including
517-
this check was causing crashes on certain tests e.g. on Fedora. */
518-
if (gen->gi_exc_state.exc_type && gen->gi_exc_state.exc_type != Py_None) {
519-
Py_INCREF(gen->gi_exc_state.exc_type);
520-
Py_XINCREF(gen->gi_exc_state.exc_value);
521-
Py_XINCREF(gen->gi_exc_state.exc_traceback);
522-
_PyErr_ChainExceptions(gen->gi_exc_state.exc_type,
523-
gen->gi_exc_state.exc_value, gen->gi_exc_state.exc_traceback);
515+
516+
_PyErr_StackItem *gi_exc_state = &gen->gi_exc_state;
517+
if (gi_exc_state->exc_type != NULL && gi_exc_state->exc_type != Py_None) {
518+
Py_INCREF(gi_exc_state->exc_type);
519+
Py_XINCREF(gi_exc_state->exc_value);
520+
Py_XINCREF(gi_exc_state->exc_traceback);
521+
_PyErr_ChainExceptions(gi_exc_state->exc_type,
522+
gi_exc_state->exc_value,
523+
gi_exc_state->exc_traceback);
524524
}
525525
return gen_send_ex(gen, Py_None, 1, 0);
526526

‎Python/errors.c

Copy file name to clipboardExpand all lines: Python/errors.c
+11-1Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,8 @@ _PyErr_SetObject(PyThreadState *tstate, PyObject *exception, PyObject *value)
107107
if (exception != NULL &&
108108
!PyExceptionClass_Check(exception)) {
109109
_PyErr_Format(tstate, PyExc_SystemError,
110-
"exception %R not a BaseException subclass",
110+
"_PyErr_SetObject: "
111+
"exception %R is not a BaseException subclass",
111112
exception);
112113
return;
113114
}
@@ -484,6 +485,15 @@ _PyErr_ChainExceptions(PyObject *exc, PyObject *val, PyObject *tb)
484485
return;
485486

486487
PyThreadState *tstate = _PyThreadState_GET();
488+
489+
if (!PyExceptionClass_Check(exc)) {
490+
_PyErr_Format(tstate, PyExc_SystemError,
491+
"_PyErr_ChainExceptions: "
492+
"exception %R is not a BaseException subclass",
493+
exc);
494+
return;
495+
}
496+
487497
if (_PyErr_Occurred(tstate)) {
488498
PyObject *exc2, *val2, *tb2;
489499
_PyErr_Fetch(tstate, &exc2, &val2, &tb2);

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.