Actually finish memcache_add_talloc
authorVolker Lendecke <vl@samba.org>
Thu, 13 Nov 2008 22:50:19 +0000 (23:50 +0100)
committerVolker Lendecke <vl@samba.org>
Fri, 14 Nov 2008 18:55:46 +0000 (19:55 +0100)
This fixes a memleak found by Martin Zielinski <mz@seh.de>. Thanks for
looking closely!

Volker

source/lib/memcache.c
source/torture/torture.c

index e1426bc811a862529a9ec48f2648980025c9ed1b..8ff75c42ca42872b9d9c543d43831017a581af08 100644 (file)
@@ -214,6 +214,16 @@ static void memcache_delete_element(struct memcache *cache,
        }
        DLIST_REMOVE(cache->mru, e);
 
+       if (memcache_is_talloc(e->n)) {
+               DATA_BLOB cache_key, cache_value;
+               void *ptr;
+
+               memcache_element_parse(e, &cache_key, &cache_value);
+               SMB_ASSERT(cache_value.length == sizeof(ptr));
+               memcpy(&ptr, cache_value.data, sizeof(ptr));
+               TALLOC_FREE(ptr);
+       }
+
        cache->size -= memcache_element_size(e->keylength, e->valuelength);
 
        SAFE_FREE(e);
@@ -276,6 +286,12 @@ void memcache_add(struct memcache *cache, enum memcache_number n,
                memcache_element_parse(e, &cache_key, &cache_value);
 
                if (value.length <= cache_value.length) {
+                       if (memcache_is_talloc(e->n)) {
+                               void *ptr;
+                               SMB_ASSERT(cache_value.length == sizeof(ptr));
+                               memcpy(&ptr, cache_value.data, sizeof(ptr));
+                               TALLOC_FREE(ptr);
+                       }
                        /*
                         * We can reuse the existing record
                         */
@@ -334,7 +350,8 @@ void memcache_add(struct memcache *cache, enum memcache_number n,
 void memcache_add_talloc(struct memcache *cache, enum memcache_number n,
                         DATA_BLOB key, void *ptr)
 {
-       memcache_add(cache, n, key, data_blob_const(&ptr, sizeof(ptr)));
+       void *p = talloc_move(cache, &ptr);
+       memcache_add(cache, n, key, data_blob_const(&p, sizeof(p)));
 }
 
 void memcache_flush(struct memcache *cache, enum memcache_number n)
index e909f8cec812bef90c37bbc9d680fe5e15a16f5b..8419be76a5098e880680e54aeadab9a49f87e4a9 100644 (file)
@@ -5188,6 +5188,11 @@ static bool run_local_memcache(int dummy)
        DATA_BLOB d1, d2, d3;
        DATA_BLOB v1, v2, v3;
 
+       TALLOC_CTX *mem_ctx;
+       char *str1, *str2;
+       size_t size1, size2;
+       bool ret = false;
+
        cache = memcache_init(NULL, 100);
 
        if (cache == NULL) {
@@ -5239,7 +5244,33 @@ static bool run_local_memcache(int dummy)
        }
 
        TALLOC_FREE(cache);
-       return true;
+
+       cache = memcache_init(NULL, 0);
+
+       mem_ctx = talloc_init("foo");
+
+       str1 = talloc_strdup(mem_ctx, "string1");
+       str2 = talloc_strdup(mem_ctx, "string2");
+
+       memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
+                           data_blob_string_const("torture"), str1);
+       size1 = talloc_total_size(cache);
+
+       memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
+                           data_blob_string_const("torture"), str2);
+       size2 = talloc_total_size(cache);
+
+       printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
+
+       if (size2 > size1) {
+               printf("memcache leaks memory!\n");
+               goto fail;
+       }
+
+       ret = true;
+ fail:
+       TALLOC_FREE(cache);
+       return ret;
 }
 
 static double create_procs(bool (*fn)(int), bool *result)