diff options
author | Wang Nan <wangnan0@huawei.com> | 2015-03-13 08:51:54 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2015-03-19 12:53:28 -0400 |
commit | 0c8c20779c5d56b93b8cb4cd30ba129a927ab437 (patch) | |
tree | 834448d6d5be440844e1ba755e6cf3a5832dfec6 /tools | |
parent | 303cb89a6d708da9c24f6f3390ff68a2bd822a13 (diff) |
perf report: Don't allow empty argument for '-t'.
Without this patch, perf report cause segfault if pass "" as '-t':
$ perf report -t ""
# To display the perf.data header info, please use --header/--header-only options.
#
# Samples: 37 of event 'syscalls:sys_enter_write'
# Event count (approx.): 37
#
# Children SelfCommand Shared Object Symbol
Segmentation fault
Since -t is used to add field-separator for generate table, -t "" is
actually meanless. This patch defines a new OPT_STRING_NOEMPTY() option
generator to ensure user never pass empty string to that option.
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Acked-by: Namhyung Kim <namhyung@kernel.org>
Cc: pi3orama@163.com
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Zefan Li <lizefan@huawei.com>
Link: http://lkml.kernel.org/r/1426251114-198991-1-git-send-email-wangnan0@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/perf/builtin-report.c | 2 | ||||
-rw-r--r-- | tools/perf/util/parse-options.c | 21 | ||||
-rw-r--r-- | tools/perf/util/parse-options.h | 2 |
3 files changed, 22 insertions, 3 deletions
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 52f74e1367e9..0ae482689e3c 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c | |||
@@ -676,7 +676,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) | |||
676 | OPT_STRING('w', "column-widths", &symbol_conf.col_width_list_str, | 676 | OPT_STRING('w', "column-widths", &symbol_conf.col_width_list_str, |
677 | "width[,width...]", | 677 | "width[,width...]", |
678 | "don't try to adjust column width, use these fixed values"), | 678 | "don't try to adjust column width, use these fixed values"), |
679 | OPT_STRING('t', "field-separator", &symbol_conf.field_sep, "separator", | 679 | OPT_STRING_NOEMPTY('t', "field-separator", &symbol_conf.field_sep, "separator", |
680 | "separator for columns, no spaces will be added between " | 680 | "separator for columns, no spaces will be added between " |
681 | "columns '.' is reserved."), | 681 | "columns '.' is reserved."), |
682 | OPT_BOOLEAN('U', "hide-unresolved", &report.hide_unresolved, | 682 | OPT_BOOLEAN('U', "hide-unresolved", &report.hide_unresolved, |
diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c index 1457d6639b60..01626be2a8eb 100644 --- a/tools/perf/util/parse-options.c +++ b/tools/perf/util/parse-options.c | |||
@@ -37,6 +37,7 @@ static int get_value(struct parse_opt_ctx_t *p, | |||
37 | { | 37 | { |
38 | const char *s, *arg = NULL; | 38 | const char *s, *arg = NULL; |
39 | const int unset = flags & OPT_UNSET; | 39 | const int unset = flags & OPT_UNSET; |
40 | int err; | ||
40 | 41 | ||
41 | if (unset && p->opt) | 42 | if (unset && p->opt) |
42 | return opterror(opt, "takes no value", flags); | 43 | return opterror(opt, "takes no value", flags); |
@@ -114,13 +115,29 @@ static int get_value(struct parse_opt_ctx_t *p, | |||
114 | return 0; | 115 | return 0; |
115 | 116 | ||
116 | case OPTION_STRING: | 117 | case OPTION_STRING: |
118 | err = 0; | ||
117 | if (unset) | 119 | if (unset) |
118 | *(const char **)opt->value = NULL; | 120 | *(const char **)opt->value = NULL; |
119 | else if (opt->flags & PARSE_OPT_OPTARG && !p->opt) | 121 | else if (opt->flags & PARSE_OPT_OPTARG && !p->opt) |
120 | *(const char **)opt->value = (const char *)opt->defval; | 122 | *(const char **)opt->value = (const char *)opt->defval; |
121 | else | 123 | else |
122 | return get_arg(p, opt, flags, (const char **)opt->value); | 124 | err = get_arg(p, opt, flags, (const char **)opt->value); |
123 | return 0; | 125 | |
126 | /* PARSE_OPT_NOEMPTY: Allow NULL but disallow empty string. */ | ||
127 | if (opt->flags & PARSE_OPT_NOEMPTY) { | ||
128 | const char *val = *(const char **)opt->value; | ||
129 | |||
130 | if (!val) | ||
131 | return err; | ||
132 | |||
133 | /* Similar to unset if we are given an empty string. */ | ||
134 | if (val[0] == '\0') { | ||
135 | *(const char **)opt->value = NULL; | ||
136 | return 0; | ||
137 | } | ||
138 | } | ||
139 | |||
140 | return err; | ||
124 | 141 | ||
125 | case OPTION_CALLBACK: | 142 | case OPTION_CALLBACK: |
126 | if (unset) | 143 | if (unset) |
diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h index 97b153fb4999..59561fd86278 100644 --- a/tools/perf/util/parse-options.h +++ b/tools/perf/util/parse-options.h | |||
@@ -40,6 +40,7 @@ enum parse_opt_option_flags { | |||
40 | PARSE_OPT_LASTARG_DEFAULT = 16, | 40 | PARSE_OPT_LASTARG_DEFAULT = 16, |
41 | PARSE_OPT_DISABLED = 32, | 41 | PARSE_OPT_DISABLED = 32, |
42 | PARSE_OPT_EXCLUSIVE = 64, | 42 | PARSE_OPT_EXCLUSIVE = 64, |
43 | PARSE_OPT_NOEMPTY = 128, | ||
43 | }; | 44 | }; |
44 | 45 | ||
45 | struct option; | 46 | struct option; |
@@ -122,6 +123,7 @@ struct option { | |||
122 | #define OPT_LONG(s, l, v, h) { .type = OPTION_LONG, .short_name = (s), .long_name = (l), .value = check_vtype(v, long *), .help = (h) } | 123 | #define OPT_LONG(s, l, v, h) { .type = OPTION_LONG, .short_name = (s), .long_name = (l), .value = check_vtype(v, long *), .help = (h) } |
123 | #define OPT_U64(s, l, v, h) { .type = OPTION_U64, .short_name = (s), .long_name = (l), .value = check_vtype(v, u64 *), .help = (h) } | 124 | #define OPT_U64(s, l, v, h) { .type = OPTION_U64, .short_name = (s), .long_name = (l), .value = check_vtype(v, u64 *), .help = (h) } |
124 | #define OPT_STRING(s, l, v, a, h) { .type = OPTION_STRING, .short_name = (s), .long_name = (l), .value = check_vtype(v, const char **), (a), .help = (h) } | 125 | #define OPT_STRING(s, l, v, a, h) { .type = OPTION_STRING, .short_name = (s), .long_name = (l), .value = check_vtype(v, const char **), (a), .help = (h) } |
126 | #define OPT_STRING_NOEMPTY(s, l, v, a, h) { .type = OPTION_STRING, .short_name = (s), .long_name = (l), .value = check_vtype(v, const char **), (a), .help = (h), .flags = PARSE_OPT_NOEMPTY} | ||
125 | #define OPT_DATE(s, l, v, h) \ | 127 | #define OPT_DATE(s, l, v, h) \ |
126 | { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = "time", .help = (h), .callback = parse_opt_approxidate_cb } | 128 | { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = "time", .help = (h), .callback = parse_opt_approxidate_cb } |
127 | #define OPT_CALLBACK(s, l, v, a, h, f) \ | 129 | #define OPT_CALLBACK(s, l, v, a, h, f) \ |