[PATCH AUTOSEL 4.19 117/177] perf tools: Splice events onto evlist even on error

From: Sasha Levin
Date: Tue Dec 10 2019 - 16:34:55 EST


From: Ian Rogers <irogers@xxxxxxxxxx>

[ Upstream commit 8e8714c3d157568b7a769917a5e05573bbaf5af0 ]

If event parsing fails the event list is leaked, instead splice the list
onto the out result and let the caller cleanup.

An example input for parse_events found by libFuzzer that reproduces
this memory leak is 'm{'.

Signed-off-by: Ian Rogers <irogers@xxxxxxxxxx>
Acked-by: Jiri Olsa <jolsa@xxxxxxxxxx>
Cc: Adrian Hunter <adrian.hunter@xxxxxxxxx>
Cc: Alexander Shishkin <alexander.shishkin@xxxxxxxxxxxxxxx>
Cc: Alexei Starovoitov <ast@xxxxxxxxxx>
Cc: Andi Kleen <ak@xxxxxxxxxxxxxxx>
Cc: Daniel Borkmann <daniel@xxxxxxxxxxxxx>
Cc: Jin Yao <yao.jin@xxxxxxxxxxxxxxx>
Cc: John Garry <john.garry@xxxxxxxxxx>
Cc: Kan Liang <kan.liang@xxxxxxxxxxxxxxx>
Cc: Mark Rutland <mark.rutland@xxxxxxx>
Cc: Martin KaFai Lau <kafai@xxxxxx>
Cc: Namhyung Kim <namhyung@xxxxxxxxxx>
Cc: Peter Zijlstra <peterz@xxxxxxxxxxxxx>
Cc: Song Liu <songliubraving@xxxxxx>
Cc: Stephane Eranian <eranian@xxxxxxxxxx>
Cc: Yonghong Song <yhs@xxxxxx>
Cc: bpf@xxxxxxxxxxxxxxx
Cc: clang-built-linux@xxxxxxxxxxxxxxxx
Cc: netdev@xxxxxxxxxxxxxxx
Link: http://lore.kernel.org/lkml/20191025180827.191916-5-irogers@xxxxxxxxxx
Signed-off-by: Arnaldo Carvalho de Melo <acme@xxxxxxxxxx>
Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>
---
tools/perf/util/parse-events.c | 17 +++++++++++------
1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 1a7c76d2baa80..7ea1a230e89d0 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -1843,15 +1843,20 @@ int parse_events(struct perf_evlist *evlist, const char *str,

ret = parse_events__scanner(str, &parse_state, PE_START_EVENTS);
perf_pmu__parse_cleanup();
+
+ if (!ret && list_empty(&parse_state.list)) {
+ WARN_ONCE(true, "WARNING: event parser found nothing\n");
+ return -1;
+ }
+
+ /*
+ * Add list to the evlist even with errors to allow callers to clean up.
+ */
+ perf_evlist__splice_list_tail(evlist, &parse_state.list);
+
if (!ret) {
struct perf_evsel *last;

- if (list_empty(&parse_state.list)) {
- WARN_ONCE(true, "WARNING: event parser found nothing\n");
- return -1;
- }
-
- perf_evlist__splice_list_tail(evlist, &parse_state.list);
evlist->nr_groups += parse_state.nr_groups;
last = perf_evlist__last(evlist);
last->cmdline_group_boundary = true;
--
2.20.1