From a665cccd2ef81e704e90bb228bbd14c0afb031af Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 24 May 2006 07:31:02 +0000 Subject: r15852: patch from Rusty to make talloc_set_destructor() and talloc_steal() type safe. This only works on recent gcc versions. With other compilers it reverts to a non-typesafe cast The patch also ensures that talloc_free() does not change error on systems where free() can change errno (This used to be commit babbff5f777642f559747f6d0697bc7c3a5e798d) --- source4/lib/talloc/talloc.c | 14 +++++++------ source4/lib/talloc/talloc.h | 47 ++++++++++++++++++++++++++++-------------- source4/lib/talloc/testsuite.c | 2 +- 3 files changed, 40 insertions(+), 23 deletions(-) (limited to 'source4') diff --git a/source4/lib/talloc/talloc.c b/source4/lib/talloc/talloc.c index 67478fc9d4..b34369cb16 100644 --- a/source4/lib/talloc/talloc.c +++ b/source4/lib/talloc/talloc.c @@ -30,12 +30,12 @@ inspired by http://swapped.cc/halloc/ */ - #include "config.h" #include #include #include +#include #ifdef HAVE_SYS_TYPES_H #include @@ -218,7 +218,7 @@ void *_talloc(const void *context, size_t size) if the destructor fails then the free is failed, and the memory can be continued to be used */ -void talloc_set_destructor(const void *ptr, int (*destructor)(void *)) +void _talloc_set_destructor(const void *ptr, int (*destructor)(void *)) { struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); tc->destructor = destructor; @@ -235,10 +235,9 @@ void talloc_increase_ref_count(const void *ptr) /* helper for talloc_reference() */ -static int talloc_reference_destructor(void *ptr) +static int talloc_reference_destructor(struct talloc_reference_handle *handle) { - struct talloc_reference_handle *handle = ptr; - struct talloc_chunk *tc1 = talloc_chunk_from_ptr(ptr); + struct talloc_chunk *tc1 = talloc_chunk_from_ptr(handle); struct talloc_chunk *tc2 = talloc_chunk_from_ptr(handle->ptr); if (tc1->destructor != (talloc_destructor_t)-1) { tc1->destructor = NULL; @@ -534,6 +533,7 @@ void talloc_free_children(void *ptr) int talloc_free(void *ptr) { struct talloc_chunk *tc; + int old_errno; if (ptr == NULL) { return -1; @@ -586,7 +586,9 @@ int talloc_free(void *ptr) tc->flags |= TALLOC_FLAG_FREE; + old_errno = errno; free(tc); + errno = old_errno; return 0; } @@ -667,7 +669,7 @@ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *n ptr on success, or NULL if it could not be transferred. passing NULL as ptr will always return NULL with no side effects. */ -void *talloc_steal(const void *new_ctx, const void *ptr) +void *_talloc_steal(const void *new_ctx, const void *ptr) { struct talloc_chunk *tc, *new_tc; diff --git a/source4/lib/talloc/talloc.h b/source4/lib/talloc/talloc.h index 99410241a6..be2b305753 100644 --- a/source4/lib/talloc/talloc.h +++ b/source4/lib/talloc/talloc.h @@ -40,6 +40,34 @@ typedef void TALLOC_CTX; #define TALLOC_DEPRECATED 0 #endif +#ifndef PRINTF_ATTRIBUTE +#if (__GNUC__ >= 3) +/** Use gcc attribute to check printf fns. a1 is the 1-based index of + * the parameter containing the format, and a2 the index of the first + * argument. Note that some gcc 2.x versions don't handle this + * properly **/ +#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2))) +#else +#define PRINTF_ATTRIBUTE(a1, a2) +#endif +#endif + +/* try to make talloc_set_destructor() and talloc_steal() type safe, + if we have a recent gcc */ +#if (__GNUC__ >= 3) +#define _TALLOC_TYPEOF(ptr) __typeof__(ptr) +#define talloc_set_destructor(ptr, function) \ + do { \ + int (*_talloc_destructor_fn)(typeof(ptr)) = (function); \ + _talloc_set_destructor((ptr), (void *)_talloc_destructor_fn); \ + } while(0) +#define _TALLOC_CHECK_TYPE(type,val) +#else +#define talloc_set_destructor(ptr, function) \ + _talloc_set_destructor((ptr), (int (*)(void *))(function)) +#define _TALLOC_TYPEOF(ptr) void * +#endif + /* useful macros for creating type checked pointers */ #define talloc(ctx, type) (type *)talloc_named_const(ctx, sizeof(type), #type) #define talloc_size(ctx, size) talloc_named_const(ctx, size, __location__) @@ -70,7 +98,7 @@ typedef void TALLOC_CTX; #define talloc_get_type(ptr, type) (type *)talloc_check_name(ptr, #type) #define talloc_find_parent_bytype(ptr, type) (type *)talloc_find_parent_byname(ptr, #type) - +#define talloc_steal(ctx, ptr) (_TALLOC_TYPEOF(ptr))_talloc_steal((ctx),(ptr)) #if TALLOC_DEPRECATED #define talloc_zero_p(ctx, type) talloc_zero(ctx, type) @@ -80,22 +108,9 @@ typedef void TALLOC_CTX; #define talloc_destroy(ctx) talloc_free(ctx) #endif -#ifndef PRINTF_ATTRIBUTE -#if (__GNUC__ >= 3) -/** Use gcc attribute to check printf fns. a1 is the 1-based index of - * the parameter containing the format, and a2 the index of the first - * argument. Note that some gcc 2.x versions don't handle this - * properly **/ -#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2))) -#else -#define PRINTF_ATTRIBUTE(a1, a2) -#endif -#endif - - /* The following definitions come from talloc.c */ void *_talloc(const void *context, size_t size); -void talloc_set_destructor(const void *ptr, int (*destructor)(void *)); +void _talloc_set_destructor(const void *ptr, int (*destructor)(void *)); void talloc_increase_ref_count(const void *ptr); void *talloc_reference(const void *context, const void *ptr); int talloc_unlink(const void *context, void *ptr); @@ -111,7 +126,7 @@ void *talloc_parent(const void *ptr); void *talloc_init(const char *fmt, ...) PRINTF_ATTRIBUTE(1,2); int talloc_free(void *ptr); void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name); -void *talloc_steal(const void *new_ctx, const void *ptr); +void *_talloc_steal(const void *new_ctx, const void *ptr); off_t talloc_total_size(const void *ptr); off_t talloc_total_blocks(const void *ptr); void talloc_report_full(const void *ptr, FILE *f); diff --git a/source4/lib/talloc/testsuite.c b/source4/lib/talloc/testsuite.c index 018d734cc3..f1b19041fa 100644 --- a/source4/lib/talloc/testsuite.c +++ b/source4/lib/talloc/testsuite.c @@ -850,7 +850,7 @@ static BOOL test_lifeless(void) static int loop_destructor_count; -static int test_loop_destructor(void *ptr) +static int test_loop_destructor(char *ptr) { printf("loop destructor\n"); loop_destructor_count++; -- cgit