diff options
author | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2022-01-06 14:05:35 +0000 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2022-01-06 14:05:35 +0000 |
commit | c71f98b2422d7c758db2d0370374408ed2c45618 (patch) | |
tree | 662a53308690a4ca4c76dbc7d6ee72eb601ce16c /contrib | |
parent | 7fd6b2b76699f3456f6b06ab1ee1d0bb6d8d9069 (diff) | |
download | rspamd-c71f98b2422d7c758db2d0370374408ed2c45618.tar.gz rspamd-c71f98b2422d7c758db2d0370374408ed2c45618.zip |
[Fix] Backport PR from libucl
https://github.com/vstakhov/libucl/pull/260
Diffstat (limited to 'contrib')
-rw-r--r-- | contrib/libucl/ucl_parser.c | 57 | ||||
-rw-r--r-- | contrib/libucl/ucl_util.c | 10 |
2 files changed, 43 insertions, 24 deletions
diff --git a/contrib/libucl/ucl_parser.c b/contrib/libucl/ucl_parser.c index 8ccbf05af..5ed72d0bb 100644 --- a/contrib/libucl/ucl_parser.c +++ b/contrib/libucl/ucl_parser.c @@ -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; diff --git a/contrib/libucl/ucl_util.c b/contrib/libucl/ucl_util.c index e97e3ab9b..13544af28 100644 --- a/contrib/libucl/ucl_util.c +++ b/contrib/libucl/ucl_util.c @@ -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]; } } |