]> git.ipfire.org Git - thirdparty/rspamd.git/commitdiff
[Fix] Backport PR from libucl
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Thu, 6 Jan 2022 14:05:35 +0000 (14:05 +0000)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Thu, 6 Jan 2022 14:05:35 +0000 (14:05 +0000)
https://github.com/vstakhov/libucl/pull/260

contrib/libucl/ucl_parser.c
contrib/libucl/ucl_util.c

index 8ccbf05af3ed9ef0f5ed087a7b916718265fa25b..5ed72d0bb53dd1ec47302e066eff2bd9d563bf3c 100644 (file)
@@ -47,6 +47,9 @@ struct ucl_parser_saved_state {
  */
 #define ucl_chunk_skipc(chunk, p)    \
 do {                                 \
+       if (p == chunk->end) {       \
+               break;                   \
+       }                            \
        if (*(p) == '\n') {          \
                (chunk)->line ++;    \
                (chunk)->column = 0; \
@@ -394,6 +397,9 @@ ucl_check_variable (struct ucl_parser *parser, const char *ptr,
                        }
                        p ++;
                }
+               if(p == end) {
+                       (*out_len) ++;
+               }
        }
        else if (*ptr != '$') {
                /* Not count escaped dollar sign */
@@ -417,13 +423,14 @@ ucl_check_variable (struct ucl_parser *parser, const char *ptr,
  * Expand a single variable
  * @param parser
  * @param ptr
- * @param remain
+ * @param in_len
  * @param dest
+ * @param out_len
  * @return
  */
 static const char *
 ucl_expand_single_variable (struct ucl_parser *parser, const char *ptr,
-               size_t remain, unsigned char **dest)
+               size_t in_len, unsigned char **dest, size_t out_len)
 {
        unsigned char *d = *dest, *dst;
        const char *p = ptr + 1, *ret;
@@ -434,7 +441,8 @@ ucl_expand_single_variable (struct ucl_parser *parser, const char *ptr,
        bool strict = false;
 
        ret = ptr + 1;
-       remain --;
+       out_len --;
+       in_len --;
 
        if (*p == '$') {
                *d++ = *p++;
@@ -443,28 +451,31 @@ ucl_expand_single_variable (struct ucl_parser *parser, const char *ptr,
        }
        else if (*p == '{') {
                p ++;
+               in_len --;
                strict = true;
                ret += 2;
-               remain -= 2;
+               out_len -= 2;
        }
 
        LL_FOREACH (parser->variables, var) {
-               if (remain >= var->var_len) {
+               if (out_len >= var->value_len && in_len >= (var->var_len + strict)) {
                        if (memcmp (p, var->var, var->var_len) == 0) {
-                               memcpy (d, var->value, var->value_len);
-                               ret += var->var_len;
-                               d += var->value_len;
-                               found = true;
-                               break;
+                               if (!strict || p[var->var_len] == '}') {
+                                       memcpy (d, var->value, var->value_len);
+                                       ret += var->var_len;
+                                       d += var->value_len;
+                                       found = true;
+                                       break;
+                               }
                        }
                }
        }
        if (!found) {
                if (strict && parser->var_handler != NULL) {
-                       if (parser->var_handler (p, remain, &dst, &dstlen, &need_free,
+                       if (parser->var_handler (p, out_len, &dst, &dstlen, &need_free,
                                                        parser->var_data)) {
                                memcpy (d, dst, dstlen);
-                               ret += remain;
+                               ret += out_len;
                                d += dstlen;
                                found = true;
                                if (need_free) {
@@ -475,7 +486,7 @@ ucl_expand_single_variable (struct ucl_parser *parser, const char *ptr,
 
                /* Leave variable as is */
                if (!found) {
-                       if (strict) {
+                       if (strict && out_len >= 2) {
                                /* Copy '${' */
                                memcpy (d, ptr, 2);
                                d += 2;
@@ -505,7 +516,7 @@ ucl_expand_variable (struct ucl_parser *parser, unsigned char **dst,
                const char *src, size_t in_len)
 {
        const char *p, *end = src + in_len;
-       unsigned char *d;
+       unsigned char *d, *d_end;
        size_t out_len = 0;
        bool vars_found = false;
 
@@ -516,7 +527,7 @@ ucl_expand_variable (struct ucl_parser *parser, unsigned char **dst,
 
        p = src;
        while (p != end) {
-               if (*p == '$') {
+               if (*p == '$' && p + 1 != end) {
                        p = ucl_check_variable (parser, p + 1, end - p - 1, &out_len, &vars_found);
                }
                else {
@@ -537,10 +548,11 @@ ucl_expand_variable (struct ucl_parser *parser, unsigned char **dst,
        }
 
        d = *dst;
+       d_end = d + out_len;
        p = src;
-       while (p != end) {
-               if (*p == '$') {
-                       p = ucl_expand_single_variable (parser, p, end - p, &d);
+       while (p != end && d != d_end) {
+               if (*p == '$' && p + 1 != end) {
+                       p = ucl_expand_single_variable (parser, p, end - p, &d, d_end - d);
                }
                else {
                        *d++ = *p++;
@@ -1054,13 +1066,13 @@ ucl_lex_json_string (struct ucl_parser *parser,
                }
                else if (c == '\\') {
                        ucl_chunk_skipc (chunk, p);
-                       c = *p;
                        if (p >= chunk->end) {
                                ucl_set_err (parser, UCL_ESYNTAX, "unfinished escape character",
                                                &parser->err);
                                return false;
                        }
-                       else if (ucl_test_character (c, UCL_CHARACTER_ESCAPE)) {
+                       c = *p;
+                       if (ucl_test_character (c, UCL_CHARACTER_ESCAPE)) {
                                if (c == 'u') {
                                        ucl_chunk_skipc (chunk, p);
                                        for (i = 0; i < 4 && p < chunk->end; i ++) {
@@ -1829,6 +1841,11 @@ ucl_parse_value (struct ucl_parser *parser, struct ucl_chunk *chunk)
                                        while (p < chunk->end && *p >= 'A' && *p <= 'Z') {
                                                p ++;
                                        }
+                                       if(p == chunk->end) {
+                                               ucl_set_err (parser, UCL_ESYNTAX,
+                                                               "unterminated multiline value", &parser->err);
+                                               return false;
+                                       }
                                        if (*p =='\n') {
                                                /* Set chunk positions and start multiline parsing */
                                                chunk->remain -= p - c + 1;
index e97e3ab9b265095d1271c25968dc35d95bd60fc0..13544af28dfbf7f20b4d79fb25473fe56e463d5a 100644 (file)
@@ -1927,7 +1927,7 @@ ucl_inherit_handler (const unsigned char *data, size_t len,
 
        /* Some sanity checks */
        if (parent == NULL || ucl_object_type (parent) != UCL_OBJECT) {
-               ucl_create_err (&parser->err, "Unable to find inherited object %*.s",
+               ucl_create_err (&parser->err, "Unable to find inherited object %.*s",
                                (int)len, data);
                return false;
        }
@@ -2185,7 +2185,7 @@ ucl_strnstr (const char *s, const char *find, int len)
                mlen = strlen (find);
                do {
                        do {
-                               if ((sc = *s++) == 0 || len-- == 0)
+                               if ((sc = *s++) == 0 || len-- < mlen)
                                        return (NULL);
                        } while (sc != c);
                } while (strncmp (s, find, mlen) != 0);
@@ -3602,9 +3602,11 @@ ucl_object_copy_internal (const ucl_object_t *other, bool allow_array)
 
                /* deep copy of values stored */
                if (other->trash_stack[UCL_TRASH_KEY] != NULL) {
-                       new->trash_stack[UCL_TRASH_KEY] =
-                                       strdup (other->trash_stack[UCL_TRASH_KEY]);
+                       new->trash_stack[UCL_TRASH_KEY] = NULL;
                        if (other->key == (const char *)other->trash_stack[UCL_TRASH_KEY]) {
+                               new->trash_stack[UCL_TRASH_KEY] = malloc(other->keylen + 1);
+                               memcpy(new->trash_stack[UCL_TRASH_KEY], other->trash_stack[UCL_TRASH_KEY], other->keylen);
+                               new->trash_stack[UCL_TRASH_KEY][other->keylen] = '\0';
                                new->key = new->trash_stack[UCL_TRASH_KEY];
                        }
                }