tal: tal_steal() fix.
authorRusty Russell <rusty@rustcorp.com.au>
Mon, 19 Nov 2012 00:23:57 +0000 (10:53 +1030)
committerRusty Russell <rusty@rustcorp.com.au>
Mon, 19 Nov 2012 00:23:57 +0000 (10:53 +1030)
We call remove_node() in tal_steal, then re-use the node.  So it's important
that we always unlink the group property from the node for that case.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
ccan/tal/tal.c
ccan/tal/test/run-steal.c [new file with mode: 0644]

index ff25db19afb8a3b16da50ef254687a85b50cc71e..474c0ff045c72f3f03c426851dc3e47ed365e4ba 100644 (file)
@@ -455,6 +455,7 @@ static struct tal_hdr *remove_node(struct tal_hdr *t)
 
                /* Are we the only one? */
                if (prev == t) {
+                       struct prop_hdr *next = (*prop)->next;
                        struct children *c = group->parent_child;
                        /* Is this the group embedded in the child property? */
                        if (group == &c->group) {
@@ -462,9 +463,9 @@ static struct tal_hdr *remove_node(struct tal_hdr *t)
                        } else {
                                /* Empty group, so free it. */
                                list_del_from(&c->group.list, &group->list.n);
-                               *prop = group->hdr.next;
                                freefn(group);
                        }
+                       *prop = next;
                        return c->parent;
                } else {
                        /* Move property to next node. */
diff --git a/ccan/tal/test/run-steal.c b/ccan/tal/test/run-steal.c
new file mode 100644 (file)
index 0000000..74a8235
--- /dev/null
@@ -0,0 +1,40 @@
+#include <ccan/tal/tal.h>
+#include <ccan/tal/tal.c>
+#include <ccan/tap/tap.h>
+
+int main(void)
+{
+       char *p[5];
+       unsigned int i;
+
+       plan_tests(9);
+
+       p[0] = NULL;
+       for (i = 1; i < 5; i++)
+               p[i] = tal(p[i-1], char);
+
+       tal_check(NULL, "check");
+       /* Steal node with no children. */
+       ok1(tal_steal(p[0], p[4]) == p[4]);
+       tal_check(NULL, "check");
+       /* Noop steal. */
+       ok1(tal_steal(p[0], p[4]) == p[4]);
+       tal_check(NULL, "check");
+       /* Steal with children. */
+       ok1(tal_steal(p[0], p[1]) == p[1]);
+       tal_check(NULL, "check");
+       /* Noop steal. */
+       ok1(tal_steal(p[0], p[1]) == p[1]);
+       tal_check(NULL, "check");
+       /* Steal from direct child. */
+       ok1(tal_steal(p[0], p[2]) == p[2]);
+       tal_check(NULL, "check");
+
+       ok1(tal_parent(p[1]) == p[0]);
+       ok1(tal_parent(p[2]) == p[0]);
+       ok1(tal_parent(p[3]) == p[2]);
+       ok1(tal_parent(p[4]) == p[0]);
+       tal_free(p[0]);
+
+       return exit_status();
+}