]> granicus.if.org Git - p11-kit/commitdiff
Fix some hash leaks and bugs.
authorStef Walter <stefw@collabora.co.uk>
Tue, 7 Jun 2011 12:06:20 +0000 (12:06 +0000)
committerStef Walter <stefw@collabora.co.uk>
Tue, 7 Jun 2011 12:06:20 +0000 (12:06 +0000)
p11-kit/hash.c
tests/hash-test.c

index 9be1c3299792846485074529a6435b212df89c0e..cfa6bf7b163e5990fcbe8afa382157d60c41bdde 100644 (file)
@@ -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
index 2efa5a9d10785a5b5116e1981ba886e993cbaf05..3349c262462dd2309d2956c2e9b07ce5a9e85b4a 100644 (file)
@@ -222,6 +222,38 @@ test_hash_remove_destroys (CuTest *tc)
        CuAssertIntEquals (tc, 0, value);
 }
 
+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)
 {
@@ -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;
 }