hash table BUGFIX invalid length when resizing dict
Refs #1045
Refs #1093
diff --git a/src/hash_table.c b/src/hash_table.c
index 5f1af01..cc6fbd0 100644
--- a/src/hash_table.c
+++ b/src/hash_table.c
@@ -130,6 +130,30 @@
return dict_hash_multi(hash, NULL, len);
}
+static ly_bool
+lydict_resize_val_eq(void *val1_p, void *val2_p, ly_bool mod, void *cb_data)
+{
+ LY_CHECK_ARG_RET(NULL, val1_p, val2_p, 0);
+
+ const char *str1 = ((struct dict_rec *)val1_p)->value;
+ const char *str2 = ((struct dict_rec *)val2_p)->value;
+
+ LY_CHECK_ERR_RET(!str1, LOGARG(NULL, val1_p), 0);
+ LY_CHECK_ERR_RET(!str2, LOGARG(NULL, val2_p), 0);
+
+ if (mod) {
+ /* used when inserting new values */
+ if (strcmp(str1, str2) == 0) {
+ return 1;
+ }
+ } else {
+ /* used when finding the original value again in the resized table */
+ return lydict_val_eq(val1_p, val2_p, mod, cb_data);
+ }
+
+ return 0;
+}
+
API void
lydict_remove(const struct ly_ctx *ctx, const char *value)
{
@@ -168,7 +192,7 @@
* free it after it is removed from hash table
*/
val_p = match->value;
- ret = lyht_remove(ctx->dict.hash_tab, &rec, hash);
+ ret = lyht_remove_with_resize_cb(ctx->dict.hash_tab, &rec, hash, lydict_resize_val_eq);
free(val_p);
LY_CHECK_ERR_GOTO(ret, LOGINT(ctx), finish);
}
@@ -193,7 +217,7 @@
rec.refcount = 1;
LOGDBG(LY_LDGDICT, "inserting \"%s\"", rec.value);
- ret = lyht_insert(ctx->dict.hash_tab, (void *)&rec, hash, (void **)&match);
+ ret = lyht_insert_with_resize_cb(ctx->dict.hash_tab, (void *)&rec, hash, lydict_resize_val_eq, (void **)&match);
if (ret == LY_EEXIST) {
match->refcount++;
if (zerocopy) {
@@ -688,12 +712,13 @@
}
LY_ERR
-lyht_remove(struct hash_table *ht, void *val_p, uint32_t hash)
+lyht_remove_with_resize_cb(struct hash_table *ht, void *val_p, uint32_t hash, values_equal_cb resize_val_equal)
{
struct ht_rec *rec, *crec;
int32_t i;
ly_bool first_matched = 0;
LY_ERR r, ret = LY_SUCCESS;
+ values_equal_cb old_val_equal;
LY_CHECK_ERR_RET(lyht_find_first(ht, hash, &rec), LOGARG(NULL, hash), LY_ENOTFOUND); /* hash not found */
@@ -737,10 +762,24 @@
if (ht->resize == 2) {
r = (ht->used * 100) / ht->size;
if ((r < LYHT_SHRINK_PERCENTAGE) && (ht->size > LYHT_MIN_SIZE)) {
+ if (resize_val_equal) {
+ old_val_equal = lyht_set_cb(ht, resize_val_equal);
+ }
+
/* shrink */
ret = lyht_resize(ht, 0);
+
+ if (resize_val_equal) {
+ lyht_set_cb(ht, old_val_equal);
+ }
}
}
return ret;
}
+
+LY_ERR
+lyht_remove(struct hash_table *ht, void *val_p, uint32_t hash)
+{
+ return lyht_remove_with_resize_cb(ht, val_p, hash, NULL);
+}