summaryrefslogtreecommitdiffstats
path: root/contrib
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2016-04-18 18:30:08 +0100
committerVsevolod Stakhov <vsevolod@highsecure.ru>2016-04-18 18:30:08 +0100
commitf789d85b3a4b239a2a22a984eb6f403fd298dcbf (patch)
treee8eb5805222a6c54d4470d16b20289d349f60c2b /contrib
parent82c33aae8f42712a21d845608142efcb2f6ae3bd (diff)
downloadrspamd-f789d85b3a4b239a2a22a984eb6f403fd298dcbf.tar.gz
rspamd-f789d85b3a4b239a2a22a984eb6f403fd298dcbf.zip
[Fix] Backport fix for empty files inclusion from libucl
Issue: #596 Reported by: @assistcontrol
Diffstat (limited to 'contrib')
-rw-r--r--contrib/libucl/ucl.h22
-rw-r--r--contrib/libucl/ucl_parser.c61
-rw-r--r--contrib/libucl/ucl_util.c50
3 files changed, 109 insertions, 24 deletions
diff --git a/contrib/libucl/ucl.h b/contrib/libucl/ucl.h
index bcc8049ac..024f5dd8f 100644
--- a/contrib/libucl/ucl.h
+++ b/contrib/libucl/ucl.h
@@ -107,7 +107,8 @@ typedef enum ucl_error {
UCL_ENESTED, /**< Input has too many recursion levels */
UCL_EMACRO, /**< Error processing a macro */
UCL_EINTERNAL, /**< Internal unclassified error */
- UCL_ESSL /**< SSL error */
+ UCL_ESSL, /**< SSL error */
+ UCL_EMERGE /**< A merge error occured */
} ucl_error_t;
/**
@@ -1131,6 +1132,25 @@ UCL_EXTERN const ucl_object_t * ucl_comments_find (const ucl_object_t *comments,
const ucl_object_t *srch);
/**
+ * Move comment from `from` object to `to` object
+ * @param comments comments object
+ * @param what source object
+ * @param whith destination object
+ * @return `true` if `from` has comment and it has been moved to `to`
+ */
+UCL_EXTERN bool ucl_comments_move (ucl_object_t *comments,
+ const ucl_object_t *from, const ucl_object_t *to);
+
+/**
+ * Adds a new comment for an object
+ * @param comments comments object
+ * @param obj object to add comment to
+ * @param comment string representation of a comment
+ */
+UCL_EXTERN void ucl_comments_add (ucl_object_t *comments,
+ const ucl_object_t *obj, const char *comment);
+
+/**
* Add new public key to parser for signatures check
* @param parser parser object
* @param key PEM representation of a key
diff --git a/contrib/libucl/ucl_parser.c b/contrib/libucl/ucl_parser.c
index 7a935a5c7..fc7cea07f 100644
--- a/contrib/libucl/ucl_parser.c
+++ b/contrib/libucl/ucl_parser.c
@@ -1068,6 +1068,7 @@ ucl_parser_process_object_element (struct ucl_parser *parser, ucl_object_t *nobj
{
ucl_hash_t *container;
ucl_object_t *tobj;
+ char errmsg[256];
container = parser->stack->obj->value.ov;
@@ -1126,25 +1127,36 @@ ucl_parser_process_object_element (struct ucl_parser *parser, ucl_object_t *nobj
break;
case UCL_DUPLICATE_ERROR:
- ucl_create_err (&parser->err, "error while parsing %s: "
- "line: %d, column: %d: duplicate element for key '%s' "
- "has been found",
- parser->cur_file ? parser->cur_file : "<unknown>",
- parser->chunks->line, parser->chunks->column, nobj->key);
+ snprintf(errmsg, sizeof(errmsg),
+ "duplicate element for key '%s' found",
+ nobj->key);
+ ucl_set_err (parser, UCL_EMERGE, errmsg, &parser->err);
return false;
case UCL_DUPLICATE_MERGE:
/*
* Here we do have some old object so we just push it on top of objects stack
+ * Check priority and then perform the merge on the remaining objects
*/
if (tobj->type == UCL_OBJECT || tobj->type == UCL_ARRAY) {
ucl_object_unref (nobj);
nobj = tobj;
}
- else {
- /* For other types we create implicit array as usual */
+ else if (priold == prinew) {
ucl_parser_append_elt (parser, container, tobj, nobj);
}
+ else if (priold > prinew) {
+ /*
+ * We add this new object to a list of trash objects just to ensure
+ * that it won't come to any real object
+ * XXX: rather inefficient approach
+ */
+ DL_APPEND (parser->trash_objs, nobj);
+ }
+ else {
+ ucl_hash_replace (container, tobj, nobj);
+ ucl_object_unref (tobj);
+ }
break;
}
}
@@ -2585,20 +2597,18 @@ ucl_parser_add_chunk_full (struct ucl_parser *parser, const unsigned char *data,
return false;
}
- if (data == NULL) {
+ if (data == NULL && len != 0) {
ucl_create_err (&parser->err, "invalid chunk added");
return false;
}
- if (len == 0) {
- parser->top_obj = ucl_object_new_full (UCL_OBJECT, priority);
- return true;
- }
+
if (parser->state != UCL_STATE_ERROR) {
chunk = UCL_ALLOC (sizeof (struct ucl_chunk));
if (chunk == NULL) {
ucl_create_err (&parser->err, "cannot allocate chunk structure");
return false;
}
+
chunk->begin = data;
chunk->remain = len;
chunk->pos = chunk->begin;
@@ -2617,12 +2627,27 @@ ucl_parser_add_chunk_full (struct ucl_parser *parser, const unsigned char *data,
return false;
}
- switch (parse_type) {
- default:
- case UCL_PARSE_UCL:
- return ucl_state_machine (parser);
- case UCL_PARSE_MSGPACK:
- return ucl_parse_msgpack (parser);
+ if (len > 0) {
+ /* Need to parse something */
+ switch (parse_type) {
+ default:
+ case UCL_PARSE_UCL:
+ return ucl_state_machine (parser);
+ case UCL_PARSE_MSGPACK:
+ return ucl_parse_msgpack (parser);
+ }
+ }
+ else {
+ /* Just add empty chunk and go forward */
+ if (parser->top_obj == NULL) {
+ /*
+ * In case of empty object, create one to indicate that we've
+ * read something
+ */
+ parser->top_obj = ucl_object_new_full (UCL_OBJECT, priority);
+ }
+
+ return true;
}
}
diff --git a/contrib/libucl/ucl_util.c b/contrib/libucl/ucl_util.c
index 6376d6a42..1adb8c3b6 100644
--- a/contrib/libucl/ucl_util.c
+++ b/contrib/libucl/ucl_util.c
@@ -975,6 +975,7 @@ ucl_include_file_single (const unsigned char *data, size_t len,
if (params->soft_fail) {
return false;
}
+
return (!params->must_exist || false);
}
@@ -1172,11 +1173,14 @@ ucl_include_file_single (const unsigned char *data, size_t len,
res = ucl_parser_add_chunk_full (parser, buf, buflen, params->priority,
params->strat, params->parse_type);
- if (!res && !params->must_exist) {
- /* Free error */
- utstring_free (parser->err);
- parser->err = NULL;
- parser->state = UCL_STATE_AFTER_VALUE;
+
+ if (!res) {
+ if (!params->must_exist) {
+ /* Free error */
+ utstring_free (parser->err);
+ parser->err = NULL;
+ res = true;
+ }
}
/* Stop nesting the include, take 1 level off the stack */
@@ -3450,3 +3454,39 @@ ucl_comments_find (const ucl_object_t *comments,
return NULL;
}
+
+bool
+ucl_comments_move (ucl_object_t *comments,
+ const ucl_object_t *from, const ucl_object_t *to)
+{
+ const ucl_object_t *found;
+ ucl_object_t *obj;
+
+ if (comments && from && to) {
+ found = ucl_object_lookup_len (comments,
+ (const char *)&from, sizeof (void *));
+
+ if (found) {
+ /* Replace key */
+ obj = ucl_object_ref (found);
+ ucl_object_delete_keyl (comments, (const char *)&from,
+ sizeof (void *));
+ ucl_object_insert_key (comments, obj, (const char *)&to,
+ sizeof (void *), true);
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void
+ucl_comments_add (ucl_object_t *comments, const ucl_object_t *obj,
+ const char *comment)
+{
+ if (comments && obj && comment) {
+ ucl_object_insert_key (comments, ucl_object_fromstring (comment),
+ (const char *)&obj, sizeof (void *), true);
+ }
+}