From: Alan T. DeKok Date: Sun, 11 Dec 2022 15:11:16 +0000 (-0500) Subject: make conditional parser use fr_skip_string() X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fff3dfaf7517d179fe3ffaf8fe25f2a0309142fa;p=thirdparty%2Ffreeradius-server.git make conditional parser use fr_skip_string() in the interest of common code. --- diff --git a/src/lib/server/cf_file.c b/src/lib/server/cf_file.c index 53773c3f04d..616bbb518f8 100644 --- a/src/lib/server/cf_file.c +++ b/src/lib/server/cf_file.c @@ -1166,47 +1166,6 @@ static int process_template(cf_stack_t *stack) static int cf_file_fill(cf_stack_t *stack); -static uint8_t const *skip_string(uint8_t const *p, char c) -{ - while (*p >= ' ') { - if (*p == c) { - p++; - return p; - } - - if (*p != '\\') { - p++; - continue; - } - - if (p[1] < ' ') { - return NULL; - } - - if (!isdigit((int) p[1])) { - p += 2; - continue; - } - - /* - * Double-quoted strings use \000 - * Regexes use \0 - */ - if (c == '/') { - p++; - continue; - } - - if (!isdigit((int) p[2]) || !isdigit((int) p[3])) { - return NULL; - } - - p += 4; - } - - return NULL; -} - /* * Expansions can contain other expansions, but can't contain regexes. */ @@ -1241,10 +1200,12 @@ static uint8_t const *skip_expanse(uint8_t const *p) } if ((*p == '"') || (*p == '\'') || (*p == '`')) { - char c = *p++; + ssize_t slen; - p = skip_string(p, c); - if (!p) return NULL; + slen = fr_skip_string((char const *) p, NULL); + if (slen <= 0) return NULL; + + p += slen; continue; } @@ -1309,7 +1270,6 @@ static CONF_ITEM *process_if(cf_stack_t *stack) * */ while (true) { - char c; bool found = false; bool was_regex = false; int depth = 0; @@ -1377,15 +1337,18 @@ static CONF_ITEM *process_if(cf_stack_t *stack) * We have a quoted string, ignore '(' and ')' within it. */ if ((*p == '"') || (*p == '\'') || (*p == '`') || (was_regex && (*p == '/'))) { + ssize_t my_slen; + was_regex = false; - c = *p++; - p = skip_string(p, c); - if (!p) { + + my_slen = fr_skip_string((char const *) p, NULL); + if (my_slen <= 0) { cf_log_err(cs, "Unexpected end of string"); talloc_free(cs); return NULL; } + p += my_slen; continue; } diff --git a/src/lib/util/token.c b/src/lib/util/token.c index 23481d134d3..4a3190df83f 100644 --- a/src/lib/util/token.c +++ b/src/lib/util/token.c @@ -491,6 +491,14 @@ char const *fr_token_name(int token) } +/** Skip a quoted string. + * + * @param[in] start start of the string, pointing to the quotation character + * @param[in] end end of the string (or NULL for zero-terminated strings) + * @return + * >0 length of the string which was parsed + * <=0 on error + */ ssize_t fr_skip_string(char const *start, char const *end) { char const *p = start; @@ -498,22 +506,59 @@ ssize_t fr_skip_string(char const *start, char const *end) quote = *(p++); - while (p < end) { + while ((end && (p < end)) || *p) { + /* + * Stop at the quotation character + */ if (*p == quote) { p++; return p - start; } - if (*p == '\\') { - if (((p + 1) >= end) || !p[1]) { - break; - } + /* + * Not an escape character: it's OK. + */ + if (*p != '\\') { + p++; + continue; + } + if (end && ((p + 2) >= end)) { + fail: + fr_strerror_const("Unexpected escape at end of string"); + return -(p - start); + } + + /* + * Escape at EOL is not allowed. + */ + if (p[1] < ' ') goto fail; + + /* + * \r or \n, etc. + */ + if (!isdigit((int) p[1])) { p += 2; continue; } - p++; + /* + * Double-quoted strings use \000 + * Regexes use \0 + */ + if (quote == '/') { + p++; + continue; + } + + if (end && ((p + 4) >= end)) goto fail; + + if (!isdigit((int) p[2]) || !isdigit((int) p[3])) { + fr_strerror_const("Invalid octal escape"); + return -(p - start); + } + + p += 4; } /* @@ -522,3 +567,4 @@ ssize_t fr_skip_string(char const *start, char const *end) fr_strerror_const("Unexpected end of string"); return -(p - start); } +