summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStef Walter <stefw@collabora.co.uk>2011-06-07 12:06:20 +0000
committerStef Walter <stefw@collabora.co.uk>2011-06-07 12:06:20 +0000
commit7c410200143b72a5976d228d75aab59f8b965fe9 (patch)
tree7a9b4e51ed12d20fa55c81053d40e3d3fa43daae
parent0f09803ba95bcdfebf4bde509b43b3ca52cd9d3f (diff)
downloadp11-kit-7c410200143b72a5976d228d75aab59f8b965fe9.tar.gz
Fix some hash leaks and bugs.
-rw-r--r--p11-kit/hash.c20
-rw-r--r--tests/hash-test.c39
2 files changed, 49 insertions, 10 deletions
diff --git a/p11-kit/hash.c b/p11-kit/hash.c
index 9be1c32..cfa6bf7 100644
--- a/p11-kit/hash.c
+++ b/p11-kit/hash.c
@@ -152,6 +152,7 @@ hash_free (hash_t* ht)
ht->key_destroy_func (hi.ths->key);
if (ht->value_destroy_func)
ht->value_destroy_func (hi.ths->val);
+ free (hi.ths);
}
if (ht->array)
@@ -231,7 +232,7 @@ expand_array (hash_t* ht)
*/
static hash_entry_t**
-find_entry (hash_t* ht, const void* key, void* val)
+find_entry (hash_t* ht, const void* key, int create)
{
hash_entry_t** hep;
hash_entry_t* he;
@@ -247,7 +248,7 @@ find_entry (hash_t* ht, const void* key, void* val)
break;
}
- if(he || !val)
+ if(he || !create)
return hep;
/* add a new entry for non-NULL val */
@@ -257,7 +258,7 @@ find_entry (hash_t* ht, const void* key, void* val)
he->key = (void*)key;
he->next = NULL;
he->hash = hash;
- he->val = val;
+ he->val = NULL;
*hep = he;
ht->count++;
@@ -269,7 +270,7 @@ find_entry (hash_t* ht, const void* key, void* val)
void*
hash_get (hash_t* ht, const void *key)
{
- hash_entry_t** he = find_entry (ht, key, NULL);
+ hash_entry_t** he = find_entry (ht, key, 0);
if (he && *he)
return (void*)((*he)->val);
else
@@ -279,8 +280,11 @@ hash_get (hash_t* ht, const void *key)
int
hash_set (hash_t* ht, void* key, void* val)
{
- hash_entry_t** hep = find_entry (ht, key, val);
+ hash_entry_t** hep = find_entry (ht, key, 1);
if(hep && *hep) {
+ if ((*hep)->val && ht->value_destroy_func)
+ ht->value_destroy_func ((*hep)->val);
+
/* replace entry */
(*hep)->val = val;
@@ -299,7 +303,7 @@ hash_set (hash_t* ht, void* key, void* val)
int
hash_remove (hash_t* ht, const void* key)
{
- hash_entry_t** hep = find_entry (ht, key, NULL);
+ hash_entry_t** hep = find_entry (ht, key, 0);
if (hep && *hep) {
hash_entry_t* old = *hep;
@@ -428,7 +432,7 @@ unsigned int
hash_intptr_hash (const void *to_int)
{
assert (to_int);
- return (unsigned int)*((unsigned long*)to_int);
+ return (unsigned int)*((int*)to_int);
}
int
@@ -436,7 +440,7 @@ hash_intptr_equal (const void *int_one, const void *int_two)
{
assert (int_one);
assert (int_two);
- return *((unsigned long*)int_one) == *((unsigned long*)int_two);
+ return *((int*)int_one) == *((int*)int_two);
}
unsigned int
diff --git a/tests/hash-test.c b/tests/hash-test.c
index 2efa5a9..3349c26 100644
--- a/tests/hash-test.c
+++ b/tests/hash-test.c
@@ -223,6 +223,38 @@ test_hash_remove_destroys (CuTest *tc)
}
static void
+test_hash_set_destroys (CuTest *tc)
+{
+ hash_t *ht;
+ int key = 0;
+ int value = 0;
+ int value2 = 0;
+ int ret;
+
+ ht = hash_create (hash_direct_hash, hash_direct_equal, destroy_key, destroy_value);
+ CuAssertPtrNotNull (tc, ht);
+ if (!hash_set (ht, &key, &value))
+ CuFail (tc, "should not be reached");
+
+ ret = hash_set (ht, &key, &value2);
+ CuAssertIntEquals (tc, ret, 1);
+ CuAssertIntEquals (tc, 0, key);
+ CuAssertIntEquals (tc, 2, value);
+ CuAssertIntEquals (tc, 0, value2);
+
+ key = 0;
+ value = 0;
+ value2 = 0;
+
+ hash_free (ht);
+
+ CuAssertIntEquals (tc, 1, key);
+ CuAssertIntEquals (tc, 0, value);
+ CuAssertIntEquals (tc, 2, value2);
+}
+
+
+static void
test_hash_clear_destroys (CuTest *tc)
{
hash_t *ht;
@@ -260,7 +292,7 @@ static unsigned int
test_hash_intptr_with_collisions (const void *data)
{
/* lots and lots of collisions, only returns 100 values */
- return (unsigned int)(*((unsigned long*)data) % 100);
+ return (unsigned int)(*((int*)data) % 100);
}
static void
@@ -330,7 +362,7 @@ test_hash_ulongptr (CuTest *tc)
ht = hash_create (hash_ulongptr_hash, hash_ulongptr_equal, NULL, free);
for (i = 0; i < 20000; ++i) {
- value = malloc (sizeof (int));
+ value = malloc (sizeof (unsigned long));
*value = i;
if (!hash_set (ht, value, value))
CuFail (tc, "should not be reached");
@@ -357,6 +389,7 @@ main (void)
SUITE_ADD_TEST (suite, test_hash_set_get_remove);
SUITE_ADD_TEST (suite, test_hash_remove_destroys);
SUITE_ADD_TEST (suite, test_hash_set_get_clear);
+ SUITE_ADD_TEST (suite, test_hash_set_destroys);
SUITE_ADD_TEST (suite, test_hash_clear_destroys);
SUITE_ADD_TEST (suite, test_hash_free_null);
SUITE_ADD_TEST (suite, test_hash_free_destroys);
@@ -371,6 +404,8 @@ main (void)
printf ("%s\n", output->buffer);
ret = suite->failCount;
CuSuiteDelete (suite);
+ CuStringDelete (output);
+
return ret;
}