Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

libsubcmd: Don't free the usage string

Currently, commands which depend on 'parse_options_subcommand()' don't
show the usage string, and instead show '(null)'

$ ./perf sched
Usage: (null)

-D, --dump-raw-trace dump raw trace in ASCII
-f, --force don't complain, do it
-i, --input <file> input file name
-v, --verbose be more verbose (show symbol address, etc)

'parse_options_subcommand()' is generally expected to initialise the usage
string, with information in the passed 'subcommands[]' array

This behaviour was changed in:

230a7a71f92212e7 ("libsubcmd: Fix parse-options memory leak")

Where the generated usage string is deallocated, and usage[0] string is
reassigned as NULL.

As discussed in [1], free the allocated usage string in the main
function itself, and don't reset usage string to NULL in
parse_options_subcommand

With this change, the behaviour is restored.

$ ./perf sched
Usage: perf sched [<options>] {record|latency|map|replay|script|timehist}

-D, --dump-raw-trace dump raw trace in ASCII
-f, --force don't complain, do it
-i, --input <file> input file name
-v, --verbose be more verbose (show symbol address, etc)

[1]: https://lore.kernel.org/linux-perf-users/htq5vhx6piet4nuq2mmhk7fs2bhfykv52dbppwxmo3s7du2odf@styd27tioc6e/

Fixes: 230a7a71f92212e7 ("libsubcmd: Fix parse-options memory leak")
Suggested-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Aditya Gupta <adityag@linux.ibm.com>
Acked-by: Namhyung Kim <namhyung@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Athira Rajeev <atrajeev@linux.vnet.ibm.com>
Cc: Disha Goel <disgoel@linux.vnet.ibm.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kajol Jain <kjain@linux.ibm.com>
Cc: Madhavan Srinivasan <maddy@linux.ibm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Link: https://lore.kernel.org/r/20240904061836.55873-2-adityag@linux.ibm.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Aditya Gupta and committed by
Arnaldo Carvalho de Melo
1a5efc9e fa6cc3f9

+20 -5
+3 -5
tools/lib/subcmd/parse-options.c
··· 633 633 const char *const subcommands[], const char *usagestr[], int flags) 634 634 { 635 635 struct parse_opt_ctx_t ctx; 636 - char *buf = NULL; 637 636 638 637 /* build usage string if it's not provided */ 639 638 if (subcommands && !usagestr[0]) { 639 + char *buf = NULL; 640 + 640 641 astrcatf(&buf, "%s %s [<options>] {", subcmd_config.exec_name, argv[0]); 641 642 642 643 for (int i = 0; subcommands[i]; i++) { ··· 679 678 astrcatf(&error_buf, "unknown switch `%c'", *ctx.opt); 680 679 usage_with_options(usagestr, options); 681 680 } 682 - if (buf) { 683 - usagestr[0] = NULL; 684 - free(buf); 685 - } 681 + 686 682 return parse_options_end(&ctx); 687 683 } 688 684
+2
tools/perf/builtin-kmem.c
··· 2057 2057 2058 2058 out_delete: 2059 2059 perf_session__delete(session); 2060 + /* free usage string allocated by parse_options_subcommand */ 2061 + free((void *)kmem_usage[0]); 2060 2062 2061 2063 return ret; 2062 2064 }
+3
tools/perf/builtin-kvm.c
··· 2184 2184 else 2185 2185 usage_with_options(kvm_usage, kvm_options); 2186 2186 2187 + /* free usage string allocated by parse_options_subcommand */ 2188 + free((void *)kvm_usage[0]); 2189 + 2187 2190 return 0; 2188 2191 }
+3
tools/perf/builtin-kwork.c
··· 2519 2519 } else 2520 2520 usage_with_options(kwork_usage, kwork_options); 2521 2521 2522 + /* free usage string allocated by parse_options_subcommand */ 2523 + free((void *)kwork_usage[0]); 2524 + 2522 2525 return 0; 2523 2526 }
+3
tools/perf/builtin-lock.c
··· 2712 2712 usage_with_options(lock_usage, lock_options); 2713 2713 } 2714 2714 2715 + /* free usage string allocated by parse_options_subcommand */ 2716 + free((void *)lock_usage[0]); 2717 + 2715 2718 zfree(&lockhash_table); 2716 2719 return rc; 2717 2720 }
+3
tools/perf/builtin-mem.c
··· 546 546 else 547 547 usage_with_options(mem_usage, mem_options); 548 548 549 + /* free usage string allocated by parse_options_subcommand */ 550 + free((void *)mem_usage[0]); 551 + 549 552 return 0; 550 553 }
+3
tools/perf/builtin-sched.c
··· 3954 3954 usage_with_options(sched_usage, sched_options); 3955 3955 } 3956 3956 3957 + /* free usage string allocated by parse_options_subcommand */ 3958 + free((void *)sched_usage[0]); 3959 + 3957 3960 return 0; 3958 3961 }