summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2004-09-28 21:41:33 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 12:59:28 -0500
commitda0e9d5f6239b809f7a930e22ff473fd38117ca1 (patch)
treedcbdedc1eb3ba55635bc3d1824354b7c27df9962
parentb79602fab5ad67aaff4492afd90b52e3292c7ef1 (diff)
downloadsamba-da0e9d5f6239b809f7a930e22ff473fd38117ca1.tar.gz
samba-da0e9d5f6239b809f7a930e22ff473fd38117ca1.tar.bz2
samba-da0e9d5f6239b809f7a930e22ff473fd38117ca1.zip
r2737: fixed up a corner case where talloc_unreference() and talloc_free()
might not place the pointer in the context specified in the docs. The code was assuming that pointer was at the head of the child list, which it may not be, depending on what other operations have happened in between. (This used to be commit e62bd7ef7ec80365ab00ce5b2051b7dc1726304b)
-rw-r--r--source4/lib/talloc.c23
1 files changed, 17 insertions, 6 deletions
diff --git a/source4/lib/talloc.c b/source4/lib/talloc.c
index bb2ed9449c..4b796fbbd0 100644
--- a/source4/lib/talloc.c
+++ b/source4/lib/talloc.c
@@ -63,6 +63,17 @@ static struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr)
return tc;
}
+
+/*
+ return the parent chunk of a pointer
+*/
+static struct talloc_chunk *talloc_parent_chunk(const void *ptr)
+{
+ struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
+ while (tc->prev) tc=tc->prev;
+ return tc->parent;
+}
+
/*
Allocate a bit of memory as a child of an existing pointer
*/
@@ -185,8 +196,7 @@ void *talloc_unreference(const void *context, const void *ptr)
}
for (h=tc->refs;h;h=h->next) {
- struct talloc_chunk *tc2 = talloc_chunk_from_ptr(h);
- const void *parent = tc2->parent?tc2->parent+1:null_context;
+ const void *parent = talloc_parent_chunk(h);
if (parent == context) break;
}
if (h == NULL) {
@@ -354,11 +364,12 @@ int talloc_free(void *ptr)
void *child = tc->child+1;
const void *new_parent = null_context;
if (tc->child->refs) {
- struct talloc_chunk *ref = talloc_chunk_from_ptr(tc->child->refs);
- if (ref->parent) new_parent = ref->parent+1;
+ struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs);
+ if (p) new_parent = p+1;
}
- if (new_parent == null_context && tc->parent) {
- new_parent = tc->parent+1;
+ if (new_parent == null_context) {
+ struct talloc_chunk *p = talloc_parent_chunk(ptr);
+ if (p) new_parent = p+1;
}
talloc_free(talloc_steal(new_parent, child));
}