commit 1347022: [Fix] Libucl: Fix deletion from ucl objects

Vsevolod Stakhov vsevolod at highsecure.ru
Mon Aug 23 09:14:04 UTC 2021


Author: Vsevolod Stakhov
Date: 2021-08-22 18:23:31 +0100
URL: https://github.com/rspamd/rspamd/commit/1347022e3863deb97d670d63d48c937f12a9abd1

[Fix] Libucl: Fix deletion from ucl objects

---
 contrib/libucl/ucl_hash.c | 96 +++++++++++++++++------------------------------
 1 file changed, 35 insertions(+), 61 deletions(-)

diff --git a/contrib/libucl/ucl_hash.c b/contrib/libucl/ucl_hash.c
index dbd19c928..e67d682b6 100644
--- a/contrib/libucl/ucl_hash.c
+++ b/contrib/libucl/ucl_hash.c
@@ -24,7 +24,7 @@
 #include "ucl_internal.h"
 #include "ucl_hash.h"
 #include "khash.h"
-#include "kvec.h"
+#include "utlist.h"
 
 #include "cryptobox.h"
 #include "libutil/str_util.h"
@@ -35,12 +35,12 @@
 
 struct ucl_hash_elt {
 	const ucl_object_t *obj;
-	size_t ar_idx;
+	struct ucl_hash_elt *prev, *next;
 };
 
 struct ucl_hash_struct {
 	void *hash;
-	kvec_t(const ucl_object_t *) ar;
+	struct ucl_hash_elt *head;
 	bool caseless;
 };
 
@@ -48,7 +48,6 @@ static uint64_t
 ucl_hash_seed (void)
 {
 	static uint64_t seed;
-
 	if (seed == 0) {
 #ifdef UCL_RANDOM_FUNCTION
 		seed = UCL_RANDOM_FUNCTION;
@@ -149,8 +148,7 @@ ucl_hash_create (bool ignore_case)
 	new = UCL_ALLOC (sizeof (ucl_hash_t));
 	if (new != NULL) {
 		void *h;
-		kv_init (new->ar);
-
+		new->head = NULL;
 		new->caseless = ignore_case;
 		if (ignore_case) {
 			h = (void *)kh_init (ucl_hash_caseless_node);
@@ -204,7 +202,6 @@ void ucl_hash_destroy (ucl_hash_t* hashlin, ucl_hash_free_func func)
 		kh_destroy (ucl_hash_node, h);
 	}
 
-	kv_destroy (hashlin->ar);
 	UCL_FREE (sizeof (*hashlin), hashlin);
 }
 
@@ -226,9 +223,8 @@ ucl_hash_insert (ucl_hash_t* hashlin, const ucl_object_t *obj,
 		k = kh_put (ucl_hash_caseless_node, h, obj, &ret);
 		if (ret > 0) {
 			elt = &kh_value (h, k);
-			kv_push_safe (const ucl_object_t *, hashlin->ar, obj, e0);
+			DL_APPEND(hashlin->head, elt);
 			elt->obj = obj;
-			elt->ar_idx = kv_size (hashlin->ar) - 1;
 		}
 	}
 	else {
@@ -237,9 +233,8 @@ ucl_hash_insert (ucl_hash_t* hashlin, const ucl_object_t *obj,
 		k = kh_put (ucl_hash_node, h, obj, &ret);
 		if (ret > 0) {
 			elt = &kh_value (h, k);
-			kv_push_safe (const ucl_object_t *, hashlin->ar, obj, e0);
+			DL_APPEND(hashlin->head, elt);
 			elt->obj = obj;
-			elt->ar_idx = kv_size (hashlin->ar) - 1;
 		} else if (ret < 0) {
 			goto e0;
 		}
@@ -270,8 +265,7 @@ void ucl_hash_replace (ucl_hash_t* hashlin, const ucl_object_t *old,
 			k = kh_put (ucl_hash_caseless_node, h, new, &ret);
 			pelt = &kh_value (h, k);
 			pelt->obj = new;
-			pelt->ar_idx = elt.ar_idx;
-			kv_A (hashlin->ar, elt.ar_idx) = new;
+			DL_REPLACE_ELEM(hashlin->head, &elt, pelt);
 		}
 	}
 	else {
@@ -284,15 +278,13 @@ void ucl_hash_replace (ucl_hash_t* hashlin, const ucl_object_t *old,
 			k = kh_put (ucl_hash_node, h, new, &ret);
 			pelt = &kh_value (h, k);
 			pelt->obj = new;
-			pelt->ar_idx = elt.ar_idx;
-			kv_A (hashlin->ar, elt.ar_idx) = new;
+			DL_REPLACE_ELEM(hashlin->head, &elt, pelt);
 		}
 	}
 }
 
 struct ucl_hash_real_iter {
-	const ucl_object_t **cur;
-	const ucl_object_t **end;
+	const struct ucl_hash_elt *cur;
 };
 
 #define UHI_SETERR(ep, ern) {if (ep != NULL) *ep = (ern);}
@@ -316,13 +308,13 @@ ucl_hash_iterate2 (ucl_hash_t *hashlin, ucl_hash_iter_t *iter, int *ep)
 			return NULL;
 		}
 
-		it->cur = &hashlin->ar.a[0];
-		it->end = it->cur + hashlin->ar.n;
+		it->cur = hashlin->head;
 	}
 
 	UHI_SETERR(ep, 0);
