[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: argp: pass NULL as msgid to dgettext without checks
From: |
Bruno Haible |
Subject: |
Re: argp: pass NULL as msgid to dgettext without checks |
Date: |
Sat, 05 Jan 2019 17:17:11 +0100 |
User-agent: |
KMail/5.1.3 (Linux/4.4.0-141-generic; KDE/5.18.0; x86_64; ; ) |
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 (address@hidden,
> address@hidden, address@hidden,
> address@hidden, address@hidden) at
> argp-help.c:1415
> #5 0x000055555558bcdd in _help (argp=0x7fffffffe740,
> address@hidden,
> stream=0x7ffff7ffb2a0 <f>, address@hidden,
> name=0x7fffffffed94 "tar") at argp-help.c:1640
> #6 0x000055555558ca08 in argp_state_help (address@hidden,
> stream=<optimized out>, address@hidden) 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 <address@hidden>
argp: Don't pass an invalid argument to dgettext().
Reported by He X <address@hidden>.
* 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 <address@hidden>
argp: Don't pass an invalid argument to dgettext().
Reported by He X <address@hidden>.
* 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)