diff options
author | Steve Dower <steve.dower@python.org> | 2019-11-28 16:46:11 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-11-28 16:46:11 (GMT) |
commit | bea33f5e1db6e4a554919a82894f44568576e979 (patch) | |
tree | 37789378933d7091eb0012d6ad3277aa8685a979 /Python | |
parent | 02519f75d15b063914a11351da30178ca4ceb54b (diff) | |
download | cpython-bea33f5e1db6e4a554919a82894f44568576e979.zip cpython-bea33f5e1db6e4a554919a82894f44568576e979.tar.gz cpython-bea33f5e1db6e4a554919a82894f44568576e979.tar.bz2 |
bpo-38920: Add audit hooks for when sys.excepthook and sys.unraisable hooks are invoked (GH-17392)
Also fixes some potential segfaults in unraisable hook handling.
Diffstat (limited to 'Python')
-rw-r--r-- | Python/errors.c | 70 | ||||
-rw-r--r-- | Python/pythonrun.c | 8 | ||||
-rw-r--r-- | Python/sysmodule.c | 4 |
3 files changed, 50 insertions, 32 deletions
diff --git a/Python/errors.c b/Python/errors.c index 1783084..d65707e 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -1391,43 +1391,53 @@ _PyErr_WriteUnraisableMsg(const char *err_msg_str, PyObject *obj) } } + PyObject *hook_args = make_unraisable_hook_args( + tstate, exc_type, exc_value, exc_tb, err_msg, obj); + if (hook_args == NULL) { + err_msg_str = ("Exception ignored on building " + "sys.unraisablehook arguments"); + goto error; + } + _Py_IDENTIFIER(unraisablehook); PyObject *hook = _PySys_GetObjectId(&PyId_unraisablehook); - if (hook != NULL && hook != Py_None) { - PyObject *hook_args; - - hook_args = make_unraisable_hook_args(tstate, exc_type, exc_value, - exc_tb, err_msg, obj); - if (hook_args != NULL) { - PyObject *res = _PyObject_CallOneArg(hook, hook_args); - Py_DECREF(hook_args); - if (res != NULL) { - Py_DECREF(res); - goto done; - } - - err_msg_str = "Exception ignored in sys.unraisablehook"; - } - else { - err_msg_str = ("Exception ignored on building " - "sys.unraisablehook arguments"); - } + if (hook == NULL) { + Py_DECREF(hook_args); + goto default_hook; + } - Py_XDECREF(err_msg); - err_msg = PyUnicode_FromString(err_msg_str); - if (err_msg == NULL) { - PyErr_Clear(); - } + if (PySys_Audit("sys.unraisablehook", "OO", hook, hook_args) < 0) { + Py_DECREF(hook_args); + err_msg_str = "Exception ignored in audit hook"; + obj = NULL; + goto error; + } - /* sys.unraisablehook failed: log its error using default hook */ - Py_XDECREF(exc_type); - Py_XDECREF(exc_value); - Py_XDECREF(exc_tb); - _PyErr_Fetch(tstate, &exc_type, &exc_value, &exc_tb); + if (hook == Py_None) { + Py_DECREF(hook_args); + goto default_hook; + } - obj = hook; + PyObject *res = _PyObject_CallOneArg(hook, hook_args); + Py_DECREF(hook_args); + if (res != NULL) { + Py_DECREF(res); + goto done; } + /* sys.unraisablehook failed: log its error using default hook */ + obj = hook; + err_msg_str = NULL; + +error: + /* err_msg_str and obj have been updated and we have a new exception */ + Py_XSETREF(err_msg, PyUnicode_FromString(err_msg_str ? + err_msg_str : "Exception ignored in sys.unraisablehook")); + Py_XDECREF(exc_type); + Py_XDECREF(exc_value); + Py_XDECREF(exc_tb); + _PyErr_Fetch(tstate, &exc_type, &exc_value, &exc_tb); + default_hook: /* Call the default unraisable hook (ignore failure) */ (void)write_unraisable_exc(tstate, exc_type, exc_value, exc_tb, diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 77a95ce..b68a0b5 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -695,6 +695,14 @@ _PyErr_PrintEx(PyThreadState *tstate, int set_sys_last_vars) } } hook = _PySys_GetObjectId(&PyId_excepthook); + if (PySys_Audit("sys.excepthook", "OOOO", hook ? hook : Py_None, + exception, v, tb) < 0) { + if (PyErr_ExceptionMatches(PyExc_RuntimeError)) { + PyErr_Clear(); + goto done; + } + _PyErr_WriteUnraisableMsg("in audit hook", NULL); + } if (hook) { PyObject* stack[3]; PyObject *result; diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 30c7e98..78b9d22 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -323,8 +323,8 @@ PySys_AddAuditHook(Py_AuditHookFunction hook, void *userData) /* Cannot invoke hooks until we are initialized */ if (runtime->initialized) { if (PySys_Audit("sys.addaudithook", NULL) < 0) { - if (_PyErr_ExceptionMatches(tstate, PyExc_Exception)) { - /* We do not report errors derived from Exception */ + if (_PyErr_ExceptionMatches(tstate, PyExc_RuntimeError)) { + /* We do not report errors derived from RuntimeError */ _PyErr_Clear(tstate); return 0; } |