* [PATCH v1 01/13] perf script: Fix metric_evlist leak in script_find_metrics
2026-06-23 5:35 [PATCH v1 00/13] perf python: Fix python extension bugs and memory leaks Ian Rogers
@ 2026-06-23 5:35 ` Ian Rogers
2026-06-23 5:35 ` [PATCH v1 02/13] perf stat: Fix evsel_list leak in cmd_stat Ian Rogers
` (11 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Ian Rogers @ 2026-06-23 5:35 UTC (permalink / raw)
To: acme, namhyung
Cc: adrian.hunter, alice.mei.rogers, dapeng1.mi, james.clark, leo.yan,
linux-kernel, linux-perf-users, mingo, peterz, tmricht,
Ian Rogers
Fix a memory leak in script_find_metrics() where metric_evlist is leaked
when returning early on error paths.
Assisted-by: Antigravity:gemini-3.1-pro
Fixes: 3622990efaab ("perf script: Change metric format to use json metrics")
Signed-off-by: Ian Rogers <irogers@google.com>
---
tools/perf/builtin-script.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 47afd8cdc2b7..6b69e982ba62 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -2275,8 +2275,8 @@ static int script_find_metrics(const struct pmu_metric *pm,
}
pr_debug("Found metric '%s' whose evsels match those of in the perf data\n",
pm->metric_name);
- evlist__put(metric_evlist);
out:
+ evlist__put(metric_evlist);
return 0;
}
--
2.55.0.rc0.786.g65d90a0328-goog
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH v1 02/13] perf stat: Fix evsel_list leak in cmd_stat
2026-06-23 5:35 [PATCH v1 00/13] perf python: Fix python extension bugs and memory leaks Ian Rogers
2026-06-23 5:35 ` [PATCH v1 01/13] perf script: Fix metric_evlist leak in script_find_metrics Ian Rogers
@ 2026-06-23 5:35 ` Ian Rogers
2026-06-23 5:35 ` [PATCH v1 03/13] perf top: Fix sb_evlist leak Ian Rogers
` (10 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Ian Rogers @ 2026-06-23 5:35 UTC (permalink / raw)
To: acme, namhyung
Cc: adrian.hunter, alice.mei.rogers, dapeng1.mi, james.clark, leo.yan,
linux-kernel, linux-perf-users, mingo, peterz, tmricht,
Ian Rogers
Fix a memory leak in cmd_stat() where evsel_list is leaked if an error
occurs while opening the output file.
Assisted-by: Antigravity:gemini-3.1-pro
Fixes: 361c99a661a7 ("perf evsel: Introduce perf_evlist")
Signed-off-by: Ian Rogers <irogers@google.com>
---
tools/perf/builtin-stat.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 3f897b2e8638..7cb6ea937e87 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -2718,7 +2718,8 @@ int cmd_stat(int argc, const char **argv)
output = fopen(output_name, mode);
if (!output) {
perror("failed to create output file");
- return -1;
+ status = -1;
+ goto out;
}
if (!stat_config.json_output) {
clock_gettime(CLOCK_REALTIME, &tm);
@@ -2729,7 +2730,8 @@ int cmd_stat(int argc, const char **argv)
output = fdopen(output_fd, mode);
if (!output) {
perror("Failed opening logfd");
- return -errno;
+ status = -errno;
+ goto out;
}
}
@@ -2738,7 +2740,8 @@ int cmd_stat(int argc, const char **argv)
parse_options_usage(stat_usage, stat_options, "o", 1);
parse_options_usage(NULL, stat_options, "log-fd", 0);
parse_options_usage(NULL, stat_options, "interval-clear", 0);
- return -1;
+ status = -1;
+ goto out;
}
stat_config.output = output;
--
2.55.0.rc0.786.g65d90a0328-goog
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH v1 03/13] perf top: Fix sb_evlist leak
2026-06-23 5:35 [PATCH v1 00/13] perf python: Fix python extension bugs and memory leaks Ian Rogers
2026-06-23 5:35 ` [PATCH v1 01/13] perf script: Fix metric_evlist leak in script_find_metrics Ian Rogers
2026-06-23 5:35 ` [PATCH v1 02/13] perf stat: Fix evsel_list leak in cmd_stat Ian Rogers
@ 2026-06-23 5:35 ` Ian Rogers
2026-06-23 5:35 ` [PATCH v1 04/13] perf python: Fix memory leak in pyrf_evlist__get_pollfd Ian Rogers
` (9 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Ian Rogers @ 2026-06-23 5:35 UTC (permalink / raw)
To: acme, namhyung
Cc: adrian.hunter, alice.mei.rogers, dapeng1.mi, james.clark, leo.yan,
linux-kernel, linux-perf-users, mingo, peterz, tmricht,
Ian Rogers
Fix a memory leak in cmd_top() where top.sb_evlist was not freed if
evlist__add_bpf_sb_event() fails. Note that evlist__start_sb_thread() and
evlist__stop_sb_thread() take ownership of the evlist and free it, so
we must only free it if we fail before starting the thread.
Assisted-by: Antigravity:gemini-3.1-pro
Fixes: b38d85ef49cf ("perf bpf: Decouple creating the evlist from adding the SB event")
Signed-off-by: Ian Rogers <irogers@google.com>
---
tools/perf/builtin-top.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 5933c46ee137..abc74b8ab759 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -1881,6 +1881,7 @@ int cmd_top(int argc, const char **argv)
if (evlist__add_bpf_sb_event(top.sb_evlist, &host_env)) {
pr_err("Couldn't ask for PERF_RECORD_BPF_EVENT side band events.\n.");
status = -EINVAL;
+ evlist__put(top.sb_evlist);
goto out_put_evlist;
}
}
--
2.55.0.rc0.786.g65d90a0328-goog
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH v1 04/13] perf python: Fix memory leak in pyrf_evlist__get_pollfd
2026-06-23 5:35 [PATCH v1 00/13] perf python: Fix python extension bugs and memory leaks Ian Rogers
` (2 preceding siblings ...)
2026-06-23 5:35 ` [PATCH v1 03/13] perf top: Fix sb_evlist leak Ian Rogers
@ 2026-06-23 5:35 ` Ian Rogers
2026-06-23 5:35 ` [PATCH v1 05/13] perf synthetic-events: Fix uninitialized pthread_join Ian Rogers
` (8 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Ian Rogers @ 2026-06-23 5:35 UTC (permalink / raw)
To: acme, namhyung
Cc: adrian.hunter, alice.mei.rogers, dapeng1.mi, james.clark, leo.yan,
linux-kernel, linux-perf-users, mingo, peterz, tmricht,
Ian Rogers
Fix a Python list object leak in pyrf_evlist__get_pollfd() by adding
a missing Py_DECREF on the error exit path.
Assisted-by: Antigravity:gemini-3.1-pro
Fixes: 877108e42b1b ("perf tools: Initial python binding")
Signed-off-by: Ian Rogers <irogers@google.com>
---
tools/perf/util/python.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index 11e1f39c1bea..21e8b5a23a1c 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -2843,6 +2843,7 @@ static PyObject *pyrf_evlist__get_pollfd(struct pyrf_evlist *pevlist,
return list;
free_list:
+ Py_DECREF(list);
return PyErr_NoMemory();
}
--
2.55.0.rc0.786.g65d90a0328-goog
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH v1 05/13] perf synthetic-events: Fix uninitialized pthread_join
2026-06-23 5:35 [PATCH v1 00/13] perf python: Fix python extension bugs and memory leaks Ian Rogers
` (3 preceding siblings ...)
2026-06-23 5:35 ` [PATCH v1 04/13] perf python: Fix memory leak in pyrf_evlist__get_pollfd Ian Rogers
@ 2026-06-23 5:35 ` Ian Rogers
2026-06-23 5:35 ` [PATCH v1 06/13] perf data: Fix directory file descriptor leak in perf_data__switch Ian Rogers
` (7 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Ian Rogers @ 2026-06-23 5:35 UTC (permalink / raw)
To: acme, namhyung
Cc: adrian.hunter, alice.mei.rogers, dapeng1.mi, james.clark, leo.yan,
linux-kernel, linux-perf-users, mingo, peterz, tmricht,
Ian Rogers
In perf_event__synthesize_threads(), fix an uninitialized pthread_join()
call when thread creation fails by only joining the successfully
created threads.
Assisted-by: Antigravity:gemini-3.1-pro
Fixes: 340b47f510bb ("perf top: Implement multithreading for perf_event__synthesize_threads")
Signed-off-by: Ian Rogers <irogers@google.com>
---
tools/perf/util/synthetic-events.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tools/perf/util/synthetic-events.c b/tools/perf/util/synthetic-events.c
index b75f9dcf4dbf..35de41ad14d3 100644
--- a/tools/perf/util/synthetic-events.c
+++ b/tools/perf/util/synthetic-events.c
@@ -1104,8 +1104,8 @@ int perf_event__synthesize_threads(const struct perf_tool *tool,
}
err = 0;
out_join:
- for (i = 0; i < thread_nr; i++)
- pthread_join(synthesize_threads[i], NULL);
+ for (j = 0; j < i; j++)
+ pthread_join(synthesize_threads[j], NULL);
free(args);
free_threads:
free(synthesize_threads);
--
2.55.0.rc0.786.g65d90a0328-goog
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH v1 06/13] perf data: Fix directory file descriptor leak in perf_data__switch
2026-06-23 5:35 [PATCH v1 00/13] perf python: Fix python extension bugs and memory leaks Ian Rogers
` (4 preceding siblings ...)
2026-06-23 5:35 ` [PATCH v1 05/13] perf synthetic-events: Fix uninitialized pthread_join Ian Rogers
@ 2026-06-23 5:35 ` Ian Rogers
2026-06-23 5:35 ` [PATCH v1 07/13] perf test: Fix skiplist leak in cmd_test Ian Rogers
` (6 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Ian Rogers @ 2026-06-23 5:35 UTC (permalink / raw)
To: acme, namhyung
Cc: adrian.hunter, alice.mei.rogers, dapeng1.mi, james.clark, leo.yan,
linux-kernel, linux-perf-users, mingo, peterz, tmricht,
Ian Rogers
Fix a file descriptor leak in perf_data__switch() when running in
directory mode. By substituting perf_data__close() for
perf_data_file__close(), any thread-local directory files are properly
closed during file rotation.
Assisted-by: Antigravity:gemini-3.1-pro
Fixes: 040f9915e99e ("perf data: Add perf_data_file__switch() helper")
Signed-off-by: Ian Rogers <irogers@google.com>
---
tools/perf/util/data.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c
index 33fd1b82019e..32d4d908ad38 100644
--- a/tools/perf/util/data.c
+++ b/tools/perf/util/data.c
@@ -472,8 +472,7 @@ int perf_data__switch(struct perf_data *data,
pr_warning("Failed to rename %s to %s\n", data->path, *new_filepath);
if (!at_exit) {
- perf_data_file__close(&data->file);
- data->open = false;
+ perf_data__close(data);
ret = perf_data__open(data);
if (ret < 0)
goto out;
--
2.55.0.rc0.786.g65d90a0328-goog
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH v1 07/13] perf test: Fix skiplist leak in cmd_test
2026-06-23 5:35 [PATCH v1 00/13] perf python: Fix python extension bugs and memory leaks Ian Rogers
` (5 preceding siblings ...)
2026-06-23 5:35 ` [PATCH v1 06/13] perf data: Fix directory file descriptor leak in perf_data__switch Ian Rogers
@ 2026-06-23 5:35 ` Ian Rogers
2026-06-23 5:35 ` [PATCH v1 08/13] perf python: Check counts_values size in set_values Ian Rogers
` (5 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Ian Rogers @ 2026-06-23 5:35 UTC (permalink / raw)
To: acme, namhyung
Cc: adrian.hunter, alice.mei.rogers, dapeng1.mi, james.clark, leo.yan,
linux-kernel, linux-perf-users, mingo, peterz, tmricht,
Ian Rogers
Fix a memory leak in cmd_test() where skiplist was not freed on
exit paths.
Assisted-by: Antigravity:gemini-3.1-pro
Fixes: 2ae828786c65 ("perf test: Allow skipping tests")
Signed-off-by: Ian Rogers <irogers@google.com>
---
tools/perf/tests/builtin-test.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 7e75f590f225..cf5625cf4f11 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -1781,9 +1781,12 @@ int cmd_test(int argc, const char **argv)
rlimit__bump_memlock();
suites = build_suites();
- if (!suites)
+ if (!suites) {
+ intlist__delete(skiplist);
return errno ? -errno : -ENOMEM;
+ }
ret = __cmd_test(suites, argc, argv, skiplist);
free(suites);
+ intlist__delete(skiplist);
return ret;
}
--
2.55.0.rc0.786.g65d90a0328-goog
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH v1 08/13] perf python: Check counts_values size in set_values
2026-06-23 5:35 [PATCH v1 00/13] perf python: Fix python extension bugs and memory leaks Ian Rogers
` (6 preceding siblings ...)
2026-06-23 5:35 ` [PATCH v1 07/13] perf test: Fix skiplist leak in cmd_test Ian Rogers
@ 2026-06-23 5:35 ` Ian Rogers
2026-06-23 5:35 ` [PATCH v1 09/13] perf python: Validate CPU and thread maps in pyrf_evsel__open Ian Rogers
` (4 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Ian Rogers @ 2026-06-23 5:35 UTC (permalink / raw)
To: acme, namhyung
Cc: adrian.hunter, alice.mei.rogers, dapeng1.mi, james.clark, leo.yan,
linux-kernel, linux-perf-users, mingo, peterz, tmricht,
Ian Rogers
The set_values function incorrectly assumed the list contained exactly
5 elements. Add a check to prevent out-of-bounds access.
Fixes: 877108e42b1b ("perf tools: Initial python binding")
Signed-off-by: Ian Rogers <irogers@google.com>
---
tools/perf/util/python.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index 21e8b5a23a1c..f9398bc30a80 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -1913,6 +1913,11 @@ static int pyrf_counts_values_set_values(struct pyrf_counts_values *self, PyObje
}
size = PyList_Size(list);
+ if (size != 5) {
+ PyErr_SetString(PyExc_ValueError, "List must have exactly 5 entries");
+ return -1;
+ }
+
for (Py_ssize_t i = 0; i < size; i++) {
item = PyList_GetItem(list, i);
if (!PyLong_Check(item)) {
--
2.55.0.rc0.786.g65d90a0328-goog
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH v1 09/13] perf python: Validate CPU and thread maps in pyrf_evsel__open
2026-06-23 5:35 [PATCH v1 00/13] perf python: Fix python extension bugs and memory leaks Ian Rogers
` (7 preceding siblings ...)
2026-06-23 5:35 ` [PATCH v1 08/13] perf python: Check counts_values size in set_values Ian Rogers
@ 2026-06-23 5:35 ` Ian Rogers
2026-06-23 5:35 ` [PATCH v1 10/13] perf python: Validate attribute setters in pyrf_evsel Ian Rogers
` (3 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Ian Rogers @ 2026-06-23 5:35 UTC (permalink / raw)
To: acme, namhyung
Cc: adrian.hunter, alice.mei.rogers, dapeng1.mi, james.clark, leo.yan,
linux-kernel, linux-perf-users, mingo, peterz, tmricht,
Ian Rogers
Add explicit Py_TYPE checks to ensure the arguments passed are
actually of the correct pyrf_thread_map and pyrf_cpu_map types.
Fixes: 877108e42b1b ("perf tools: Initial python binding")
Signed-off-by: Ian Rogers <irogers@google.com>
---
tools/perf/util/python.c | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index f9398bc30a80..62f404c40d8d 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -2096,11 +2096,21 @@ static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel,
&pcpus, &pthreads, &group, &inherit))
return NULL;
- if (pthreads != NULL && pthreads != Py_None)
+ if (pthreads != NULL && pthreads != Py_None) {
+ if (Py_TYPE(pthreads) != &pyrf_thread_map__type) {
+ PyErr_SetString(PyExc_TypeError, "threads must be a thread_map");
+ return NULL;
+ }
threads = ((struct pyrf_thread_map *)pthreads)->threads;
+ }
- if (pcpus != NULL && pcpus != Py_None)
+ if (pcpus != NULL && pcpus != Py_None) {
+ if (Py_TYPE(pcpus) != &pyrf_cpu_map__type) {
+ PyErr_SetString(PyExc_TypeError, "cpus must be a cpu_map");
+ return NULL;
+ }
cpus = ((struct pyrf_cpu_map *)pcpus)->cpus;
+ }
evsel->core.attr.inherit = inherit;
/*
--
2.55.0.rc0.786.g65d90a0328-goog
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH v1 10/13] perf python: Validate attribute setters in pyrf_evsel
2026-06-23 5:35 [PATCH v1 00/13] perf python: Fix python extension bugs and memory leaks Ian Rogers
` (8 preceding siblings ...)
2026-06-23 5:35 ` [PATCH v1 09/13] perf python: Validate CPU and thread maps in pyrf_evsel__open Ian Rogers
@ 2026-06-23 5:35 ` Ian Rogers
2026-06-23 5:35 ` [PATCH v1 11/13] perf python: Zero initialize perf_data in pyrf_data__init Ian Rogers
` (2 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Ian Rogers @ 2026-06-23 5:35 UTC (permalink / raw)
To: acme, namhyung
Cc: adrian.hunter, alice.mei.rogers, dapeng1.mi, james.clark, leo.yan,
linux-kernel, linux-perf-users, mingo, peterz, tmricht,
Ian Rogers
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@google.com>
---
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 62f404c40d8d..e277c89b8347 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -2284,6 +2284,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;
@@ -2295,11 +2300,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)
@@ -2314,11 +2329,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)
@@ -2333,11 +2358,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)
@@ -2352,11 +2387,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)
@@ -2380,11 +2425,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)
@@ -2399,11 +2454,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.786.g65d90a0328-goog
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH v1 11/13] perf python: Zero initialize perf_data in pyrf_data__init
2026-06-23 5:35 [PATCH v1 00/13] perf python: Fix python extension bugs and memory leaks Ian Rogers
` (9 preceding siblings ...)
2026-06-23 5:35 ` [PATCH v1 10/13] perf python: Validate attribute setters in pyrf_evsel Ian Rogers
@ 2026-06-23 5:35 ` Ian Rogers
2026-06-23 5:35 ` [PATCH v1 12/13] perf python: Add thread uninitialized checks Ian Rogers
2026-06-23 5:35 ` [PATCH v1 13/13] perf python: Fix MetricGroup return type in perf.pyi Ian Rogers
12 siblings, 0 replies; 14+ messages in thread
From: Ian Rogers @ 2026-06-23 5:35 UTC (permalink / raw)
To: acme, namhyung
Cc: adrian.hunter, alice.mei.rogers, dapeng1.mi, james.clark, leo.yan,
linux-kernel, linux-perf-users, mingo, peterz, tmricht,
Ian Rogers
Replace path clearing with memset so the entire struct is zeroed,
preventing uninitialized fields from causing errors later.
Fixes: 4cd0142f7dec ("perf python: Add wrapper for perf_data file abstraction")
Signed-off-by: Ian Rogers <irogers@google.com>
---
tools/perf/util/python.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index e277c89b8347..03b4e8809107 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -3607,7 +3607,7 @@ static int pyrf_data__init(struct pyrf_data *pdata, PyObject *args, PyObject *kw
if (pdata->data.open)
perf_data__close(&pdata->data);
free((char *)pdata->data.path);
- pdata->data.path = NULL;
+ memset(&pdata->data, 0, sizeof(pdata->data));
if (fd != -1) {
struct stat st;
--
2.55.0.rc0.786.g65d90a0328-goog
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH v1 12/13] perf python: Add thread uninitialized checks
2026-06-23 5:35 [PATCH v1 00/13] perf python: Fix python extension bugs and memory leaks Ian Rogers
` (10 preceding siblings ...)
2026-06-23 5:35 ` [PATCH v1 11/13] perf python: Zero initialize perf_data in pyrf_data__init Ian Rogers
@ 2026-06-23 5:35 ` Ian Rogers
2026-06-23 5:35 ` [PATCH v1 13/13] perf python: Fix MetricGroup return type in perf.pyi Ian Rogers
12 siblings, 0 replies; 14+ messages in thread
From: Ian Rogers @ 2026-06-23 5:35 UTC (permalink / raw)
To: acme, namhyung
Cc: adrian.hunter, alice.mei.rogers, dapeng1.mi, james.clark, leo.yan,
linux-kernel, linux-perf-users, mingo, peterz, tmricht,
Ian Rogers
Add CHECK_INITIALIZED checks to the thread attribute getters
(get_pid, get_tid, get_ppid) to prevent crashes if they are accessed
before being properly initialized.
Fixes: 3b96bf7af60d ("perf python: Add python session abstraction wrapping perf's session")
Signed-off-by: Ian Rogers <irogers@google.com>
---
tools/perf/util/python.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index 03b4e8809107..70f985ad3dd2 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -3743,16 +3743,19 @@ static PyMethodDef pyrf_thread__methods[] = {
static PyObject *pyrf_thread__get_pid(struct pyrf_thread *pthread, void *closure __maybe_unused)
{
+ CHECK_INITIALIZED(pthread->thread, "thread");
return PyLong_FromLong(thread__pid(pthread->thread));
}
static PyObject *pyrf_thread__get_tid(struct pyrf_thread *pthread, void *closure __maybe_unused)
{
+ CHECK_INITIALIZED(pthread->thread, "thread");
return PyLong_FromLong(thread__tid(pthread->thread));
}
static PyObject *pyrf_thread__get_ppid(struct pyrf_thread *pthread, void *closure __maybe_unused)
{
+ CHECK_INITIALIZED(pthread->thread, "thread");
return PyLong_FromLong(thread__ppid(pthread->thread));
}
--
2.55.0.rc0.786.g65d90a0328-goog
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH v1 13/13] perf python: Fix MetricGroup return type in perf.pyi
2026-06-23 5:35 [PATCH v1 00/13] perf python: Fix python extension bugs and memory leaks Ian Rogers
` (11 preceding siblings ...)
2026-06-23 5:35 ` [PATCH v1 12/13] perf python: Add thread uninitialized checks Ian Rogers
@ 2026-06-23 5:35 ` Ian Rogers
12 siblings, 0 replies; 14+ messages in thread
From: Ian Rogers @ 2026-06-23 5:35 UTC (permalink / raw)
To: acme, namhyung
Cc: adrian.hunter, alice.mei.rogers, dapeng1.mi, james.clark, leo.yan,
linux-kernel, linux-perf-users, mingo, peterz, tmricht,
Ian Rogers
The metrics() function can return a dictionary where the value is either
a string or a list of strings, so the type signature in the stub file
should be Union[str, List[str]].
Signed-off-by: Ian Rogers <irogers@google.com>
---
tools/perf/python/perf.pyi | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tools/perf/python/perf.pyi b/tools/perf/python/perf.pyi
index f266c9baffd0..58b0b3ed819d 100644
--- a/tools/perf/python/perf.pyi
+++ b/tools/perf/python/perf.pyi
@@ -1,5 +1,5 @@
"""Type stubs for the perf Python module."""
-from typing import Callable, Dict, List, Optional, Any, Iterator
+from typing import Callable, Dict, List, Optional, Any, Iterator, Union
def config_get(name: str) -> Optional[str]:
"""Get a configuration value from perf config.
@@ -12,7 +12,7 @@ def config_get(name: str) -> Optional[str]:
"""
...
-def metrics() -> List[Dict[str, str]]:
+def metrics() -> List[Dict[str, Union[str, List[str]]]]:
"""Get a list of available metrics.
Returns:
--
2.55.0.rc0.786.g65d90a0328-goog
^ permalink raw reply related [flat|nested] 14+ messages in thread