From 6037617499b7e181afcd03466025f595471d91de Mon Sep 17 00:00:00 2001 From: helg Date: Mon, 11 Dec 2017 12:01:55 +0000 Subject: [PATCH] The fuse_opt_match(3) library function does not match options correctly. libfuse supports option templates of the following form that can be used to automatically parse arguments supplied on the command line. "-p " argument that takes an option e.g -p 22 or -p22 "-p %x" argument that takes an option parsed like sscanf(3) "cache=yes" matches -ocache=yes or -o cache=yes "cache=%s" matches -ocache= or -o cache= "cache=" matches same as above but value is passed to option proc "noatime" matches -onoatime or -o atime For example, it does not match options of the form "-p 22" or "cache=yes" to the corresponding templates "-p " and "cache=yes". This patch fixes that and updates the regression tests accordingly. ok mpi@ --- lib/libfuse/fuse_opt.c | 76 ++++++------------------ regress/lib/libfuse/fuse-opt-match.c | 87 +++++++++++++++------------- 2 files changed, 66 insertions(+), 97 deletions(-) diff --git a/lib/libfuse/fuse_opt.c b/lib/libfuse/fuse_opt.c index 873b3380399..0b026cc6038 100644 --- a/lib/libfuse/fuse_opt.c +++ b/lib/libfuse/fuse_opt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fuse_opt.c,v 1.19 2017/11/16 12:56:58 helg Exp $ */ +/* $OpenBSD: fuse_opt.c,v 1.20 2017/12/11 12:01:55 helg Exp $ */ /* * Copyright (c) 2013 Sylvestre Gallon * Copyright (c) 2013 Stefan Sperling @@ -67,73 +67,35 @@ alloc_argv(struct fuse_args *args) return (0); } -static int +/* + * Returns the number of characters that matched for bounds checking later. + */ +static size_t match_opt(const char *templ, const char *opt) { - const char *o, *t; - char *arg; - - arg = strpbrk(templ, " ="); - - /* verify template */ - t = templ; - if (*t == '-') { - t++; - if (*t == '-') - t++; - if (*t == 'o' || *t == '\0') - return (0); - } + size_t sep, len; - /* skip leading -, -o, and -- in option name */ - o = opt; - if (*o == '-') { - o++; - if (*o == 'o' || *o == '-') - o++; - } + len = strlen(templ); + sep = strcspn(templ, "="); - /* empty option name is invalid */ - if (*o == '\0') - return (0); + if (sep == len) + sep = strcspn(templ, " "); - /* match option name */ - while (*t && *o) { - if (*t++ != *o++) + /* key=, key=%, "-k ", -k % */ + if (sep < len && (templ[sep + 1] == '\0' || templ[sep + 1] == '%')) { + if (strncmp(opt, templ, sep) == 0) + return (sep); + else return (0); - if (arg && t == arg) { - if (*o != ' ' && *o != '=') - return (0); - o++; /* o now points at argument */ - if (*o == '\0') - return (0); - break; - } } - /* match argument */ - if (arg) { - if (t != arg) - return (0); - t++; - /* does template have an argument? */ - if (*t != '%' && *t != '\0') - return (0); - if (*t == '%' && t[1] == '\0') - return (0); - /* yes it does, consume argument in opt */ - while (*o && *o != ' ') - o++; - } else if (*t != '\0') - return (0); + if (strcmp(opt, templ) == 0) + return (len); - /* we should have consumed entire opt string */ - if (*o != '\0') - return (0); - - return (1); + return (0); } + static int add_opt(char **opts, const char *opt) { diff --git a/regress/lib/libfuse/fuse-opt-match.c b/regress/lib/libfuse/fuse-opt-match.c index 71daa0245f3..830f456ed3a 100644 --- a/regress/lib/libfuse/fuse-opt-match.c +++ b/regress/lib/libfuse/fuse-opt-match.c @@ -1,5 +1,5 @@ /* - * Copyright (c) Sylvestre Gallon + * Copyright (c) 2017 Helg Bredow * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -14,55 +14,62 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include +#include +#include #include -const struct fuse_opt nullopts[] = { +static const struct fuse_opt emptyopts[] = { FUSE_OPT_END }; -const int nullresults[] = { - 0, 0, 0, 0, 0, 0 -}; - -const struct fuse_opt badopts[] = { - FUSE_OPT_KEY("-p ", 0), - FUSE_OPT_KEY("-C", 1), - FUSE_OPT_KEY("-V", 3), - FUSE_OPT_KEY("--version", 3), - FUSE_OPT_KEY("-h", 2), +static const struct fuse_opt opts[] = { + FUSE_OPT_KEY("-p ", FUSE_OPT_KEY_DISCARD), + FUSE_OPT_KEY("-C", FUSE_OPT_KEY_DISCARD), + FUSE_OPT_KEY("-V", FUSE_OPT_KEY_DISCARD), + FUSE_OPT_KEY("--version", FUSE_OPT_KEY_DISCARD), + FUSE_OPT_KEY("-h", FUSE_OPT_KEY_DISCARD), + FUSE_OPT_KEY("const=false", FUSE_OPT_KEY_DISCARD), + FUSE_OPT_KEY("cache=no", FUSE_OPT_KEY_DISCARD), + FUSE_OPT_KEY("cache=yes", FUSE_OPT_KEY_DISCARD), + FUSE_OPT_KEY("debug", FUSE_OPT_KEY_DISCARD), + FUSE_OPT_KEY("ro", FUSE_OPT_KEY_DISCARD), + FUSE_OPT_KEY("--foo=", FUSE_OPT_KEY_DISCARD), + FUSE_OPT_KEY("bars=%s", FUSE_OPT_KEY_DISCARD), + FUSE_OPT_KEY("--fool=%lu", FUSE_OPT_KEY_DISCARD), + FUSE_OPT_KEY("-x ", FUSE_OPT_KEY_DISCARD), + FUSE_OPT_KEY("-n %u", FUSE_OPT_KEY_DISCARD), + FUSE_OPT_KEY("-P", FUSE_OPT_KEY_DISCARD), FUSE_OPT_END }; -static int -match_opts(const struct fuse_opt *opts, const int *results) +int +main(void) { - if (fuse_opt_match(opts, NULL) != 0) - return (1); + assert(fuse_opt_match(emptyopts, "debug") == 0); - if (fuse_opt_match(opts, "bar=") != results[0]) - return (3); - if (fuse_opt_match(opts, "--foo=") != results[1]) - return (4); - if (fuse_opt_match(opts, "bar=%s") != results[2]) - return (5); - if (fuse_opt_match(opts, "--foo=%lu") != results[3]) - return (6); - if (fuse_opt_match(opts, "-x ") != results[4]) - return (7); - if (fuse_opt_match(opts, "-x %s") != results[5]) - return (8); + assert(fuse_opt_match(opts, NULL) == 0); + assert(fuse_opt_match(opts, "-p ") == 1); + assert(fuse_opt_match(opts, "-C") == 1); + assert(fuse_opt_match(opts, "-c") == 0); + assert(fuse_opt_match(opts, "-V") == 1); + assert(fuse_opt_match(opts, "--version") == 1); + assert(fuse_opt_match(opts, "-h") == 1); + assert(fuse_opt_match(opts, "const=false") == 1); + assert(fuse_opt_match(opts, "const=falsefalse") == 0); + assert(fuse_opt_match(opts, "cache=no") == 1); + assert(fuse_opt_match(opts, "cache=yes") == 1); + assert(fuse_opt_match(opts, "debug") == 1); + assert(fuse_opt_match(opts, "ro") == 1); + assert(fuse_opt_match(opts, "ro_fallback") == 0); + assert(fuse_opt_match(opts, "--foo=bar") == 1); + assert(fuse_opt_match(opts, "bars=foo") == 1); + assert(fuse_opt_match(opts, "--fool=bool") == 1); + assert(fuse_opt_match(opts, "--fool=1") == 1); + assert(fuse_opt_match(opts, "-x bar") == 1); + assert(fuse_opt_match(opts, "-xbar") == 1); + assert(fuse_opt_match(opts, "-n 100") == 1); + assert(fuse_opt_match(opts, "-n100") == 1); + assert(fuse_opt_match(opts, "-P") == 1); return (0); } - -int -main(int ac, char **av) -{ - if (match_opts(nullopts, nullresults) != 0) - return (1); - if (match_opts(badopts, nullresults) != 0) - return (1); - return (0); -} - -- 2.20.1