]> source.dussan.org Git - rspamd.git/commitdiff
[Fix] Fix freeing of arrays iterators
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Wed, 8 Mar 2017 15:54:46 +0000 (15:54 +0000)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Wed, 8 Mar 2017 15:55:26 +0000 (15:55 +0000)
Issue: #1497

contrib/libucl/ucl_util.c

index 7fcfe2e6ed9e8064aaff23355f42fa1d3a756cb0..07af232d9d82fceb0838671f2deb269482f618ed 100644 (file)
@@ -2434,9 +2434,17 @@ ucl_object_iterate (const ucl_object_t *obj, ucl_object_iter_t *iter, bool expan
        return NULL;
 }
 
+enum ucl_safe_iter_flags {
+       UCL_ITERATE_FLAG_UNDEFINED = 0,
+       UCL_ITERATE_FLAG_INSIDE_ARRAY,
+       UCL_ITERATE_FLAG_INSIDE_OBJECT,
+       UCL_ITERATE_FLAG_IMPLICIT,
+};
+
 const char safe_iter_magic[4] = {'u', 'i', 't', 'e'};
 struct ucl_object_safe_iter {
        char magic[4]; /* safety check */
+       uint32_t flags;
        const ucl_object_t *impl_it; /* implicit object iteration */
        ucl_object_iter_t expl_it; /* explicit iteration */
 };
@@ -2455,6 +2463,7 @@ ucl_object_iterate_new (const ucl_object_t *obj)
        it = UCL_ALLOC (sizeof (*it));
        if (it != NULL) {
                memcpy (it->magic, safe_iter_magic, sizeof (it->magic));
+               it->flags = UCL_ITERATE_FLAG_UNDEFINED;
                it->expl_it = NULL;
                it->impl_it = obj;
        }
@@ -2471,11 +2480,14 @@ ucl_object_iterate_reset (ucl_object_iter_t it, const ucl_object_t *obj)
        UCL_SAFE_ITER_CHECK (rit);
 
        if (rit->expl_it != NULL) {
-               UCL_FREE (sizeof (*rit->expl_it), rit->expl_it);
+               if (rit->flags == UCL_ITERATE_FLAG_INSIDE_OBJECT) {
+                       UCL_FREE (sizeof (*rit->expl_it), rit->expl_it);
+               }
        }
 
        rit->impl_it = obj;
        rit->expl_it = NULL;
+       rit->flags = UCL_ITERATE_FLAG_UNDEFINED;
 
        return it;
 }
@@ -2499,7 +2511,20 @@ ucl_object_iterate_full (ucl_object_iter_t it, enum ucl_iterate_type type)
                return NULL;
        }
 
-       if (rit->impl_it->type == UCL_OBJECT || rit->impl_it->type == UCL_ARRAY) {
+       if (rit->impl_it->type == UCL_OBJECT) {
+               rit->flags = UCL_ITERATE_FLAG_INSIDE_OBJECT;
+               ret = ucl_object_iterate (rit->impl_it, &rit->expl_it, true);
+
+               if (ret == NULL && (type & UCL_ITERATE_IMPLICIT)) {
+                       /* Need to switch to another implicit object in chain */
+                       rit->impl_it = rit->impl_it->next;
+                       rit->expl_it = NULL;
+
+                       return ucl_object_iterate_safe (it, type);
+               }
+       }
+       else if (rit->impl_it->type == UCL_ARRAY) {
+               rit->flags = UCL_ITERATE_FLAG_INSIDE_ARRAY;
                ret = ucl_object_iterate (rit->impl_it, &rit->expl_it, true);
 
                if (ret == NULL && (type & UCL_ITERATE_IMPLICIT)) {
@@ -2512,6 +2537,7 @@ ucl_object_iterate_full (ucl_object_iter_t it, enum ucl_iterate_type type)
        }
        else {
                /* Just iterate over the implicit array */
+               rit->flags = UCL_ITERATE_FLAG_IMPLICIT;
                ret = rit->impl_it;
                rit->impl_it = rit->impl_it->next;
 
@@ -2534,7 +2560,9 @@ ucl_object_iterate_free (ucl_object_iter_t it)
        UCL_SAFE_ITER_CHECK (rit);
 
        if (rit->expl_it != NULL) {
-               UCL_FREE (sizeof (*rit->expl_it), rit->expl_it);
+               if (rit->flags == UCL_ITERATE_FLAG_INSIDE_OBJECT) {
+                       UCL_FREE (sizeof (*rit->expl_it), rit->expl_it);
+               }
        }
 
        UCL_FREE (sizeof (*rit), it);