bpo-35370: Add _PyEval_SetTrace() function (GH-18975)

* sys.settrace(), sys.setprofile() and _lsprof.Profiler.enable() now
  properly report PySys_Audit() error if "sys.setprofile" or
  "sys.settrace" audit event is denied.
* Add _PyEval_SetProfile() and _PyEval_SetTrace() function: similar
  to PyEval_SetProfile() and PyEval_SetTrace() but take a tstate
  parameter and return -1 on error.
* Add _PyObject_FastCallTstate() function.
This commit is contained in:
Victor Stinner 2020-03-13 16:39:12 +01:00 committed by GitHub
parent 9ee88cde1a
commit 309d7cc5df
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 156 additions and 65 deletions

View file

@ -4586,51 +4586,85 @@ maybe_call_line_trace(Py_tracefunc func, PyObject *obj,
return result;
}
int
_PyEval_SetProfile(PyThreadState *tstate, Py_tracefunc func, PyObject *arg)
{
assert(tstate != NULL);
/* The caller must hold the GIL */
assert(PyGILState_Check());
/* Call PySys_Audit() in the context of the current thread state,
even if tstate is not the current thread state. */
if (PySys_Audit("sys.setprofile", NULL) < 0) {
return -1;
}
PyObject *profileobj = tstate->c_profileobj;
tstate->c_profilefunc = NULL;
tstate->c_profileobj = NULL;
/* Must make sure that tracing is not ignored if 'profileobj' is freed */
tstate->use_tracing = tstate->c_tracefunc != NULL;
Py_XDECREF(profileobj);
Py_XINCREF(arg);
tstate->c_profileobj = arg;
tstate->c_profilefunc = func;
/* Flag that tracing or profiling is turned on */
tstate->use_tracing = (func != NULL) || (tstate->c_tracefunc != NULL);
return 0;
}
void
PyEval_SetProfile(Py_tracefunc func, PyObject *arg)
{
if (PySys_Audit("sys.setprofile", NULL) < 0) {
return;
PyThreadState *tstate = _PyThreadState_GET();
(void)_PyEval_SetProfile(tstate, func, arg);
}
int
_PyEval_SetTrace(PyThreadState *tstate, Py_tracefunc func, PyObject *arg)
{
assert(tstate != NULL);
/* The caller must hold the GIL */
assert(PyGILState_Check());
/* Call PySys_Audit() in the context of the current thread state,
even if tstate is not the current thread state. */
if (PySys_Audit("sys.settrace", NULL) < 0) {
return -1;
}
PyThreadState *tstate = _PyThreadState_GET();
PyObject *temp = tstate->c_profileobj;
struct _ceval_runtime_state *ceval = &tstate->interp->runtime->ceval;
PyObject *traceobj = tstate->c_traceobj;
ceval->tracing_possible += (func != NULL) - (tstate->c_tracefunc != NULL);
tstate->c_tracefunc = NULL;
tstate->c_traceobj = NULL;
/* Must make sure that profiling is not ignored if 'traceobj' is freed */
tstate->use_tracing = (tstate->c_profilefunc != NULL);
Py_XDECREF(traceobj);
Py_XINCREF(arg);
tstate->c_profilefunc = NULL;
tstate->c_profileobj = NULL;
/* Must make sure that tracing is not ignored if 'temp' is freed */
tstate->use_tracing = tstate->c_tracefunc != NULL;
Py_XDECREF(temp);
tstate->c_profilefunc = func;
tstate->c_profileobj = arg;
tstate->c_traceobj = arg;
tstate->c_tracefunc = func;
/* Flag that tracing or profiling is turned on */
tstate->use_tracing = (func != NULL) || (tstate->c_tracefunc != NULL);
tstate->use_tracing = ((func != NULL)
|| (tstate->c_profilefunc != NULL));
return 0;
}
void
PyEval_SetTrace(Py_tracefunc func, PyObject *arg)
{
if (PySys_Audit("sys.settrace", NULL) < 0) {
return;
}
_PyRuntimeState *runtime = &_PyRuntime;
PyThreadState *tstate = _PyRuntimeState_GetThreadState(runtime);
PyObject *temp = tstate->c_traceobj;
runtime->ceval.tracing_possible += (func != NULL) - (tstate->c_tracefunc != NULL);
Py_XINCREF(arg);
tstate->c_tracefunc = NULL;
tstate->c_traceobj = NULL;
/* Must make sure that profiling is not ignored if 'temp' is freed */
tstate->use_tracing = tstate->c_profilefunc != NULL;
Py_XDECREF(temp);
tstate->c_tracefunc = func;
tstate->c_traceobj = arg;
/* Flag that tracing or profiling is turned on */
tstate->use_tracing = ((func != NULL)
|| (tstate->c_profilefunc != NULL));
PyThreadState *tstate = _PyThreadState_GET();
(void)_PyEval_SetTrace(tstate, func, arg);
}
void
_PyEval_SetCoroutineOriginTrackingDepth(PyThreadState *tstate, int new_depth)
{