From a5cced2b7acf4fb1818d6cd84c09a9ffe4dd1e89 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Wed, 24 Apr 2019 11:42:10 -0400 Subject: [PATCH] Extract keyword argument checking from argument parsing. --- src/feature/control/control_cmd.c | 53 +++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 14 deletions(-) diff --git a/src/feature/control/control_cmd.c b/src/feature/control/control_cmd.c index da9a95fc5d..9afa734d86 100644 --- a/src/feature/control/control_cmd.c +++ b/src/feature/control/control_cmd.c @@ -113,6 +113,41 @@ string_array_contains_keyword(const char **array, const char *kwd) return false; } +/** Helper for argument parsing: check whether the keyword arguments just + * parsed in result were well-formed according to syntax. + * + * On success, return 0. On failure, return -1 and set *error_out + * to a newly allocated error string. + **/ +static int +kvline_check_keyword_args(const control_cmd_args_t *result, + const control_cmd_syntax_t *syntax, + char **error_out) +{ + if (result->kwargs == NULL) { + tor_asprintf(error_out, "Cannot parse keyword argument(s)"); + return -1; + } + + if (! syntax->allowed_keywords) { + /* All keywords are permitted. */ + return 0; + } + + /* Check for unpermitted arguments */ + const config_line_t *line; + for (line = result->kwargs; line; line = line->next) { + if (! string_array_contains_keyword(syntax->allowed_keywords, + line->key)) { + tor_asprintf(error_out, "Unrecognized keyword argument %s", + escaped(line->key)); + return -1; + } + } + + return 0; +} + /** * Helper: parse the arguments to a command according to syntax. On * success, set *error_out to NULL and return a newly allocated @@ -174,27 +209,17 @@ control_cmd_parse_args(const char *command, } if (n_args > syntax->max_args) { + /* We have extra arguments after the positional arguments, and we didn't + treat them as an error, so they must count as keyword arguments: Either + K=V pairs, or flags, or both. */ tor_assert(n_args == syntax->max_args + 1); tor_assert(syntax->accept_keywords); char *remainder = smartlist_pop_last(result->args); result->kwargs = kvline_parse(remainder, syntax->kvline_flags); tor_free(remainder); - if (result->kwargs == NULL) { - tor_asprintf(error_out, "Cannot parse keyword argument(s)"); + if (kvline_check_keyword_args(result, syntax, error_out) < 0) { goto err; } - if (syntax->allowed_keywords) { - /* Check for unpermitted arguments */ - const config_line_t *line; - for (line = result->kwargs; line; line = line->next) { - if (! string_array_contains_keyword(syntax->allowed_keywords, - line->key)) { - tor_asprintf(error_out, "Unrecognized keyword argument %s", - escaped(line->key)); - goto err; - } - } - } } tor_assert_nonfatal(*error_out == NULL);