commit c71f98b: [Fix] Backport PR from libucl

Vsevolod Stakhov vsevolod at highsecure.ru
Thu Jan 6 14:07:04 UTC 2022


Author: Vsevolod Stakhov
Date: 2022-01-06 14:05:35 +0000
URL: https://github.com/rspamd/rspamd/commit/c71f98b2422d7c758db2d0370374408ed2c45618 (HEAD -> master)

[Fix] Backport PR from libucl
https://github.com/vstakhov/libucl/pull/260

---
 contrib/libucl/ucl_parser.c | 57 +++++++++++++++++++++++++++++----------------
 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];
 			}
 		}


More information about the Commits mailing list