]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
make conditional parser use fr_skip_string()
authorAlan T. DeKok <aland@freeradius.org>
Sun, 11 Dec 2022 15:11:16 +0000 (10:11 -0500)
committerAlan T. DeKok <aland@freeradius.org>
Mon, 12 Dec 2022 15:27:38 +0000 (10:27 -0500)
in the interest of common code.

src/lib/server/cf_file.c
src/lib/util/token.c

index 53773c3f04d1660fd2ee6fc244750a383a8de31e..616bbb518f8d79acd7bb95620a6156134db60c8e 100644 (file)
@@ -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;
                        }
 
index 23481d134d37a73b5a5acc008ef768a9379570d7..4a3190df83fb0d2fa3f7139c2b901992eb03918f 100644 (file)
@@ -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);
 }
+