diff options
author | schwarze <schwarze@openbsd.org> | 2020-02-24 21:15:05 +0000 |
---|---|---|
committer | schwarze <schwarze@openbsd.org> | 2020-02-24 21:15:05 +0000 |
commit | e8a031dcddfc5d7c9801e443aececd939abe3ec4 (patch) | |
tree | 35d0f38236c752db9cc333c198ddd11e6e532624 /usr.bin/mandoc | |
parent | Stop generating rdatastruct.h and put the dns_rdata_* structs for (diff) | |
download | wireguard-openbsd-e8a031dcddfc5d7c9801e443aececd939abe3ec4.tar.xz wireguard-openbsd-e8a031dcddfc5d7c9801e443aececd939abe3ec4.zip |
Marc Espie reported that "man p*ipc" displayed the perlipc(1) manual.
The reason was that as a last resort when failing to find a page
name in mandoc.db(5) or at a few well well-defined fully qualified
file names, man(1) uses glob(3) to look for candidate files in
relevant directories, because some operating systems have weird
file name extensions, for example pcap.3pcap and BF_set_key.3ssl
on Linux. But during that globbing, the metacharacters "*?[" need
to be escaped in the name, section, and path supplied by the user,
or you would get weird false positives and misleading warning
messages and would be unable to use the fallback for path or file
names that actually contain an opening bracket.
Feedback and OK espie@.
Diffstat (limited to 'usr.bin/mandoc')
-rw-r--r-- | usr.bin/mandoc/main.c | 30 |
1 files changed, 26 insertions, 4 deletions
diff --git a/usr.bin/mandoc/main.c b/usr.bin/mandoc/main.c index 694dc415e6d..5c72f60ce7b 100644 --- a/usr.bin/mandoc/main.c +++ b/usr.bin/mandoc/main.c @@ -1,4 +1,4 @@ -/* $OpenBSD: main.c,v 1.246 2020/02/10 13:49:04 schwarze Exp $ */ +/* $OpenBSD: main.c,v 1.247 2020/02/24 21:15:05 schwarze Exp $ */ /* * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2010-2012, 2014-2020 Ingo Schwarze <schwarze@openbsd.org> @@ -98,6 +98,7 @@ static int fs_lookup(const struct manpaths *, static int fs_search(const struct mansearch *, const struct manpaths *, const char *, struct manpage **, size_t *); +static void glob_esc(char **, const char *, const char *); static void outdata_alloc(struct outstate *, struct manoutput *); static void parse(struct mparse *, int, const char *, struct outstate *, struct manoutput *); @@ -653,6 +654,18 @@ usage(enum argmode argmode) exit((int)MANDOCLEVEL_BADARG); } +static void +glob_esc(char **dst, const char *src, const char *suffix) +{ + while (*src != '\0') { + if (strchr("*?[", *src) != NULL) + *(*dst)++ = '\\'; + *(*dst)++ = *src++; + } + while (*suffix != '\0') + *(*dst)++ = *suffix++; +} + static int fs_lookup(const struct manpaths *paths, size_t ipath, const char *sec, const char *arch, const char *name, @@ -661,10 +674,14 @@ fs_lookup(const struct manpaths *paths, size_t ipath, struct stat sb; glob_t globinfo; struct manpage *page; - char *file; + char *file, *cp; int globres; enum form form; + const char *const slman = "/man"; + const char *const slash = "/"; + const char *const sglob = ".[01-9]*"; + form = FORM_SRC; mandoc_asprintf(&file, "%s/man%s/%s.%s", paths->paths[ipath], sec, name, sec); @@ -688,8 +705,13 @@ fs_lookup(const struct manpaths *paths, size_t ipath, free(file); } - mandoc_asprintf(&file, "%s/man%s/%s.[01-9]*", - paths->paths[ipath], sec, name); + cp = file = mandoc_malloc(strlen(paths->paths[ipath]) * 2 + + strlen(slman) + strlen(sec) * 2 + strlen(slash) + + strlen(name) * 2 + strlen(sglob) + 1); + glob_esc(&cp, paths->paths[ipath], slman); + glob_esc(&cp, sec, slash); + glob_esc(&cp, name, sglob); + *cp = '\0'; globres = glob(file, 0, NULL, &globinfo); if (globres != 0 && globres != GLOB_NOMATCH) mandoc_msg(MANDOCERR_GLOB, 0, 0, |