From: Jo-Philipp Wich Date: Fri, 26 May 2017 16:42:05 +0000 (+0200) Subject: options: improve handling of negations when parsing space separated values X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=3d2c18a91bb7cd5f3c0dec7fecf3008934de170b;p=oweals%2Ffirewall3.git options: improve handling of negations when parsing space separated values Improve the space separated list parser to interprete "val1 ! val2" as ("val1", "!val2") instead of ("val1", "!", "val2"). This corrects parsing of sections like ... config rule option sec_ip '! 1.1.1.0/24' ... which previously errored out with: Warning: Option @rule[0].src_ip has invalid value '!' Fixes FS#806. Signed-off-by: Jo-Philipp Wich --- diff --git a/options.c b/options.c index d88d3ba..ae6bf5d 100644 --- a/options.c +++ b/options.c @@ -891,7 +891,7 @@ fw3_parse_options(void *s, const struct fw3_option *opts, struct uci_section *section) { char *p, *v; - bool known; + bool known, inv; struct uci_element *e, *l; struct uci_option *o; const struct fw3_option *opt; @@ -953,10 +953,30 @@ fw3_parse_options(void *s, const struct fw3_option *opts, } else { + inv = false; dest = (struct list_head *)((char *)s + opt->offset); for (p = strtok(v, " \t"); p != NULL; p = strtok(NULL, " \t")) { + /* If we encounter a sole "!" token, assume that it + * is meant to be part of the next token, so silently + * skip it and remember the state... */ + if (!strcmp(p, "!")) + { + inv = true; + continue; + } + + /* The previous token was a sole "!", rewind pointer + * back by one byte to precede the value with an + * exclamation mark which effectively turns + * ("!", "foo") into ("!foo") */ + if (inv) + { + *--p = '!'; + inv = false; + } + if (!opt->parse(dest, p, true)) { warn_elem(e, "has invalid value '%s'", p); @@ -964,6 +984,15 @@ fw3_parse_options(void *s, const struct fw3_option *opts, continue; } } + + /* The last token was a sole "!" without any subsequent + * text, so pass it to the option parser as-is. */ + if (inv && !opt->parse(dest, "!", true)) + { + warn_elem(e, "has invalid value '%s'", p); + valid = false; + continue; + } } }