perf metricgroup: Fix metric expression copy leaks

metricgroup__copy_metric_events() allocates a new metric expression and
duplicates metric_name before linking the expression into the destination
metric event.

Free new_expr when strdup() fails, and free the duplicated metric_name on
the later error paths.

Fixes: b85a4d61d3 ("perf metric: Allow modifiers on metrics")
Signed-off-by: Yu Peng <pengyu@kylinos.cn>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
This commit is contained in:
Yu Peng
2026-06-02 16:11:04 +08:00
committed by Namhyung Kim
parent c25a46dc63
commit ef3af1df4f

View File

@@ -1693,8 +1693,10 @@ int metricgroup__copy_metric_events(struct evlist *evlist, struct cgroup *cgrp,
new_expr->metric_expr = old_expr->metric_expr;
new_expr->metric_threshold = old_expr->metric_threshold;
new_expr->metric_name = strdup(old_expr->metric_name);
if (!new_expr->metric_name)
if (!new_expr->metric_name) {
free(new_expr);
return -ENOMEM;
}
new_expr->metric_unit = old_expr->metric_unit;
new_expr->runtime = old_expr->runtime;
@@ -1707,6 +1709,7 @@ int metricgroup__copy_metric_events(struct evlist *evlist, struct cgroup *cgrp,
alloc_size = sizeof(*new_expr->metric_refs);
new_expr->metric_refs = calloc(nr + 1, alloc_size);
if (!new_expr->metric_refs) {
zfree(&new_expr->metric_name);
free(new_expr);
return -ENOMEM;
}
@@ -1723,6 +1726,7 @@ int metricgroup__copy_metric_events(struct evlist *evlist, struct cgroup *cgrp,
alloc_size = sizeof(*new_expr->metric_events);
new_expr->metric_events = calloc(nr + 1, alloc_size);
if (!new_expr->metric_events) {
zfree(&new_expr->metric_name);
zfree(&new_expr->metric_refs);
free(new_expr);
return -ENOMEM;
@@ -1733,6 +1737,7 @@ int metricgroup__copy_metric_events(struct evlist *evlist, struct cgroup *cgrp,
evsel = old_expr->metric_events[idx];
evsel = evlist__find_evsel(evlist, evsel->core.idx);
if (evsel == NULL) {
zfree(&new_expr->metric_name);
zfree(&new_expr->metric_events);
zfree(&new_expr->metric_refs);
free(new_expr);