mirror of
https://github.com/python/cpython.git
synced 2025-08-22 09:45:06 +00:00
Fix segfaults when running test_exceptions with coverage tracing, caused by wrongly defining Exception.__context__ as a T_OBJECT structmember which does not set the member to NULL on None assignment, and generally does not do type checks. This could be used to crash the interpreter by setting any object to __context__. The same applies to __cause__. Also document the PyException_* functions.
This commit is contained in:
parent
71095ea4ce
commit
ab6f2f6eb6
4 changed files with 114 additions and 10 deletions
|
@ -250,11 +250,67 @@ BaseException_set_tb(PyBaseExceptionObject *self, PyObject *tb)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
BaseException_get_context(PyObject *self) {
|
||||
PyObject *res = PyException_GetContext(self);
|
||||
if (res) return res; /* new reference already returned above */
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static int
|
||||
BaseException_set_context(PyObject *self, PyObject *arg) {
|
||||
if (arg == NULL) {
|
||||
PyErr_SetString(PyExc_TypeError, "__context__ may not be deleted");
|
||||
return -1;
|
||||
} else if (arg == Py_None) {
|
||||
arg = NULL;
|
||||
} else if (!PyExceptionInstance_Check(arg)) {
|
||||
PyErr_SetString(PyExc_TypeError, "exception context must be None "
|
||||
"or derive from BaseException");
|
||||
return -1;
|
||||
} else {
|
||||
/* PyException_SetContext steals this reference */
|
||||
Py_INCREF(arg);
|
||||
}
|
||||
PyException_SetContext(self, arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
BaseException_get_cause(PyObject *self) {
|
||||
PyObject *res = PyException_GetCause(self);
|
||||
if (res) return res; /* new reference already returned above */
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static int
|
||||
BaseException_set_cause(PyObject *self, PyObject *arg) {
|
||||
if (arg == NULL) {
|
||||
PyErr_SetString(PyExc_TypeError, "__cause__ may not be deleted");
|
||||
return -1;
|
||||
} else if (arg == Py_None) {
|
||||
arg = NULL;
|
||||
} else if (!PyExceptionInstance_Check(arg)) {
|
||||
PyErr_SetString(PyExc_TypeError, "exception cause must be None "
|
||||
"or derive from BaseException");
|
||||
return -1;
|
||||
} else {
|
||||
/* PyException_SetCause steals this reference */
|
||||
Py_INCREF(arg);
|
||||
}
|
||||
PyException_SetCause(self, arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static PyGetSetDef BaseException_getset[] = {
|
||||
{"__dict__", (getter)BaseException_get_dict, (setter)BaseException_set_dict},
|
||||
{"args", (getter)BaseException_get_args, (setter)BaseException_set_args},
|
||||
{"__traceback__", (getter)BaseException_get_tb, (setter)BaseException_set_tb},
|
||||
{"__context__", (getter)BaseException_get_context,
|
||||
(setter)BaseException_set_context, PyDoc_STR("exception context")},
|
||||
{"__cause__", (getter)BaseException_get_cause,
|
||||
(setter)BaseException_set_cause, PyDoc_STR("exception cause")},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
|
@ -303,14 +359,6 @@ PyException_SetContext(PyObject *self, PyObject *context) {
|
|||
}
|
||||
|
||||
|
||||
static PyMemberDef BaseException_members[] = {
|
||||
{"__context__", T_OBJECT, offsetof(PyBaseExceptionObject, context), 0,
|
||||
PyDoc_STR("exception context")},
|
||||
{"__cause__", T_OBJECT, offsetof(PyBaseExceptionObject, cause), 0,
|
||||
PyDoc_STR("exception cause")},
|
||||
{NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
static PyTypeObject _PyExc_BaseException = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"BaseException", /*tp_name*/
|
||||
|
@ -341,7 +389,7 @@ static PyTypeObject _PyExc_BaseException = {
|
|||
0, /* tp_iter */
|
||||
0, /* tp_iternext */
|
||||
BaseException_methods, /* tp_methods */
|
||||
BaseException_members, /* tp_members */
|
||||
0, /* tp_members */
|
||||
BaseException_getset, /* tp_getset */
|
||||
0, /* tp_base */
|
||||
0, /* tp_dict */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue