talloc: there is no ambiguity when freeing a ptr with a null parent
authorAndrew Tridgell <tridge@samba.org>
Tue, 20 Apr 2010 05:30:57 +0000 (15:30 +1000)
committerAndrew Tridgell <tridge@samba.org>
Tue, 20 Apr 2010 05:50:27 +0000 (15:50 +1000)
when a ptr has a single reference and a NULL parent, then
talloc_free(ptr) is not ambiguous, as the caller could not have done a
talloc_free(NULL) to free the memory

Pair-Programmed-With: Rusty Russell <rusty@samba.org>

lib/talloc/ABI/talloc-2.0.3.sigs [new file with mode: 0644]
lib/talloc/configure.ac
lib/talloc/talloc.c
lib/talloc/testsuite.c
lib/talloc/wscript
source4/min_versions.m4

diff --git a/lib/talloc/ABI/talloc-2.0.3.sigs b/lib/talloc/ABI/talloc-2.0.3.sigs
new file mode 100644 (file)
index 0000000..6e236d5
--- /dev/null
@@ -0,0 +1,62 @@
+_talloc: void *(const void *, size_t)
+_talloc_array: void *(const void *, size_t, unsigned int, const char *)
+_talloc_free: int (void *, const char *)
+_talloc_get_type_abort: void *(const void *, const char *, const char *)
+_talloc_memdup: void *(const void *, const void *, size_t, const char *)
+_talloc_move: void *(const void *, const void *)
+_talloc_realloc: void *(const void *, void *, size_t, const char *)
+_talloc_realloc_array: void *(const void *, void *, size_t, unsigned int, const char *)
+_talloc_reference_loc: void *(const void *, const void *, const char *)
+_talloc_set_destructor: void (const void *, int (*)(void *))
+_talloc_steal_loc: void *(const void *, const void *, const char *)
+_talloc_zero: void *(const void *, size_t, const char *)
+_talloc_zero_array: void *(const void *, size_t, unsigned int, const char *)
+talloc_asprintf: char *(const void *, const char *, ...)
+talloc_asprintf_append: char *(char *, const char *, ...)
+talloc_asprintf_append_buffer: char *(char *, const char *, ...)
+talloc_autofree_context: void *(void)
+talloc_check_name: void *(const void *, const char *)
+talloc_disable_null_tracking: void (void)
+talloc_enable_leak_report: void (void)
+talloc_enable_leak_report_full: void (void)
+talloc_enable_null_tracking: void (void)
+talloc_enable_null_tracking_no_autofree: void (void)
+talloc_find_parent_byname: void *(const void *, const char *)
+talloc_free_children: void (void *)
+talloc_get_name: const char *(const void *)
+talloc_get_size: size_t (const void *)
+talloc_increase_ref_count: int (const void *)
+talloc_init: void *(const char *, ...)
+talloc_is_parent: int (const void *, const void *)
+talloc_named: void *(const void *, size_t, const char *, ...)
+talloc_named_const: void *(const void *, size_t, const char *)
+talloc_parent: void *(const void *)
+talloc_parent_name: const char *(const void *)
+talloc_pool: void *(const void *, size_t)
+talloc_realloc_fn: void *(const void *, void *, size_t)
+talloc_reference_count: size_t (const void *)
+talloc_reparent: void *(const void *, const void *, const void *)
+talloc_report: void (const void *, FILE *)
+talloc_report_depth_cb: void (const void *, int, int, void (*)(const void *, int, int, int, void *), void *)
+talloc_report_depth_file: void (const void *, int, int, FILE *)
+talloc_report_full: void (const void *, FILE *)
+talloc_set_abort_fn: void (void (*)(const char *))
+talloc_set_log_fn: void (void (*)(const char *))
+talloc_set_log_stderr: void (void)
+talloc_set_name: const char *(const void *, const char *, ...)
+talloc_set_name_const: void (const void *, const char *)
+talloc_show_parents: void (const void *, FILE *)
+talloc_strdup: char *(const void *, const char *)
+talloc_strdup_append: char *(char *, const char *)
+talloc_strdup_append_buffer: char *(char *, const char *)
+talloc_strndup: char *(const void *, const char *, size_t)
+talloc_strndup_append: char *(char *, const char *, size_t)
+talloc_strndup_append_buffer: char *(char *, const char *, size_t)
+talloc_total_blocks: size_t (const void *)
+talloc_total_size: size_t (const void *)
+talloc_unlink: int (const void *, void *)
+talloc_vasprintf: char *(const void *, const char *, va_list)
+talloc_vasprintf_append: char *(char *, const char *, va_list)
+talloc_vasprintf_append_buffer: char *(char *, const char *, va_list)
+talloc_version_major: int (void)
+talloc_version_minor: int (void)
index d160f08298d14be9aeb5309ea5ff2a404ebcba0b..258910e57ec43c3ced6a91966a3037f3abd60e3a 100644 (file)
@@ -1,5 +1,5 @@
 AC_PREREQ(2.50)
 AC_PREREQ(2.50)
-AC_INIT(talloc, 2.0.2)
+AC_INIT(talloc, 2.0.3)
 AC_CONFIG_SRCDIR([talloc.c])
 AC_SUBST(datarootdir)
 AC_CONFIG_HEADER(config.h)
 AC_CONFIG_SRCDIR([talloc.c])
 AC_SUBST(datarootdir)
 AC_CONFIG_HEADER(config.h)
index d3b5565fe2c1e7241d6c5df2883c2a2e56508ad5..bd364ed51b8adbfd626e23b788ed775e50656c32 100644 (file)
@@ -1128,6 +1128,13 @@ _PUBLIC_ int _talloc_free(void *ptr, const char *location)
        if (unlikely(tc->refs != NULL)) {
                struct talloc_reference_handle *h;
 
        if (unlikely(tc->refs != NULL)) {
                struct talloc_reference_handle *h;
 
+               if (talloc_parent(ptr) == null_context && tc->refs->next == NULL) {
+                       /* in this case we do know which parent should
+                          get this pointer, as there is really only
+                          one parent */
+                       return talloc_unlink(null_context, ptr);
+               }
+
                talloc_log("ERROR: talloc_free with references at %s\n",
                           location);
 
                talloc_log("ERROR: talloc_free with references at %s\n",
                           location);
 
index f33805d6b07bb95f202323f69df5b9d7b71852a7..5e9b3ec8f23d3c5b6f448b2dd8ed2e7590f8171b 100644 (file)
@@ -1132,6 +1132,37 @@ static bool test_pool(void)
        return true;
 }
 
        return true;
 }
 
+
+static bool test_free_ref_null_context(void)
+{
+       void *p1, *p2, *p3;
+       int ret;
+
+       talloc_disable_null_tracking();
+       p1 = talloc_new(NULL);
+       p2 = talloc_new(NULL);
+
+       p3 = talloc_reference(p2, p1);
+       torture_assert("reference", p3 == p1, "failed: reference on null");
+
+       ret = talloc_free(p1);
+       torture_assert("ref free with null parent", ret == 0, "failed: free with null parent");
+       talloc_free(p2);
+
+       talloc_enable_null_tracking_no_autofree();
+       p1 = talloc_new(NULL);
+       p2 = talloc_new(NULL);
+
+       p3 = talloc_reference(p2, p1);
+       torture_assert("reference", p3 == p1, "failed: reference on null");
+
+       ret = talloc_free(p1);
+       torture_assert("ref free with null tracked parent", ret == 0, "failed: free with null parent");
+       talloc_free(p2);
+
+       return true;
+}
+
 static void test_reset(void)
 {
        talloc_set_log_fn(test_log_stdout);
 static void test_reset(void)
 {
        talloc_set_log_fn(test_log_stdout);
@@ -1185,6 +1216,8 @@ bool torture_local_talloc(struct torture_context *tctx)
        ret &= test_talloc_free_in_destructor();
        test_reset();
        ret &= test_pool();
        ret &= test_talloc_free_in_destructor();
        test_reset();
        ret &= test_pool();
+       test_reset();
+       ret &= test_free_ref_null_context();
 
        if (ret) {
                test_reset();
 
        if (ret) {
                test_reset();
index e6da2da027c36d8dbf093893da98119456a9995b..3a875060d764d0c7efcd1a094234111a091f834c 100644 (file)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 
 APPNAME = 'talloc'
 #!/usr/bin/env python
 
 APPNAME = 'talloc'
-VERSION = '2.0.2'
+VERSION = '2.0.3'
 
 
 blddir = 'bin'
 
 
 blddir = 'bin'
index 82e7eb42c0cfd47948efb5271a9bd405b1326baa..b310133786666ac292ded9ae7e13257f61c16748 100644 (file)
@@ -1,6 +1,6 @@
 # Minimum and exact required versions for various libraries 
 # if we use the ones installed in the system.
 define(TDB_MIN_VERSION,1.2.1)
 # Minimum and exact required versions for various libraries 
 # if we use the ones installed in the system.
 define(TDB_MIN_VERSION,1.2.1)
-define(TALLOC_MIN_VERSION,2.0.2)
+define(TALLOC_MIN_VERSION,2.0.3)
 define(LDB_REQUIRED_VERSION,0.9.10)
 define(TEVENT_REQUIRED_VERSION,0.9.9)
 define(LDB_REQUIRED_VERSION,0.9.10)
 define(TEVENT_REQUIRED_VERSION,0.9.9)