He X wrote: > > The msgid argument is a null-terminated string. > > problem is that msgid is a empty pointer, not a pointer to a > NULL-terminated string. > > full backtrace: > > ``` > #0 0x00007ffff7fab65d in strcmp (l=0x0, r=0x7ffff7eff7df "Packaged by > %s\n") at src/string/strcmp.c:5 > #1 0x00007ffff7f51351 in __mo_lookup (p=0x7ffff7efa000, size=55838, s=0x0) > at src/locale/__mo_lookup.c:25 > #2 0x00007ffff7f51e14 in dcngettext (domainname=0x7ffff7ffe320 "tar", > msgid1=0x0, msgid2=0x0, n=1, category=5) at src/locale/dcngettext.c:211 > #3 0x00007ffff7f52204 in dgettext (domainname=0x0, msgid=0x0) at > src/locale/dcngettext.c:271 > #4 0x000055555558a63c in argp_args_usage (argp=argp@entry=0x7fffffffe740, > state=state@entry=0x7fffffffe8f0, levels=levels@entry=0x7fffffffe690, > advance=advance@entry=1, stream=stream@entry=0x5555555c5e20) at > argp-help.c:1415 > #5 0x000055555558bcdd in _help (argp=0x7fffffffe740, > state=state@entry=0x7fffffffe8f0, > stream=0x7ffff7ffb2a0 <f>, flags=flags@entry=634, > name=0x7fffffffed94 "tar") at argp-help.c:1640 > #6 0x000055555558ca08 in argp_state_help (state=state@entry=0x7fffffffe8f0, > stream=<optimized out>, flags=flags@entry=634) at argp-help.c:1741 > #7 0x000055555558d088 in argp_default_parser (key=<optimized out>, > arg=<optimized out>, state=0x7fffffffe8f0) at argp-parse.c:96 > #8 0x000055555558df89 in group_parse (arg=<optimized out>, key=63, > state=0x7fffffffe8f0, group=0x5555555c40b0) at argp-parse.c:234 > #9 parser_parse_opt (val=<optimized out>, opt=50331711, > parser=0x7fffffffe880) at argp-parse.c:749 > #10 parser_parse_next (arg_ebadkey=<synthetic pointer>, > parser=0x7fffffffe880) at argp-parse.c:860 > #11 argp_parse (argp=<optimized out>, argc=2, argv=<optimized out>, > flags=<optimized out>, end_index=0x7fffffffe9f0, input=0x5555555c3500 > <args>) > at argp-parse.c:928 > #12 0x000055555555d3b7 in decode_options (argv=0x7fffffffeb58, argc=2) at > tar.c:2312 > #13 main (argc=<optimized out>, argv=<optimized out>) at tar.c:2698 > ```
Thank you! With this stack trace, I'm fixing the issue as follows: 2019-01-05 Bruno Haible <br...@clisp.org> argp: Don't pass an invalid argument to dgettext(). Reported by He X <xw897002...@gmail.com>. * lib/argp.h (struct argp): Clarify that the args_doc field may be NULL. * lib/argp-help.c (argp_args_usage): Don't pass a NULL args_doc to dgettext(). diff --git a/lib/argp.h b/lib/argp.h index 317ac03..7aba887 100644 --- a/lib/argp.h +++ b/lib/argp.h @@ -69,6 +69,9 @@ typedef int error_t; extern "C" { #endif +/* Glibc documentation: + https://www.gnu.org/software/libc/manual/html_node/Argp.html */ + /* A description of a particular option. A pointer to an array of these is passed in the OPTIONS field of an argp structure. Each option entry can correspond to one long option and/or one short option; more @@ -236,9 +239,9 @@ struct argp ARGP_KEY_ definitions below. */ argp_parser_t parser; - /* A string describing what other arguments are wanted by this program. It - is only used by argp_usage to print the "Usage:" message. If it - contains newlines, the strings separated by them are considered + /* If non-NULL, a string describing what other arguments are wanted by this + program. It is only used by argp_usage to print the "Usage:" message. + If it contains newlines, the strings separated by them are considered alternative usage patterns, and printed on separate lines (lines after the first are prefix by " or: " instead of "Usage:"). */ const char *args_doc; diff --git a/lib/argp-help.c b/lib/argp-help.c index e5375a0..e5e97ec 100644 --- a/lib/argp-help.c +++ b/lib/argp-help.c @@ -1412,8 +1412,10 @@ argp_args_usage (const struct argp *argp, const struct argp_state *state, char *our_level = *levels; int multiple = 0; const struct argp_child *child = argp->children; - const char *tdoc = dgettext (argp->argp_domain, argp->args_doc), *nl = 0; + const char *tdoc = + argp->args_doc ? dgettext (argp->argp_domain, argp->args_doc) : NULL; const char *fdoc = filter_doc (tdoc, ARGP_KEY_HELP_ARGS_DOC, argp, state); + const char *nl = NULL; if (fdoc) { > you could see that from #3, msgid is 0x0. > > > I don't see which dgettext invocation in argp-help.c is the one that > needs the > NULL check. > > it's not one but multiple. argp->doc[argp_doc()], and > argp->args_doc[argp_args_usage[]) are what i have found . i am not sure if > there's any other, but i'll give the fix a test and see. Ah right. The 'doc' field of a 'struct argp' can be NULL as well, this is documented in https://www.gnu.org/software/libc/manual/html_node/Argp-Parsers.html. The 'doc' field in a 'struct argp_option' looks like it can be NULL as well, see argp-help.c line 1178. 2019-01-05 Bruno Haible <br...@clisp.org> argp: Don't pass an invalid argument to dgettext(). Reported by He X <xw897002...@gmail.com>. * lib/argp-help.c (print_header, argp_doc): Don't pass a NULL doc to dgettext(). diff --git a/lib/argp-help.c b/lib/argp-help.c index e5e97ec..75abe84 100644 --- a/lib/argp-help.c +++ b/lib/argp-help.c @@ -1021,7 +1021,7 @@ static void print_header (const char *str, const struct argp *argp, struct pentry_state *pest) { - const char *tstr = dgettext (argp->argp_domain, str); + const char *tstr = str ? dgettext (argp->argp_domain, str) : NULL; const char *fstr = filter_doc (tstr, ARGP_KEY_HELP_HEADER, argp, pest->state); if (fstr) @@ -1479,7 +1479,7 @@ argp_doc (const struct argp *argp, const struct argp_state *state, void *input = 0; int anything = 0; size_t inp_text_limit = 0; - const char *doc = dgettext (argp->argp_domain, argp->doc); + const char *doc = argp->doc ? dgettext (argp->argp_domain, argp->doc) : NULL; const struct argp_child *child = argp->children; if (doc)