svn commit: samba r8032 - in branches/SAMBA_4_0/source/lib/talloc: .
tridge at samba.org
tridge at samba.org
Fri Jul 1 01:25:56 GMT 2005
Author: tridge
Date: 2005-07-01 01:25:55 +0000 (Fri, 01 Jul 2005)
New Revision: 8032
WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=8032
Log:
added loop detection into talloc. Robert Collins found a way to make a
memory loop with talloc_unlink(), so now we detect it and handle it
Modified:
branches/SAMBA_4_0/source/lib/talloc/talloc.c
branches/SAMBA_4_0/source/lib/talloc/testsuite.c
Changeset:
Modified: branches/SAMBA_4_0/source/lib/talloc/talloc.c
===================================================================
--- branches/SAMBA_4_0/source/lib/talloc/talloc.c 2005-06-30 23:44:18 UTC (rev 8031)
+++ branches/SAMBA_4_0/source/lib/talloc/talloc.c 2005-07-01 01:25:55 UTC (rev 8032)
@@ -59,8 +59,9 @@
#define MAX_TALLOC_SIZE 0x10000000
-#define TALLOC_MAGIC 0xe814ec4f
-#define TALLOC_MAGIC_FREE 0x7faebef3
+#define TALLOC_MAGIC 0xe814ec70
+#define TALLOC_FLAG_FREE 0x01
+#define TALLOC_FLAG_LOOP 0x02
#define TALLOC_MAGIC_REFERENCE ((const char *)1)
/* by default we abort when given a bad pointer (such as when talloc_free() is called
@@ -100,7 +101,7 @@
talloc_destructor_t destructor;
const char *name;
union {
- unsigned magic;
+ unsigned flags;
double align_dummy;
} u;
};
@@ -109,14 +110,12 @@
static struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr)
{
struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, ptr)-1;
- if (tc->u.magic != TALLOC_MAGIC) {
- if (tc->u.magic == TALLOC_MAGIC_FREE) {
- TALLOC_ABORT("Bad talloc magic value - double free");
- } else {
- TALLOC_ABORT("Bad talloc magic value - unknown value");
- }
+ if ((tc->u.flags & ~0xF) != TALLOC_MAGIC) {
+ TALLOC_ABORT("Bad talloc magic value - unknown value");
}
-
+ if (tc->u.flags & TALLOC_FLAG_FREE) {
+ TALLOC_ABORT("Bad talloc magic value - double free");
+ }
return tc;
}
@@ -183,7 +182,7 @@
if (tc == NULL) return NULL;
tc->size = size;
- tc->u.magic = TALLOC_MAGIC;
+ tc->u.flags = TALLOC_MAGIC;
tc->destructor = NULL;
tc->child = NULL;
tc->name = NULL;
@@ -537,6 +536,11 @@
return -1;
}
+ if (tc->u.flags & TALLOC_FLAG_LOOP) {
+ /* we have a free loop - stop looping */
+ return 0;
+ }
+
if (tc->destructor) {
talloc_destructor_t d = tc->destructor;
if (d == (talloc_destructor_t)-1) {
@@ -550,6 +554,8 @@
tc->destructor = NULL;
}
+ tc->u.flags |= TALLOC_FLAG_LOOP;
+
talloc_free_children(ptr);
if (tc->parent) {
@@ -562,7 +568,7 @@
if (tc->next) tc->next->prev = tc->prev;
}
- tc->u.magic = TALLOC_MAGIC_FREE;
+ tc->u.flags |= TALLOC_FLAG_FREE;
free(tc);
return 0;
@@ -602,7 +608,7 @@
}
/* by resetting magic we catch users of the old memory */
- tc->u.magic = TALLOC_MAGIC_FREE;
+ tc->u.flags |= TALLOC_FLAG_FREE;
#if ALWAYS_REALLOC
new_ptr = malloc(size + sizeof(*tc));
@@ -614,12 +620,12 @@
new_ptr = realloc(tc, size + sizeof(*tc));
#endif
if (!new_ptr) {
- tc->u.magic = TALLOC_MAGIC;
+ tc->u.flags &= ~TALLOC_FLAG_FREE;
return NULL;
}
tc = new_ptr;
- tc->u.magic = TALLOC_MAGIC;
+ tc->u.flags &= ~TALLOC_FLAG_FREE;
if (tc->parent) {
tc->parent->child = new_ptr;
}
@@ -714,10 +720,19 @@
tc = talloc_chunk_from_ptr(ptr);
+ if (tc->u.flags & TALLOC_FLAG_LOOP) {
+ return 0;
+ }
+
+ tc->u.flags |= TALLOC_FLAG_LOOP;
+
total = tc->size;
for (c=tc->child;c;c=c->next) {
total += talloc_total_size(c+1);
}
+
+ tc->u.flags &= ~TALLOC_FLAG_LOOP;
+
return total;
}
@@ -729,10 +744,19 @@
off_t total = 0;
struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
+ if (tc->u.flags & TALLOC_FLAG_LOOP) {
+ return 0;
+ }
+
+ tc->u.flags |= TALLOC_FLAG_LOOP;
+
total++;
for (c=tc->child;c;c=c->next) {
total += talloc_total_blocks(c+1);
}
+
+ tc->u.flags &= ~TALLOC_FLAG_LOOP;
+
return total;
}
@@ -758,6 +782,12 @@
{
struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
+ if (tc->u.flags & TALLOC_FLAG_LOOP) {
+ return;
+ }
+
+ tc->u.flags |= TALLOC_FLAG_LOOP;
+
for (c=tc->child;c;c=c->next) {
if (c->name == TALLOC_MAGIC_REFERENCE) {
struct talloc_reference_handle *handle = (void *)(c+1);
@@ -774,7 +804,7 @@
talloc_report_depth(c+1, f, depth+1);
}
}
-
+ tc->u.flags &= ~TALLOC_FLAG_LOOP;
}
/*
Modified: branches/SAMBA_4_0/source/lib/talloc/testsuite.c
===================================================================
--- branches/SAMBA_4_0/source/lib/talloc/testsuite.c 2005-06-30 23:44:18 UTC (rev 8031)
+++ branches/SAMBA_4_0/source/lib/talloc/testsuite.c 2005-07-01 01:25:55 UTC (rev 8032)
@@ -818,6 +818,26 @@
}
+BOOL test_lifeless(void)
+{
+ char *top = talloc_new(NULL);
+ char *parent, *child;
+ char *child_owner = talloc_new(NULL);
+
+ printf("TESTING TALLOC_UNLINK LOOP\n");
+
+ parent = talloc_strdup(top, "parent");
+ child = talloc_strdup(parent, "child");
+ talloc_reference(child, parent);
+ talloc_reference(child_owner, child);
+ talloc_unlink(top, parent);
+ talloc_free(child);
+ talloc_report_full(top, stdout);
+ talloc_free(top);
+ return True;
+}
+
+
BOOL torture_local_talloc(void)
{
BOOL ret = True;
@@ -834,6 +854,7 @@
ret &= test_unref_reparent();
ret &= test_realloc_fn();
ret &= test_type();
+ ret &= test_lifeless();
if (ret) {
ret &= test_speed();
}
More information about the samba-cvs
mailing list