]> www.infradead.org Git - users/hch/misc.git/commitdiff
perf tools kvm: Add missed memory allocation check and free
authorDapeng Mi <dapeng1.mi@linux.intel.com>
Fri, 19 Sep 2025 02:16:54 +0000 (10:16 +0800)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Thu, 2 Oct 2025 18:30:21 +0000 (15:30 -0300)
Current code allocates rec_argv[] array, but doesn't check if the
allocation is successful and explicitly free the rec_argv[] array.

Add them back.

Signed-off-by: Dapeng Mi <dapeng1.mi@linux.intel.com>
Acked-by: Namhyung Kim <namhyung@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/builtin-kvm.c

index 7b15b4a705e467d6dfb9d1b5ebf0c81ca48ab6b1..9813f1eb56f9b29cc424562e897f27f897b25f3b 100644 (file)
@@ -1638,9 +1638,11 @@ exit:
 
 #define STRDUP_FAIL_EXIT(s)            \
        ({      char *_p;               \
-       _p = strdup(s);         \
-               if (!_p)                \
-                       return -ENOMEM; \
+               _p = strdup(s);         \
+               if (!_p) {              \
+                       ret = -ENOMEM;  \
+                       goto EXIT;      \
+               }                       \
                _p;                     \
        })
 
@@ -1688,7 +1690,7 @@ kvm_events_record(struct perf_kvm_stat *kvm, int argc, const char **argv)
                rec_argv[i] = STRDUP_FAIL_EXIT(record_args[i]);
 
        for (j = 0; j < events_tp_size; j++) {
-               rec_argv[i++] = "-e";
+               rec_argv[i++] = STRDUP_FAIL_EXIT("-e");
                rec_argv[i++] = STRDUP_FAIL_EXIT(kvm_events_tp[j]);
        }
 
@@ -1696,7 +1698,7 @@ kvm_events_record(struct perf_kvm_stat *kvm, int argc, const char **argv)
        rec_argv[i++] = STRDUP_FAIL_EXIT(kvm->file_name);
 
        for (j = 1; j < (unsigned int)argc; j++, i++)
-               rec_argv[i] = argv[j];
+               rec_argv[i] = STRDUP_FAIL_EXIT(argv[j]);
 
        set_option_flag(record_options, 'e', "event", PARSE_OPT_HIDDEN);
        set_option_flag(record_options, 0, "filter", PARSE_OPT_HIDDEN);
@@ -1719,7 +1721,13 @@ kvm_events_record(struct perf_kvm_stat *kvm, int argc, const char **argv)
        set_option_flag(record_options, 0, "transaction", PARSE_OPT_DISABLED);
 
        record_usage = kvm_stat_record_usage;
-       return cmd_record(i, rec_argv);
+       ret = cmd_record(i, rec_argv);
+
+EXIT:
+       for (i = 0; i < rec_argc; i++)
+               free((void *)rec_argv[i]);
+       free(rec_argv);
+       return ret;
 }
 
 static int
@@ -2006,52 +2014,79 @@ static int __cmd_record(const char *file_name, int argc, const char **argv)
 
        rec_argc = argc + 2;
        rec_argv = calloc(rec_argc + 1, sizeof(char *));
-       rec_argv[i++] = strdup("record");
-       rec_argv[i++] = strdup("-o");
-       rec_argv[i++] = strdup(file_name);
+       if (!rec_argv)
+               return -ENOMEM;
+
+       rec_argv[i++] = STRDUP_FAIL_EXIT("record");
+       rec_argv[i++] = STRDUP_FAIL_EXIT("-o");
+       rec_argv[i++] = STRDUP_FAIL_EXIT(file_name);
        for (j = 1; j < argc; j++, i++)
-               rec_argv[i] = argv[j];
+               rec_argv[i] = STRDUP_FAIL_EXIT(argv[j]);
 
        BUG_ON(i != rec_argc);
 
-       return cmd_record(i, rec_argv);
+       ret = cmd_record(i, rec_argv);
+
+EXIT:
+       for (i = 0; i < rec_argc; i++)
+               free((void *)rec_argv[i]);
+       free(rec_argv);
+       return ret;
 }
 
 static int __cmd_report(const char *file_name, int argc, const char **argv)
 {
-       int rec_argc, i = 0, j;
+       int rec_argc, i = 0, j, ret;
        const char **rec_argv;
 
        rec_argc = argc + 2;
        rec_argv = calloc(rec_argc + 1, sizeof(char *));
-       rec_argv[i++] = strdup("report");
-       rec_argv[i++] = strdup("-i");
-       rec_argv[i++] = strdup(file_name);
+       if (!rec_argv)
+               return -ENOMEM;
+
+       rec_argv[i++] = STRDUP_FAIL_EXIT("report");
+       rec_argv[i++] = STRDUP_FAIL_EXIT("-i");
+       rec_argv[i++] = STRDUP_FAIL_EXIT(file_name);
        for (j = 1; j < argc; j++, i++)
-               rec_argv[i] = argv[j];
+               rec_argv[i] = STRDUP_FAIL_EXIT(argv[j]);
 
        BUG_ON(i != rec_argc);
 
-       return cmd_report(i, rec_argv);
+       ret = cmd_report(i, rec_argv);
+
+EXIT:
+       for (i = 0; i < rec_argc; i++)
+               free((void *)rec_argv[i]);
+       free(rec_argv);
+       return ret;
 }
 
 static int
 __cmd_buildid_list(const char *file_name, int argc, const char **argv)
 {
-       int rec_argc, i = 0, j;
+       int rec_argc, i = 0, j, ret;
        const char **rec_argv;
 
        rec_argc = argc + 2;
        rec_argv = calloc(rec_argc + 1, sizeof(char *));
-       rec_argv[i++] = strdup("buildid-list");
-       rec_argv[i++] = strdup("-i");
-       rec_argv[i++] = strdup(file_name);
+       if (!rec_argv)
+               return -ENOMEM;
+
+       rec_argv[i++] = STRDUP_FAIL_EXIT("buildid-list");
+       rec_argv[i++] = STRDUP_FAIL_EXIT("-i");
+       rec_argv[i++] = STRDUP_FAIL_EXIT(file_name);
        for (j = 1; j < argc; j++, i++)
-               rec_argv[i] = argv[j];
+               rec_argv[i] = STRDUP_FAIL_EXIT(argv[j]);
 
        BUG_ON(i != rec_argc);
 
-       return cmd_buildid_list(i, rec_argv);
+       ret = cmd_buildid_list(i, rec_argv);
+
+EXIT:
+       for (i = 0; i < rec_argc; i++)
+               free((void *)rec_argv[i]);
+       free(rec_argv);
+       return ret;
 }
 
 int cmd_kvm(int argc, const char **argv)