From 45be1c7ba4382d85c742a241687bbc6d5a2ebd8c Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 20 Apr 2010 15:30:57 +1000 Subject: talloc: there is no ambiguity when freeing a ptr with a null parent 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 --- lib/talloc/ABI/talloc-2.0.3.sigs | 62 ++++++++++++++++++++++++++++++++++++++++ lib/talloc/configure.ac | 2 +- lib/talloc/talloc.c | 7 +++++ lib/talloc/testsuite.c | 33 +++++++++++++++++++++ lib/talloc/wscript | 2 +- 5 files changed, 104 insertions(+), 2 deletions(-) create mode 100644 lib/talloc/ABI/talloc-2.0.3.sigs (limited to 'lib/talloc') diff --git a/lib/talloc/ABI/talloc-2.0.3.sigs b/lib/talloc/ABI/talloc-2.0.3.sigs new file mode 100644 index 0000000000..6e236d52ac --- /dev/null +++ b/lib/talloc/ABI/talloc-2.0.3.sigs @@ -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) diff --git a/lib/talloc/configure.ac b/lib/talloc/configure.ac index d160f08298..258910e57e 100644 --- a/lib/talloc/configure.ac +++ b/lib/talloc/configure.ac @@ -1,5 +1,5 @@ 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) diff --git a/lib/talloc/talloc.c b/lib/talloc/talloc.c index d3b5565fe2..bd364ed51b 100644 --- a/lib/talloc/talloc.c +++ b/lib/talloc/talloc.c @@ -1128,6 +1128,13 @@ _PUBLIC_ int _talloc_free(void *ptr, const char *location) 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); diff --git a/lib/talloc/testsuite.c b/lib/talloc/testsuite.c index f33805d6b0..5e9b3ec8f2 100644 --- a/lib/talloc/testsuite.c +++ b/lib/talloc/testsuite.c @@ -1132,6 +1132,37 @@ static bool test_pool(void) 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); @@ -1185,6 +1216,8 @@ bool torture_local_talloc(struct torture_context *tctx) ret &= test_talloc_free_in_destructor(); test_reset(); ret &= test_pool(); + test_reset(); + ret &= test_free_ref_null_context(); if (ret) { test_reset(); diff --git a/lib/talloc/wscript b/lib/talloc/wscript index e6da2da027..3a875060d7 100644 --- a/lib/talloc/wscript +++ b/lib/talloc/wscript @@ -1,7 +1,7 @@ #!/usr/bin/env python APPNAME = 'talloc' -VERSION = '2.0.2' +VERSION = '2.0.3' blddir = 'bin' -- cgit