]> git.ipfire.org Git - thirdparty/rspamd.git/commitdiff
[Fix] Backport fix for empty files inclusion from libucl
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Mon, 18 Apr 2016 17:30:08 +0000 (18:30 +0100)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Mon, 18 Apr 2016 17:30:08 +0000 (18:30 +0100)
Issue: #596
Reported by: @assistcontrol

contrib/libucl/ucl.h
contrib/libucl/ucl_parser.c
contrib/libucl/ucl_util.c

index bcc8049acb6333762cfd4a433014c4643d6d3694..024f5dd8fd357f110e57d9ce5237ea6046c4eb03 100644 (file)
@@ -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;
 
 /**
@@ -1130,6 +1131,25 @@ UCL_EXTERN const ucl_object_t * ucl_parser_get_comments (struct ucl_parser *pars
 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
index 7a935a5c7ca652be15d8507c4ac27a0dd89d1e76..fc7cea07febab39b1dacb0a9e36a294c2059b2bc 100644 (file)
@@ -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;
                }
        }
 
index 6376d6a428ded2cca398c91a4126fc9bbcc18488..1adb8c3b6d56a496ce3021d4ed44a24b149eb792 100644 (file)
@@ -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);
+       }
+}