perf header: Fix various error path memory leaks
authorIan Rogers <irogers@google.com>
Mon, 9 Oct 2023 18:39:19 +0000 (11:39 -0700)
committerNamhyung Kim <namhyung@kernel.org>
Thu, 12 Oct 2023 17:01:57 +0000 (10:01 -0700)
Memory leaks were detected by clang-tidy.

Signed-off-by: Ian Rogers <irogers@google.com>
Acked-by: Namhyung Kim <namhyung@kernel.org>
Cc: Ravi Bangoria <ravi.bangoria@amd.com>
Cc: Nick Desaulniers <ndesaulniers@google.com>
Cc: Yang Jihong <yangjihong1@huawei.com>
Cc: Huacai Chen <chenhuacai@kernel.org>
Cc: Nathan Chancellor <nathan@kernel.org>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: llvm@lists.linux.dev
Cc: Ming Wang <wangming01@loongson.cn>
Cc: Tom Rix <trix@redhat.com>
Cc: bpf@vger.kernel.org
Link: https://lore.kernel.org/r/20231009183920.200859-19-irogers@google.com
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
tools/perf/util/header.c

index d812e1e371a743d7dcc3afd720d372f25e60ad99..e86b9439ffee054a4088efc944b1b4b657f8d330 100644 (file)
@@ -2573,7 +2573,7 @@ error:
 static int process_cpu_topology(struct feat_fd *ff, void *data __maybe_unused)
 {
        u32 nr, i;
-       char *str;
+       char *str = NULL;
        struct strbuf sb;
        int cpu_nr = ff->ph->env.nr_cpus_avail;
        u64 size = 0;
@@ -2601,7 +2601,7 @@ static int process_cpu_topology(struct feat_fd *ff, void *data __maybe_unused)
                if (strbuf_add(&sb, str, strlen(str) + 1) < 0)
                        goto error;
                size += string_size(str);
-               free(str);
+               zfree(&str);
        }
        ph->env.sibling_cores = strbuf_detach(&sb, NULL);
 
@@ -2620,7 +2620,7 @@ static int process_cpu_topology(struct feat_fd *ff, void *data __maybe_unused)
                if (strbuf_add(&sb, str, strlen(str) + 1) < 0)
                        goto error;
                size += string_size(str);
-               free(str);
+               zfree(&str);
        }
        ph->env.sibling_threads = strbuf_detach(&sb, NULL);
 
@@ -2684,7 +2684,7 @@ static int process_cpu_topology(struct feat_fd *ff, void *data __maybe_unused)
                if (strbuf_add(&sb, str, strlen(str) + 1) < 0)
                        goto error;
                size += string_size(str);
-               free(str);
+               zfree(&str);
        }
        ph->env.sibling_dies = strbuf_detach(&sb, NULL);
 
@@ -2699,6 +2699,7 @@ static int process_cpu_topology(struct feat_fd *ff, void *data __maybe_unused)
 
 error:
        strbuf_release(&sb);
+       zfree(&str);
 free_cpu:
        zfree(&ph->env.cpu);
        return -1;
@@ -2736,10 +2737,9 @@ static int process_numa_topology(struct feat_fd *ff, void *data __maybe_unused)
                        goto error;
 
                n->map = perf_cpu_map__new(str);
+               free(str);
                if (!n->map)
                        goto error;
-
-               free(str);
        }
        ff->ph->env.nr_numa_nodes = nr;
        ff->ph->env.numa_nodes = nodes;
@@ -2913,10 +2913,10 @@ static int process_cache(struct feat_fd *ff, void *data __maybe_unused)
                return -1;
 
        for (i = 0; i < cnt; i++) {
-               struct cpu_cache_level c;
+               struct cpu_cache_level *c = &caches[i];
 
                #define _R(v)                                           \
-                       if (do_read_u32(ff, &c.v))\
+                       if (do_read_u32(ff, &c->v))                     \
                                goto out_free_caches;                   \
 
                _R(level)
@@ -2926,22 +2926,25 @@ static int process_cache(struct feat_fd *ff, void *data __maybe_unused)
                #undef _R
 
                #define _R(v)                                   \
-                       c.v = do_read_string(ff);               \
-                       if (!c.v)                               \
-                               goto out_free_caches;
+                       c->v = do_read_string(ff);              \
+                       if (!c->v)                              \
+                               goto out_free_caches;           \
 
                _R(type)
                _R(size)
                _R(map)
                #undef _R
-
-               caches[i] = c;
        }
 
        ff->ph->env.caches = caches;
        ff->ph->env.caches_cnt = cnt;
        return 0;
 out_free_caches:
