On Fri, Mar 13, 2015 at 12:51:54PM +0000, Wang Nan wrote:
> 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 <[email protected]>
> ---
>  tools/perf/builtin-report.c     |  2 +-

I think perf 'diff' and 'mem' commands also have same problem..

Thanks,
Namhyung


>  tools/perf/util/parse-options.c | 21 +++++++++++++++++++--
>  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 fb35034..2652e52 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)
>       OPT_STRING('w', "column-widths", &symbol_conf.col_width_list_str,
>                  "width[,width...]",
>                  "don't try to adjust column width, use these fixed values"),
> -     OPT_STRING('t', "field-separator", &symbol_conf.field_sep, "separator",
> +     OPT_STRING_NOEMPTY('t', "field-separator", &symbol_conf.field_sep, 
> "separator",
>                  "separator for columns, no spaces will be added between "
>                  "columns '.' is reserved."),
>       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 1457d66..01626be 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,
>  {
>       const char *s, *arg = NULL;
>       const int unset = flags & OPT_UNSET;
> +     int err;
>  
>       if (unset && p->opt)
>               return opterror(opt, "takes no value", flags);
> @@ -114,13 +115,29 @@ static int get_value(struct parse_opt_ctx_t *p,
>               return 0;
>  
>       case OPTION_STRING:
> +             err = 0;
>               if (unset)
>                       *(const char **)opt->value = NULL;
>               else if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
>                       *(const char **)opt->value = (const char *)opt->defval;
>               else
> -                     return get_arg(p, opt, flags, (const char 
> **)opt->value);
> -             return 0;
> +                     err = get_arg(p, opt, flags, (const char **)opt->value);
> +
> +             /* PARSE_OPT_NOEMPTY: Allow NULL but disallow empty string. */
> +             if (opt->flags & PARSE_OPT_NOEMPTY) {
> +                     const char *val = *(const char **)opt->value;
> +
> +                     if (!val)
> +                             return err;
> +
> +                     /* Similar to unset if we are given an empty string. */
> +                     if (val[0] == '\0') {
> +                             *(const char **)opt->value = NULL;
> +                             return 0;
> +                     }
> +             }
> +
> +             return err;
>  
>       case OPTION_CALLBACK:
>               if (unset)
> diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h
> index 97b153f..59561fd 100644
> --- a/tools/perf/util/parse-options.h
> +++ b/tools/perf/util/parse-options.h
> @@ -40,6 +40,7 @@ enum parse_opt_option_flags {
>       PARSE_OPT_LASTARG_DEFAULT = 16,
>       PARSE_OPT_DISABLED = 32,
>       PARSE_OPT_EXCLUSIVE = 64,
> +     PARSE_OPT_NOEMPTY  = 128,
>  };
>  
>  struct option;
> @@ -122,6 +123,7 @@ struct option {
>  #define OPT_LONG(s, l, v, h)        { .type = OPTION_LONG, .short_name = 
> (s), .long_name = (l), .value = check_vtype(v, long *), .help = (h) }
>  #define OPT_U64(s, l, v, h)         { .type = OPTION_U64, .short_name = (s), 
> .long_name = (l), .value = check_vtype(v, u64 *), .help = (h) }
>  #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) }
> +#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}
>  #define OPT_DATE(s, l, v, h) \
>       { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value 
> = (v), .argh = "time", .help = (h), .callback = parse_opt_approxidate_cb }
>  #define OPT_CALLBACK(s, l, v, a, h, f) \
> -- 
> 1.8.3.4
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to [email protected]
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to