aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@openbsd.org>2020-02-24 21:16:31 +0000
committerIngo Schwarze <schwarze@openbsd.org>2020-02-24 21:16:31 +0000
commit83ad1abc9ffe08ed430d83909fe1297738f5c224 (patch)
tree186ffcaf1c2b771cf58d1837352354e08d5ed7b4
parent34bee6097a58670fc58c4e6bcf0516bda8db47d7 (diff)
downloadmandoc-83ad1abc9ffe08ed430d83909fe1297738f5c224.tar.gz
mandoc-83ad1abc9ffe08ed430d83909fe1297738f5c224.tar.zst
mandoc-83ad1abc9ffe08ed430d83909fe1297738f5c224.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@.
-rw-r--r--main.c30
1 files changed, 26 insertions, 4 deletions
diff --git a/main.c b/main.c
index b84a9a2b..862eb9bf 100644
--- a/main.c
+++ b/main.c
@@ -1,4 +1,4 @@
-/* $Id: main.c,v 1.343 2020/02/10 13:49:15 schwarze Exp $ */
+/* $Id: main.c,v 1.344 2020/02/24 21:16:31 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 *);
@@ -674,6 +675,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,
@@ -682,10 +695,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);
@@ -709,8 +726,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,