+       for (i = 0; i < cnt; i++) {
+               free(caches[i].type);
+               free(caches[i].size);
+               free(caches[i].map);
+       }
        free(caches);
        return -1;
 }
@@ -3585,18 +3588,16 @@ static int perf_header__adds_write(struct perf_header *header,
                                   struct feat_copier *fc)
 {
        int nr_sections;
-       struct feat_fd ff;
+       struct feat_fd ff = {
+               .fd  = fd,
+               .ph = header,
+       };
        struct perf_file_section *feat_sec, *p;
        int sec_size;
        u64 sec_start;
        int feat;
        int err;
 
-       ff = (struct feat_fd){
-               .fd  = fd,
-               .ph = header,
-       };
-
        nr_sections = bitmap_weight(header->adds_features, HEADER_FEAT_BITS);
        if (!nr_sections)
                return 0;
@@ -3623,6 +3624,7 @@ static int perf_header__adds_write(struct perf_header *header,
        err = do_write(&ff, feat_sec, sec_size);
        if (err < 0)
                pr_debug("failed to write feature section\n");
+       free(ff.buf); /* TODO: added to silence clang-tidy. */
        free(feat_sec);
        return err;
 }
@@ -3630,11 +3632,11 @@ static int perf_header__adds_write(struct perf_header *header,
 int perf_header__write_pipe(int fd)
 {
        struct perf_pipe_file_header f_header;
-       struct feat_fd ff;
+       struct feat_fd ff = {
+               .fd = fd,
+       };
        int err;
 
-       ff = (struct feat_fd){ .fd = fd };
-
        f_header = (struct perf_pipe_file_header){
                .magic     = PERF_MAGIC,
                .size      = sizeof(f_header),
@@ -3645,7 +3647,7 @@ int perf_header__write_pipe(int fd)
                pr_debug("failed to write perf pipe header\n");
                return err;
        }
-
+       free(ff.buf);
        return 0;
 }
 
@@ -3658,11 +3660,12 @@ static int perf_session__do_write_header(struct perf_session *session,
        struct perf_file_attr   f_attr;
        struct perf_header *header = &session->header;
        struct evsel *evsel;
-       struct feat_fd ff;
+       struct feat_fd ff = {
+               .fd = fd,
+       };
        u64 attr_offset;
        int err;
 
-       ff = (struct feat_fd){ .fd = fd};
        lseek(fd, sizeof(f_header), SEEK_SET);
 
        evlist__for_each_entry(session->evlist, evsel) {
@@ -3670,6 +3673,7 @@ static int perf_session__do_write_header(struct perf_session *session,
                err = do_write(&ff, evsel->core.id, evsel->core.ids * sizeof(u64));
                if (err < 0) {
                        pr_debug("failed to write perf header\n");
+                       free(ff.buf);
                        return err;
                }
        }
@@ -3695,6 +3699,7 @@ static int perf_session__do_write_header(struct perf_session *session,
                err = do_write(&ff, &f_attr, sizeof(f_attr));
                if (err < 0) {
                        pr_debug("failed to write perf header attribute\n");
+                       free(ff.buf);
                        return err;
                }
        }
@@ -3705,8 +3710,10 @@ static int perf_session__do_write_header(struct perf_session *session,
 
        if (at_exit) {
                err = perf_header__adds_write(header, evlist, fd, fc);
-               if (err < 0)
+               if (err < 0) {
+                       free(ff.buf);
                        return err;
+               }
        }
 
        f_header = (struct perf_file_header){
@@ -3728,6 +3735,7 @@ static int perf_session__do_write_header(struct perf_session *session,
 
        lseek(fd, 0, SEEK_SET);
        err = do_write(&ff, &f_header, sizeof(f_header));
+       free(ff.buf);
        if (err < 0) {
                pr_debug("failed to write perf header\n");
                return err;