summaryrefslogtreecommitdiffstats
path: root/usr.bin/mandoc
diff options
context:
space:
mode:
authorschwarze <schwarze@openbsd.org>2020-02-24 21:15:05 +0000
committerschwarze <schwarze@openbsd.org>2020-02-24 21:15:05 +0000
commite8a031dcddfc5d7c9801e443aececd939abe3ec4 (patch)
tree35d0f38236c752db9cc333c198ddd11e6e532624 /usr.bin/mandoc
parentStop generating rdatastruct.h and put the dns_rdata_* structs for (diff)
downloadwireguard-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.c30
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,