summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/lib/talloc/talloc.3.xml12
-rw-r--r--source4/lib/talloc/talloc.c11
-rw-r--r--source4/lib/talloc/talloc.h6
-rw-r--r--source4/lib/talloc/testsuite.c35
4 files changed, 61 insertions, 3 deletions
diff --git a/source4/lib/talloc/talloc.3.xml b/source4/lib/talloc/talloc.3.xml
index a448e8d978..76b54ddb80 100644
--- a/source4/lib/talloc/talloc.3.xml
+++ b/source4/lib/talloc/talloc.3.xml
@@ -369,7 +369,7 @@ talloc_realloc(ctx, ptr, type, 0) ==> talloc_free(ptr);</programlisting>
known so the type-safe talloc_realloc() cannot be used.
</para>
</refsect2>
- <refsect2><title>void *talloc_steal(const void *<emphasis role="italic">new_ctx</emphasis>, const void *<emphasis role="italic">ptr</emphasis>);</title>
+ <refsect2><title>TYPE *talloc_steal(const void *<emphasis role="italic">new_ctx</emphasis>, const TYPE *<emphasis role="italic">ptr</emphasis>);</title>
<para>
The talloc_steal() function changes the parent context of a
talloc pointer. It is typically used when the context that the
@@ -387,6 +387,16 @@ talloc_realloc(ctx, ptr, type, 0) ==> talloc_free(ptr);</programlisting>
data if you do this.
</para>
</refsect2>
+ <refsect2><title>TYPE *talloc_move(const void *<emphasis role="italic">new_ctx</emphasis>, TYPE *<emphasis role="italic">ptr</emphasis>);</title>
+ <para>
+ The talloc_move() function is a wrapper around
+ talloc_steal() which zeros the source pointer after the
+ move. This avoids a potential source of bugs where a
+ programmer leaves a pointer in two structures, and uses the
+ pointer from the old structure after it has been moved to a
+ new one.
+ </para>
+ </refsect2>
<refsect2><title>size_t talloc_total_size(const void *<emphasis role="italic">ptr</emphasis>);</title>
<para>
The talloc_total_size() function returns the total size in bytes
diff --git a/source4/lib/talloc/talloc.c b/source4/lib/talloc/talloc.c
index d2f7a5d828..2b80594e80 100644
--- a/source4/lib/talloc/talloc.c
+++ b/source4/lib/talloc/talloc.c
@@ -738,6 +738,17 @@ void *_talloc_steal(const void *new_ctx, const void *ptr)
}
/*
+ a wrapper around talloc_steal() for situations where you are moving a pointer
+ between two structures, and want the old pointer to be set to NULL
+*/
+void *_talloc_move(const void *new_ctx, const void **pptr)
+{
+ void *ret = _talloc_steal(new_ctx, *pptr);
+ (*pptr) = NULL;
+ return ret;
+}
+
+/*
return the total size of a talloc pool (subtree)
*/
size_t talloc_total_size(const void *ptr)
diff --git a/source4/lib/talloc/talloc.h b/source4/lib/talloc/talloc.h
index fdc0fd3494..b9ecd8f0b8 100644
--- a/source4/lib/talloc/talloc.h
+++ b/source4/lib/talloc/talloc.h
@@ -65,15 +65,16 @@ typedef void TALLOC_CTX;
/* this extremely strange macro is to avoid some braindamaged warning
stupidity in gcc 4.1.x */
#define talloc_steal(ctx, ptr) ({ _TALLOC_TYPEOF(ptr) __talloc_steal_ret = (_TALLOC_TYPEOF(ptr))_talloc_steal((ctx),(ptr)); __talloc_steal_ret; })
-#define talloc_reference(ctx, ptr) (_TALLOC_TYPEOF(ptr))_talloc_reference((ctx),(ptr))
#else
#define talloc_set_destructor(ptr, function) \
_talloc_set_destructor((ptr), (int (*)(void *))(function))
#define _TALLOC_TYPEOF(ptr) void *
#define talloc_steal(ctx, ptr) (_TALLOC_TYPEOF(ptr))_talloc_steal((ctx),(ptr))
-#define talloc_reference(ctx, ptr) (_TALLOC_TYPEOF(ptr))_talloc_reference((ctx),(ptr))
#endif
+#define talloc_reference(ctx, ptr) (_TALLOC_TYPEOF(ptr))_talloc_reference((ctx),(ptr))
+#define talloc_move(ctx, ptr) (_TALLOC_TYPEOF(ptr))_talloc_move((ctx),&(ptr))
+
/* 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__)
@@ -127,6 +128,7 @@ int talloc_free(void *ptr);
void talloc_free_children(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_move(const void *new_ctx, const void **pptr);
size_t talloc_total_size(const void *ptr);
size_t talloc_total_blocks(const void *ptr);
void talloc_report_depth_cb(const void *ptr, int depth, int max_depth,
diff --git a/source4/lib/talloc/testsuite.c b/source4/lib/talloc/testsuite.c
index 2faa6d64c4..38039c11bf 100644
--- a/source4/lib/talloc/testsuite.c
+++ b/source4/lib/talloc/testsuite.c
@@ -731,6 +731,40 @@ static bool test_steal(void)
}
/*
+ test move
+*/
+static bool test_move(void)
+{
+ void *root;
+ struct t_move {
+ char *p;
+ int *x;
+ } *t1, *t2;
+ printf("TESTING MOVE\n");
+
+ root = talloc_new(NULL);
+
+ t1 = talloc(root, struct t_move);
+ t2 = talloc(root, struct t_move);
+ t1->p = talloc_strdup(t1, "foo");
+ t1->x = talloc(t1, int);
+ *t1->x = 42;
+
+ t2->p = talloc_move(t2, t1->p);
+ t2->x = talloc_move(t2, t1->x);
+ if (t1->p != NULL || t1->x != NULL ||
+ strcmp(t2->p, "foo") ||
+ *t2->x != 42) {
+ printf("talloc move failed\n");
+ return false;
+ }
+
+ talloc_free(root);
+
+ return true;
+}
+
+/*
test talloc_realloc_fn
*/
static bool test_realloc_fn(void)
@@ -1022,6 +1056,7 @@ bool torture_local_talloc(struct torture_context *torture)
ret &= test_realloc();
ret &= test_realloc_child();
ret &= test_steal();
+ ret &= test_move();
ret &= test_unref_reparent();
ret &= test_realloc_fn();
ret &= test_type();