talloc: change TALLOC_MAGIC for version 2.0.0
[metze/samba/wip.git] / lib / talloc / talloc.c
index 1f7e52439f81619ae6f6cb78fdb09f140f878ecd..c8ecac1619fa423dce8d1a3cf30bb9fe18bf9fb5 100644 (file)
@@ -57,7 +57,9 @@
 
 
 #define MAX_TALLOC_SIZE 0x10000000
-#define TALLOC_MAGIC 0xe814ec70
+#define TALLOC_MAGIC_V1 0xe814ec70
+#define TALLOC_MAGIC_V2 0xe814ec80
+#define TALLOC_MAGIC    TALLOC_MAGIC_V2
 #define TALLOC_FLAG_FREE 0x01
 #define TALLOC_FLAG_LOOP 0x02
 #define TALLOC_FLAG_POOL 0x04          /* This is a talloc pool */
@@ -138,14 +140,35 @@ struct talloc_chunk {
 #define TC_HDR_SIZE ((sizeof(struct talloc_chunk)+15)&~15)
 #define TC_PTR_FROM_CHUNK(tc) ((void *)(TC_HDR_SIZE + (char*)tc))
 
+static void (*talloc_abort_fn)(const char *reason);
+
+void talloc_set_abort_fn(void (*abort_fn)(const char *reason))
+{
+       talloc_abort_fn = abort_fn;
+}
+
+static void talloc_abort(const char *reason)
+{
+       if (!talloc_abort_fn) {
+               TALLOC_ABORT(reason);
+       }
+
+       talloc_abort_fn(reason);
+}
+
+static void talloc_abort_magic_v1(void)
+{
+       talloc_abort("Bad talloc magic value - old magic v1 used");
+}
+
 static void talloc_abort_double_free(void)
 {
-       TALLOC_ABORT("Bad talloc magic value - double free"); 
+       talloc_abort("Bad talloc magic value - double free");
 }
 
 static void talloc_abort_unknown_value(void)
 {
-       TALLOC_ABORT("Bad talloc magic value - unknown value"); 
+       talloc_abort("Bad talloc magic value - unknown value");
 }
 
 /* panic if we get a bad magic value */
@@ -154,6 +177,10 @@ static inline struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr)
        const char *pp = (const char *)ptr;
        struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, pp - TC_HDR_SIZE);
        if (unlikely((tc->flags & (TALLOC_FLAG_FREE | ~0xF)) != TALLOC_MAGIC)) { 
+               if ((tc->flags & (~0xF)) == TALLOC_MAGIC_V1)) {
+                       talloc_abort_magic_v1();
+               }
+
                if (tc->flags & TALLOC_FLAG_FREE) {
                        talloc_abort_double_free();
                } else {
@@ -564,7 +591,7 @@ static inline int _talloc_free(void *ptr)
                pool_object_count = talloc_pool_objectcount(pool);
 
                if (*pool_object_count == 0) {
-                       TALLOC_ABORT("Pool object count zero!");
+                       talloc_abort("Pool object count zero!");
                }
 
                *pool_object_count -= 1;
@@ -806,6 +833,41 @@ void *talloc_check_name(const void *ptr, const char *name)
        return NULL;
 }
 
+static void talloc_abort_type_missmatch(const char *location,
+                                       const char *name,
+                                       const char *expected)
+{
+       const char *reason;
+
+       reason = talloc_asprintf(NULL,
+                                "%s: Type mismatch: name[%s] expected[%s]",
+                                location,
+                                name?name:"NULL",
+                                expected);
+       if (!reason) {
+               reason = "Type mismatch";
+       }
+
+       talloc_abort(reason);
+}
+
+void *_talloc_get_type_abort(const void *ptr, const char *name, const char *location)
+{
+       const char *pname;
+
+       if (unlikely(ptr == NULL)) {
+               talloc_abort_type_missmatch(location, NULL, name);
+               return NULL;
+       }
+
+       pname = talloc_get_name(ptr);
+       if (likely(pname == name || strcmp(pname, name) == 0)) {
+               return discard_const_p(void, ptr);
+       }
+
+       talloc_abort_type_missmatch(location, pname, name);
+       return NULL;
+}
 
 /*
   this is for compatibility with older versions of talloc
@@ -957,6 +1019,11 @@ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *n
                return NULL;
        }
 
+       /* don't let anybody try to realloc a talloc_pool */
+       if (unlikely(tc->flags & TALLOC_FLAG_POOL)) {
+               return NULL;
+       }
+
        /* don't shrink if we have less than 1k to gain */
        if ((size < tc->size) && ((tc->size - size) < 1024)) {
                tc->size = size;