summaryrefslogtreecommitdiffstats
path: root/contrib
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2017-03-08 15:54:46 +0000
committerVsevolod Stakhov <vsevolod@highsecure.ru>2017-03-08 15:55:26 +0000
commit7c2e2dc6d631ff5090fb1120bcfc9a6389f44e6a (patch)
treed20bc121fd4e59859a567631f563a2d5694db4d6 /contrib
parenta060326c85beea9057da0ee913b2cf0bbfe9529b (diff)
downloadrspamd-7c2e2dc6d631ff5090fb1120bcfc9a6389f44e6a.tar.gz
rspamd-7c2e2dc6d631ff5090fb1120bcfc9a6389f44e6a.zip
[Fix] Fix freeing of arrays iterators
Issue: #1497
Diffstat (limited to 'contrib')
-rw-r--r--contrib/libucl/ucl_util.c34
1 files changed, 31 insertions, 3 deletions
diff --git a/contrib/libucl/ucl_util.c b/contrib/libucl/ucl_util.c
index 7fcfe2e6e..07af232d9 100644
--- a/contrib/libucl/ucl_util.c
+++ b/contrib/libucl/ucl_util.c
@@ -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);