From a665cccd2ef81e704e90bb228bbd14c0afb031af Mon Sep 17 00:00:00 2001
From: Andrew Tridgell <tridge@samba.org>
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/lib')

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 <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <errno.h>
 
 #ifdef HAVE_SYS_TYPES_H
 #include <sys/types.h>
@@ -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