Skip to content

Commit 1b65c46

Browse files
committed
Don't leak references and don't return BRANCH event wrappers to the user
1 parent dc5a9d5 commit 1b65c46

File tree

1 file changed

+51
-38
lines changed

1 file changed

+51
-38
lines changed

Python/instrumentation.c

Lines changed: 51 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1400,43 +1400,6 @@ _Py_call_instrumentation_instruction(PyThreadState *tstate, _PyInterpreterFrame*
14001400
return next_opcode;
14011401
}
14021402

1403-
static PyObject *make_branch_handler(int tool_id, PyObject *handler, bool taken);
1404-
1405-
static PyObject *exchange_callables(int tool_id, int event_id, PyObject *obj)
1406-
{
1407-
PyInterpreterState *is = _PyInterpreterState_GET();
1408-
return _Py_atomic_exchange_ptr(&is->monitoring_callables[tool_id][event_id],
1409-
Py_XNewRef(obj));
1410-
}
1411-
1412-
PyObject *
1413-
_PyMonitoring_RegisterCallback(int tool_id, int event_id, PyObject *obj)
1414-
{
1415-
assert(0 <= tool_id && tool_id < PY_MONITORING_TOOL_IDS);
1416-
assert(0 <= event_id && event_id < _PY_MONITORING_EVENTS);
1417-
if (event_id != PY_MONITORING_EVENT_BRANCH) {
1418-
return exchange_callables(tool_id, event_id, Py_XNewRef(obj));
1419-
}
1420-
PyObject *taken, *not_taken;
1421-
if (obj == NULL) {
1422-
taken = NULL;
1423-
not_taken = NULL;
1424-
}
1425-
else {
1426-
taken = make_branch_handler(tool_id, obj, true);
1427-
if (taken == NULL) {
1428-
return NULL;
1429-
}
1430-
not_taken = make_branch_handler(tool_id, obj, false);
1431-
if (not_taken == NULL) {
1432-
Py_DECREF(taken);
1433-
return NULL;
1434-
}
1435-
}
1436-
Py_XDECREF(exchange_callables(tool_id, PY_MONITORING_EVENT_BRANCH_TAKEN, taken));
1437-
return exchange_callables(tool_id, PY_MONITORING_EVENT_BRANCH_NOT_TAKEN, not_taken);
1438-
}
1439-
14401403
static void
14411404
initialize_tools(PyCodeObject *code)
14421405
{
@@ -2798,12 +2761,18 @@ typedef struct _PyLegacyBranchEventHandler {
27982761
int tool_id;
27992762
} _PyLegacyBranchEventHandler;
28002763

2764+
static void
2765+
dealloc_branch_handler(_PyLegacyBranchEventHandler *self)
2766+
{
2767+
Py_CLEAR(self->handler);
2768+
PyObject_Free((PyObject *)self);
2769+
}
28012770

28022771
static PyTypeObject _PyLegacyBranchEventHandler_Type = {
28032772
PyVarObject_HEAD_INIT(&PyType_Type, 0)
28042773
"sys.monitoring.branch_event_handler",
28052774
sizeof(_PyLegacyBranchEventHandler),
2806-
.tp_dealloc = (destructor)PyObject_Free,
2775+
.tp_dealloc = (destructor)dealloc_branch_handler,
28072776
.tp_vectorcall_offset = offsetof(_PyLegacyBranchEventHandler, vectorcall),
28082777
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
28092778
Py_TPFLAGS_HAVE_VECTORCALL | Py_TPFLAGS_DISALLOW_INSTANTIATION,
@@ -2863,3 +2832,47 @@ static PyObject *make_branch_handler(int tool_id, PyObject *handler, bool taken)
28632832
callback->tool_id = tool_id;
28642833
return (PyObject *)callback;
28652834
}
2835+
2836+
static PyObject *exchange_callables(int tool_id, int event_id, PyObject *obj)
2837+
{
2838+
PyInterpreterState *is = _PyInterpreterState_GET();
2839+
return _Py_atomic_exchange_ptr(&is->monitoring_callables[tool_id][event_id],
2840+
Py_XNewRef(obj));
2841+
}
2842+
2843+
PyObject *
2844+
_PyMonitoring_RegisterCallback(int tool_id, int event_id, PyObject *obj)
2845+
{
2846+
assert(0 <= tool_id && tool_id < PY_MONITORING_TOOL_IDS);
2847+
assert(0 <= event_id && event_id < _PY_MONITORING_EVENTS);
2848+
PyObject *res;
2849+
if (event_id == PY_MONITORING_EVENT_BRANCH) {
2850+
PyObject *taken, *not_taken;
2851+
if (obj == NULL) {
2852+
taken = NULL;
2853+
not_taken = NULL;
2854+
}
2855+
else {
2856+
taken = make_branch_handler(tool_id, obj, true);
2857+
if (taken == NULL) {
2858+
return NULL;
2859+
}
2860+
not_taken = make_branch_handler(tool_id, obj, false);
2861+
if (not_taken == NULL) {
2862+
Py_DECREF(taken);
2863+
return NULL;
2864+
}
2865+
}
2866+
Py_XDECREF(exchange_callables(tool_id, PY_MONITORING_EVENT_BRANCH_TAKEN, taken));
2867+
res = exchange_callables(tool_id, PY_MONITORING_EVENT_BRANCH_NOT_TAKEN, not_taken);
2868+
}
2869+
else {
2870+
res = exchange_callables(tool_id, event_id, Py_XNewRef(obj));
2871+
}
2872+
if (res != NULL && Py_TYPE(res) == &_PyLegacyBranchEventHandler_Type) {
2873+
_PyLegacyBranchEventHandler *wrapper = (_PyLegacyBranchEventHandler *)res;
2874+
res = Py_NewRef(wrapper->handler);
2875+
Py_DECREF(wrapper);
2876+
}
2877+
return res;
2878+
}

0 commit comments

Comments
 (0)