-	if (it->cur < it->end) {
-		ret = *it->cur++;
+	if (it->cur) {
+		ret = it->cur->obj;
+		it->cur = it->cur->next;
 	}
 	else {
 		UCL_FREE (sizeof (*it), it);
@@ -340,7 +332,7 @@ ucl_hash_iter_has_next (ucl_hash_t *hashlin, ucl_hash_iter_t iter)
 {
 	struct ucl_hash_real_iter *it = (struct ucl_hash_real_iter *)(iter);
 
-	return it->cur < it->end - 1;
+	return it->cur != NULL;
 }
 
 
@@ -387,7 +379,6 @@ ucl_hash_delete (ucl_hash_t* hashlin, const ucl_object_t *obj)
 {
 	khiter_t k;
 	struct ucl_hash_elt *elt;
-	size_t i;
 
 	if (hashlin == NULL) {
 		return;
@@ -400,15 +391,8 @@ ucl_hash_delete (ucl_hash_t* hashlin, const ucl_object_t *obj)
 		k = kh_get (ucl_hash_caseless_node, h, obj);
 		if (k != kh_end (h)) {
 			elt = &kh_value (h, k);
-			i = elt->ar_idx;
-			kv_del (const ucl_object_t *, hashlin->ar, elt->ar_idx);
+			DL_DELETE(hashlin->head, elt);
 			kh_del (ucl_hash_caseless_node, h, k);
-
-			/* Update subsequent elts */
-			for (; i < hashlin->ar.n; i ++) {
-				elt = &kh_value (h, i);
-				elt->ar_idx --;
-			}
 		}
 	}
 	else {
@@ -417,15 +401,8 @@ ucl_hash_delete (ucl_hash_t* hashlin, const ucl_object_t *obj)
 		k = kh_get (ucl_hash_node, h, obj);
 		if (k != kh_end (h)) {
 			elt = &kh_value (h, k);
-			i = elt->ar_idx;
-			kv_del (const ucl_object_t *, hashlin->ar, elt->ar_idx);
+			DL_DELETE(hashlin->head, elt);
 			kh_del (ucl_hash_node, h, k);
-
-			/* Update subsequent elts */
-			for (; i < hashlin->ar.n; i ++) {
-				elt = &kh_value (h, i);
-				elt->ar_idx --;
-			}
 		}
 	}
 }
@@ -437,9 +414,7 @@ ucl_hash_reserve (ucl_hash_t *hashlin, size_t sz)
 		return false;
 	}
 
-	if (sz > hashlin->ar.m) {
-		kv_resize_safe (const ucl_object_t *, hashlin->ar, sz, e0);
-
+	if (sz > kh_size((khash_t(ucl_hash_node) *)hashlin->hash)) {
 		if (hashlin->caseless) {
 			khash_t(ucl_hash_caseless_node) *h = (khash_t(
 					ucl_hash_caseless_node) *)
@@ -451,35 +426,34 @@ ucl_hash_reserve (ucl_hash_t *hashlin, size_t sz)
 			kh_resize (ucl_hash_node, h, sz * 2);
 		}
 	}
+
 	return true;
-	e0:
-	return false;
 }
 
 static int
 ucl_hash_cmp_icase (const void *a, const void *b)
 {
-	const ucl_object_t *oa = *(const ucl_object_t **)a,
-		*ob = *(const ucl_object_t **)b;
+	const struct ucl_hash_elt *oa = (const struct ucl_hash_elt *)a,
+		*ob = (const struct ucl_hash_elt *)b;
 
-	if (oa->keylen == ob->keylen) {
-		return rspamd_lc_cmp (oa->key, ob->key, oa->keylen);
+	if (oa->obj->keylen == ob->obj->keylen) {
+		return rspamd_lc_cmp (oa->obj->key, ob->obj->key, oa->obj->keylen);
 	}
 
-	return ((int)(oa->keylen)) - ob->keylen;
+	return ((int)(oa->obj->keylen)) - ob->obj->keylen;
 }
 
 static int
 ucl_hash_cmp_case_sens (const void *a, const void *b)
 {
-	const ucl_object_t *oa = *(const ucl_object_t **)a,
-			*ob = *(const ucl_object_t **)b;
+	const struct ucl_hash_elt *oa = (const struct ucl_hash_elt *)a,
+			*ob = (const struct ucl_hash_elt *)b;
 
-	if (oa->keylen == ob->keylen) {
-		return memcmp (oa->key, ob->key, oa->keylen);
+	if (oa->obj->keylen == ob->obj->keylen) {
+		return memcmp (oa->obj->key, ob->obj->key, oa->obj->keylen);
 	}
 
-	return ((int)(oa->keylen)) - ob->keylen;
+	return ((int)(oa->obj->keylen)) - ob->obj->keylen;
 }
 
 void
@@ -487,18 +461,18 @@ ucl_hash_sort (ucl_hash_t *hashlin, enum ucl_object_keys_sort_flags fl)
 {
 
 	if (fl & UCL_SORT_KEYS_ICASE) {
-		qsort (hashlin->ar.a, hashlin->ar.n, sizeof (ucl_object_t *),
-				ucl_hash_cmp_icase);
+		DL_SORT(hashlin->head, ucl_hash_cmp_icase);
 	}
 	else {
-		qsort (hashlin->ar.a, hashlin->ar.n, sizeof (ucl_object_t *),
-				ucl_hash_cmp_case_sens);
+		DL_SORT(hashlin->head, ucl_hash_cmp_case_sens);
 	}
 
 	if (fl & UCL_SORT_KEYS_RECURSIVE) {
-		for (size_t i = 0; i < hashlin->ar.n; i ++) {
-			if (ucl_object_type (hashlin->ar.a[i]) == UCL_OBJECT) {
-				ucl_hash_sort (hashlin->ar.a[i]->value.ov, fl);
+		struct ucl_hash_elt *elt;
+
+		DL_FOREACH(hashlin->head, elt) {
+			if (ucl_object_type (elt->obj) == UCL_OBJECT) {
+				ucl_hash_sort (elt->obj->value.ov, fl);
 			}
 		}
 	}


More information about the Commits mailing list