From 7c2e2dc6d631ff5090fb1120bcfc9a6389f44e6a Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Wed, 8 Mar 2017 15:54:46 +0000 Subject: [PATCH] [Fix] Fix freeing of arrays iterators Issue: #1497 --- contrib/libucl/ucl_util.c | 34 +++++++++++++++++++++++++++++++--- 1 file 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); -- 2.39.5