[PATCH v2 10/16] perf python: Validate attribute setters in pyrf_evsel

From: Ian Rogers

Date: Wed Jun 24 2026 - 01:16:59 EST


If val is NULL when setting an attribute, PyErr_SetString should be
called as deleting the attribute isn't supported. In addition, ensure
PyErr_Occurred is checked before setting the attribute to avoid setting
a garbage value.

Fixes: 877108e42b1b ("perf tools: Initial python binding")
Signed-off-by: Ian Rogers <irogers@xxxxxxxxxx>
---
tools/perf/util/python.c | 89 ++++++++++++++++++++++++++++++++++------
1 file changed, 77 insertions(+), 12 deletions(-)

diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index 4bf37e2afb18..657b054f5e51 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -2296,6 +2296,11 @@ static int pyrf_evsel__set_tracking(PyObject *self, PyObject *val, void *closure

CHECK_INITIALIZED_INT(pevsel->evsel, "evsel");

+ if (val == NULL) {
+ PyErr_SetString(PyExc_TypeError, "cannot delete attribute");
+ return -1;
+ }
+
is_true = PyObject_IsTrue(val);
if (is_true < 0)
return -1;
@@ -2307,11 +2312,21 @@ static int pyrf_evsel__set_tracking(PyObject *self, PyObject *val, void *closure
static int pyrf_evsel__set_attr_config(PyObject *self, PyObject *val, void *closure __maybe_unused)
{
struct pyrf_evsel *pevsel = (void *)self;
+ unsigned long long new_val;

CHECK_INITIALIZED_INT(pevsel->evsel, "evsel");

- pevsel->evsel->core.attr.config = PyLong_AsUnsignedLongLong(val);
- return PyErr_Occurred() ? -1 : 0;
+ if (val == NULL) {
+ PyErr_SetString(PyExc_TypeError, "cannot delete attribute");
+ return -1;
+ }
+
+ new_val = PyLong_AsUnsignedLongLong(val);
+ if (PyErr_Occurred())
+ return -1;
+
+ pevsel->evsel->core.attr.config = new_val;
+ return 0;
}

static PyObject *pyrf_evsel__get_attr_config(PyObject *self, void *closure __maybe_unused)
@@ -2326,11 +2341,21 @@ static PyObject *pyrf_evsel__get_attr_config(PyObject *self, void *closure __may
static int pyrf_evsel__set_attr_read_format(PyObject *self, PyObject *val, void *closure __maybe_unused)
{
struct pyrf_evsel *pevsel = (void *)self;
+ unsigned long long new_val;

CHECK_INITIALIZED_INT(pevsel->evsel, "evsel");

- pevsel->evsel->core.attr.read_format = PyLong_AsUnsignedLongLong(val);
- return PyErr_Occurred() ? -1 : 0;
+ if (val == NULL) {
+ PyErr_SetString(PyExc_TypeError, "cannot delete attribute");
+ return -1;
+ }
+
+ new_val = PyLong_AsUnsignedLongLong(val);
+ if (PyErr_Occurred())
+ return -1;
+
+ pevsel->evsel->core.attr.read_format = new_val;
+ return 0;
}

static PyObject *pyrf_evsel__get_attr_read_format(PyObject *self, void *closure __maybe_unused)
@@ -2345,11 +2370,21 @@ static PyObject *pyrf_evsel__get_attr_read_format(PyObject *self, void *closure
static int pyrf_evsel__set_attr_sample_period(PyObject *self, PyObject *val, void *closure __maybe_unused)
{
struct pyrf_evsel *pevsel = (void *)self;
+ unsigned long long new_val;

CHECK_INITIALIZED_INT(pevsel->evsel, "evsel");

- pevsel->evsel->core.attr.sample_period = PyLong_AsUnsignedLongLong(val);
- return PyErr_Occurred() ? -1 : 0;
+ if (val == NULL) {
+ PyErr_SetString(PyExc_TypeError, "cannot delete attribute");
+ return -1;
+ }
+
+ new_val = PyLong_AsUnsignedLongLong(val);
+ if (PyErr_Occurred())
+ return -1;
+
+ pevsel->evsel->core.attr.sample_period = new_val;
+ return 0;
}

static PyObject *pyrf_evsel__get_attr_sample_period(PyObject *self, void *closure __maybe_unused)
@@ -2364,11 +2399,21 @@ static PyObject *pyrf_evsel__get_attr_sample_period(PyObject *self, void *closur
static int pyrf_evsel__set_attr_sample_type(PyObject *self, PyObject *val, void *closure __maybe_unused)
{
struct pyrf_evsel *pevsel = (void *)self;
+ unsigned long long new_val;

CHECK_INITIALIZED_INT(pevsel->evsel, "evsel");

- pevsel->evsel->core.attr.sample_type = PyLong_AsUnsignedLongLong(val);
- return PyErr_Occurred() ? -1 : 0;
+ if (val == NULL) {
+ PyErr_SetString(PyExc_TypeError, "cannot delete attribute");
+ return -1;
+ }
+
+ new_val = PyLong_AsUnsignedLongLong(val);
+ if (PyErr_Occurred())
+ return -1;
+
+ pevsel->evsel->core.attr.sample_type = new_val;
+ return 0;
}

static PyObject *pyrf_evsel__get_attr_sample_type(PyObject *self, void *closure __maybe_unused)
@@ -2392,11 +2437,21 @@ static PyObject *pyrf_evsel__get_attr_size(PyObject *self, void *closure __maybe
static int pyrf_evsel__set_attr_type(PyObject *self, PyObject *val, void *closure __maybe_unused)
{
struct pyrf_evsel *pevsel = (void *)self;
+ unsigned long new_val;

CHECK_INITIALIZED_INT(pevsel->evsel, "evsel");

- pevsel->evsel->core.attr.type = PyLong_AsUnsignedLong(val);
- return PyErr_Occurred() ? -1 : 0;
+ if (val == NULL) {
+ PyErr_SetString(PyExc_TypeError, "cannot delete attribute");
+ return -1;
+ }
+
+ new_val = PyLong_AsUnsignedLong(val);
+ if (PyErr_Occurred())
+ return -1;
+
+ pevsel->evsel->core.attr.type = new_val;
+ return 0;
}

static PyObject *pyrf_evsel__get_attr_type(PyObject *self, void *closure __maybe_unused)
@@ -2411,11 +2466,21 @@ static PyObject *pyrf_evsel__get_attr_type(PyObject *self, void *closure __maybe
static int pyrf_evsel__set_attr_wakeup_events(PyObject *self, PyObject *val, void *closure __maybe_unused)
{
struct pyrf_evsel *pevsel = (void *)self;
+ unsigned long new_val;

CHECK_INITIALIZED_INT(pevsel->evsel, "evsel");

- pevsel->evsel->core.attr.wakeup_events = PyLong_AsUnsignedLong(val);
- return PyErr_Occurred() ? -1 : 0;
+ if (val == NULL) {
+ PyErr_SetString(PyExc_TypeError, "cannot delete attribute");
+ return -1;
+ }
+
+ new_val = PyLong_AsUnsignedLong(val);
+ if (PyErr_Occurred())
+ return -1;
+
+ pevsel->evsel->core.attr.wakeup_events = new_val;
+ return 0;
}

static PyObject *pyrf_evsel__get_attr_wakeup_events(PyObject *self, void *closure __maybe_unused)
--
2.55.0.rc0.799.gd6f94ed593-goog