tal: append the length property to the initial allocation.
[ccan] / ccan / tal / tal.c
1 /* Licensed under BSD-MIT - see LICENSE file for details */
2 #include <ccan/tal/tal.h>
3 #include <ccan/compiler/compiler.h>
4 #include <ccan/list/list.h>
5 #include <ccan/take/take.h>
6 #include <ccan/alignof/alignof.h>
7 #include <assert.h>
8 #include <stdio.h>
9 #include <stddef.h>
10 #include <string.h>
11 #include <limits.h>
12 #include <errno.h>
13
14 //#define TAL_DEBUG 1
15
16 #define NOTIFY_IS_DESTRUCTOR 512
17
18 /* 32-bit type field, first byte 0 in either endianness. */
19 enum prop_type {
20         CHILDREN = 0x00c1d500,
21         NAME = 0x00111100,
22         NOTIFIER = 0x00071f00,
23         LENGTH = 0x00515300
24 };
25
26 struct tal_hdr {
27         struct list_node list;
28         struct prop_hdr *prop;
29         struct children *parent_child;
30 };
31
32 struct prop_hdr {
33         enum prop_type type;
34         struct prop_hdr *next;
35 };
36
37 struct children {
38         struct prop_hdr hdr; /* CHILDREN */
39         struct tal_hdr *parent;
40         struct list_head children; /* Head of siblings. */
41 };
42
43 struct name {
44         struct prop_hdr hdr; /* NAME */
45         char name[];
46 };
47
48 struct length {
49         struct prop_hdr hdr; /* LENGTH */
50         size_t count;
51 };
52
53 struct notifier {
54         struct prop_hdr hdr; /* NOTIFIER */
55         enum tal_notify_type types;
56         union {
57                 void (*notifyfn)(tal_t *, enum tal_notify_type, void *);
58                 void (*destroy)(tal_t *); /* If NOTIFY_IS_DESTRUCTOR set */
59         } u;
60 };
61
62 static struct {
63         struct tal_hdr hdr;
64         struct children c;
65 } null_parent = { { { &null_parent.hdr.list, &null_parent.hdr.list },
66                     &null_parent.c.hdr, NULL },
67                   { { CHILDREN, NULL },
68                     &null_parent.hdr,
69                     { { &null_parent.c.children.n,
70                         &null_parent.c.children.n } }
71                   }
72 };
73
74
75 static void *(*allocfn)(size_t size) = malloc;
76 static void *(*resizefn)(void *, size_t size) = realloc;
77 static void (*freefn)(void *) = free;
78 static void (*errorfn)(const char *msg) = (void *)abort;
79 static bool initialized = false;
80 /* Count on non-destrutor notifiers; often stays zero. */
81 static size_t notifiers = 0;
82
83 static inline void COLD call_error(const char *msg)
84 {
85         errorfn(msg);
86 }
87
88 static bool get_destroying_bit(struct children *parent_child)
89 {
90         return (size_t)parent_child & 1;
91 }
92
93 static void set_destroying_bit(struct children **parent_child)
94 {
95         *parent_child = (void *)((size_t)*parent_child | 1);
96 }
97
98 static struct children *ignore_destroying_bit(struct children *parent_child)
99 {
100         return (void *)((size_t)parent_child & ~(size_t)1);
101 }
102
103 /* This means valgrind can see leaks. */
104 static void tal_cleanup(void)
105 {
106         struct tal_hdr *i;
107
108         while ((i = list_top(&null_parent.c.children, struct tal_hdr, list)))
109                 list_del(&i->list);
110
111         /* Cleanup any taken pointers. */
112         take_cleanup();
113 }
114
115 /* For allocation failures inside ccan/take */
116 static void take_alloc_failed(const void *p)
117 {
118         tal_free(p);
119 }
120
121 /* We carefully start all real properties with a zero byte. */
122 static bool is_literal(const struct prop_hdr *prop)
123 {
124         return ((char *)prop)[0] != 0;
125 }
126
127 #ifndef NDEBUG
128 static const void *bounds_start, *bounds_end;
129
130 static void update_bounds(const void *new, size_t size)
131 {
132         if (unlikely(!bounds_start)) {
133                 bounds_start = new;
134                 bounds_end = (char *)new + size;
135         } else if (new < bounds_start)
136                 bounds_start = new;
137         else if ((char *)new + size > (char *)bounds_end)
138                 bounds_end = (char *)new + size;
139 }
140
141 static bool in_bounds(const void *p)
142 {
143         return !p
144                 || (p >= (void *)&null_parent && p <= (void *)(&null_parent + 1))
145                 || (p >= bounds_start && p <= bounds_end);
146 }
147 #else
148 static void update_bounds(const void *new, size_t size)
149 {
150 }
151
152 static bool in_bounds(const void *p)
153 {
154         return true;
155 }
156 #endif
157
158 static void check_bounds(const void *p)
159 {
160         if (!in_bounds(p))
161                 call_error("Not a valid header");
162 }
163
164 static struct tal_hdr *to_tal_hdr(const void *ctx)
165 {
166         struct tal_hdr *t;
167
168         t = (struct tal_hdr *)((char *)ctx - sizeof(struct tal_hdr));
169         check_bounds(t);
170         check_bounds(ignore_destroying_bit(t->parent_child));
171         check_bounds(t->list.next);
172         check_bounds(t->list.prev);
173         if (t->prop && !is_literal(t->prop))
174                 check_bounds(t->prop);
175         return t;
176 }
177
178 static struct tal_hdr *to_tal_hdr_or_null(const void *ctx)
179 {
180         if (!ctx)
181                 return &null_parent.hdr;
182         return to_tal_hdr(ctx);
183 }
184
185 static void *from_tal_hdr(const struct tal_hdr *hdr)
186 {
187         return (void *)(hdr + 1);
188 }
189
190 #ifdef TAL_DEBUG
191 static void *from_tal_hdr_or_null(struct tal_hdr *hdr)
192 {
193         if (hdr == &null_parent.hdr)
194                 return NULL;
195         return from_tal_hdr(hdr);
196 }
197
198 static struct tal_hdr *debug_tal(struct tal_hdr *tal)
199 {
200         tal_check(from_tal_hdr_or_null(tal), "TAL_DEBUG ");
201         return tal;
202 }
203 #else
204 static struct tal_hdr *debug_tal(struct tal_hdr *tal)
205 {
206         return tal;
207 }
208 #endif
209
210 static void notify(const struct tal_hdr *ctx,
211                    enum tal_notify_type type, const void *info)
212 {
213         const struct prop_hdr *p;
214
215         for (p = ctx->prop; p; p = p->next) {
216                 struct notifier *n;
217
218                 if (is_literal(p))
219                         break;
220                 if (p->type != NOTIFIER)
221                         continue;
222                 n = (struct notifier *)p;
223                 if (n->types & type) {
224                         if (n->types & NOTIFY_IS_DESTRUCTOR)
225                                 n->u.destroy(from_tal_hdr(ctx));
226                         else
227                                 n->u.notifyfn(from_tal_hdr(ctx), type,
228                                               (void *)info);
229                 }
230         }
231 }
232
233 static void *allocate(size_t size)
234 {
235         void *ret = allocfn(size);
236         if (!ret)
237                 call_error("allocation failed");
238         else
239                 update_bounds(ret, size);
240         return ret;
241 }
242
243 static struct prop_hdr **find_property_ptr(const struct tal_hdr *t,
244                                            enum prop_type type)
245 {
246         struct prop_hdr **p;
247
248         for (p = (struct prop_hdr **)&t->prop; *p; p = &(*p)->next) {
249                 if (is_literal(*p)) {
250                         if (type == NAME)
251                                 return p;
252                         break;
253                 }
254                 if ((*p)->type == type)
255                         return p;
256         }
257         return NULL;
258 }
259
260 static void *find_property(const struct tal_hdr *parent, enum prop_type type)
261 {
262         struct prop_hdr **p = find_property_ptr(parent, type);
263
264         if (p)
265                 return *p;
266         return NULL;
267 }
268
269 static void init_property(struct prop_hdr *hdr,
270                           struct tal_hdr *parent,
271                           enum prop_type type)
272 {
273         hdr->type = type;
274         hdr->next = parent->prop;
275         parent->prop = hdr;
276 }
277
278 static struct notifier *add_notifier_property(struct tal_hdr *t,
279                                               enum tal_notify_type types,
280                                               void (*fn)(void *,
281                                                          enum tal_notify_type,
282                                                          void *))
283 {
284         struct notifier *prop = allocate(sizeof(*prop));
285         if (prop) {
286                 init_property(&prop->hdr, t, NOTIFIER);
287                 prop->types = types;
288                 prop->u.notifyfn = fn;
289         }
290         return prop;
291 }
292
293 static enum tal_notify_type del_notifier_property(struct tal_hdr *t,
294                                                   void (*fn)(tal_t *,
295                                                              enum tal_notify_type,
296                                                              void *))
297 {
298         struct prop_hdr **p;
299
300         for (p = (struct prop_hdr **)&t->prop; *p; p = &(*p)->next) {
301                 struct notifier *n;
302
303                 if (is_literal(*p))
304                         break;
305                 if ((*p)->type != NOTIFIER)
306                         continue;
307                 n = (struct notifier *)*p;
308                 if (n->u.notifyfn == fn) {
309                         enum tal_notify_type types = n->types;
310                         *p = (*p)->next;
311                         freefn(n);
312                         return types & ~NOTIFY_IS_DESTRUCTOR;
313                 }
314         }
315         return 0;
316 }
317
318 static struct name *add_name_property(struct tal_hdr *t, const char *name)
319 {
320         struct name *prop;
321
322         prop = allocate(sizeof(*prop) + strlen(name) + 1);
323         if (prop) {
324                 init_property(&prop->hdr, t, NAME);
325                 strcpy(prop->name, name);
326         }
327         return prop;
328 }
329
330 static struct children *add_child_property(struct tal_hdr *parent,
331                                            struct tal_hdr *child)
332 {
333         struct children *prop = allocate(sizeof(*prop));
334         if (prop) {
335                 init_property(&prop->hdr, parent, CHILDREN);
336                 prop->parent = parent;
337                 list_head_init(&prop->children);
338         }
339         return prop;
340 }
341
342 static bool add_child(struct tal_hdr *parent, struct tal_hdr *child)
343 {
344         struct children *children = find_property(parent, CHILDREN);
345
346         if (!children) {
347                 if (unlikely(!initialized)) {
348                         atexit(tal_cleanup);
349                         take_allocfail(take_alloc_failed);
350                         initialized = true;
351                 }
352                 children = add_child_property(parent, child);
353                 if (!children)
354                         return false;
355         }
356         list_add(&children->children, &child->list);
357         child->parent_child = children;
358         return true;
359 }
360
361 static void del_tree(struct tal_hdr *t, const tal_t *orig)
362 {
363         struct prop_hdr **prop, *p, *next;
364
365         /* Already being destroyed?  Don't loop. */
366         if (unlikely(get_destroying_bit(t->parent_child)))
367                 return;
368
369         set_destroying_bit(&t->parent_child);
370
371         /* Call free notifiers. */
372         notify(t, TAL_NOTIFY_FREE, (tal_t *)orig);
373
374         /* Now free children and groups. */
375         prop = find_property_ptr(t, CHILDREN);
376         if (prop) {
377                 struct tal_hdr *i;
378                 struct children *c = (struct children *)*prop;
379
380                 while ((i = list_top(&c->children, struct tal_hdr, list))) {
381                         list_del(&i->list);
382                         del_tree(i, orig);
383                 }
384         }
385
386         /* Finally free our properties. */
387         for (p = t->prop; p && !is_literal(p); p = next) {
388                 next = p->next;
389                 /* LENGTH is appended, so don't free separately! */
390                 if (p->type != LENGTH)
391                         freefn(p);
392         }
393         freefn(t);
394 }
395
396 void *tal_alloc_(const tal_t *ctx, size_t size, bool clear, const char *label)
397 {
398         struct tal_hdr *child, *parent = debug_tal(to_tal_hdr_or_null(ctx));
399
400         child = allocate(sizeof(struct tal_hdr) + size);
401         if (!child)
402                 return NULL;
403         if (clear)
404                 memset(from_tal_hdr(child), 0, size);
405         child->prop = (void *)label;
406         if (!add_child(parent, child)) {
407                 freefn(child);
408                 return NULL;
409         }
410         debug_tal(parent);
411         if (notifiers)
412                 notify(parent, TAL_NOTIFY_ADD_CHILD, from_tal_hdr(child));
413         return from_tal_hdr(debug_tal(child));
414 }
415
416 static bool adjust_size(size_t *size, size_t count)
417 {
418         const size_t extra = sizeof(struct tal_hdr) + sizeof(struct length)*2;
419
420         /* Multiplication wrap */
421         if (count && unlikely(*size * count / *size != count))
422                 goto overflow;
423
424         *size *= count;
425
426         /* Make sure we don't wrap adding header/tailer. */
427         if (*size + extra < extra)
428                 goto overflow;
429         return true;
430 overflow:
431         call_error("allocation size overflow");
432         return false;
433 }
434
435 static size_t extra_for_length(size_t size)
436 {
437         size_t extra;
438         const size_t align = ALIGNOF(struct length);
439
440         /* Round up size, and add tailer. */
441         extra = ((size + align-1) & ~(align-1)) - size;
442         extra += sizeof(struct length);
443         return extra;
444 }
445
446 void *tal_alloc_arr_(const tal_t *ctx, size_t size, size_t count, bool clear,
447                      bool add_count, const char *label)
448 {
449         void *ret;
450
451         if (!adjust_size(&size, count))
452                 return NULL;
453
454         if (add_count)
455                 size += extra_for_length(size);
456
457         ret = tal_alloc_(ctx, size, clear, label);
458         if (unlikely(!ret))
459                 return ret;
460
461         if (add_count) {
462                 struct length *lprop;
463                 lprop = (struct length *)((char *)ret + size) - 1;
464                 init_property(&lprop->hdr, to_tal_hdr(ret), LENGTH);
465                 lprop->count = count;
466         }
467         return ret;
468 }
469
470 void *tal_free(const tal_t *ctx)
471 {
472         if (ctx) {
473                 struct tal_hdr *t;
474                 int saved_errno = errno;
475                 t = debug_tal(to_tal_hdr(ctx));
476                 if (notifiers)
477                         notify(ignore_destroying_bit(t->parent_child)->parent,
478                                TAL_NOTIFY_DEL_CHILD, ctx);
479                 list_del(&t->list);
480                 del_tree(t, ctx);
481                 errno = saved_errno;
482         }
483         return NULL;
484 }
485
486 void *tal_steal_(const tal_t *new_parent, const tal_t *ctx)
487 {
488         if (ctx) {
489                 struct tal_hdr *newpar, *t, *old_parent;
490
491                 newpar = debug_tal(to_tal_hdr_or_null(new_parent));
492                 t = debug_tal(to_tal_hdr(ctx));
493
494                 /* Unlink it from old parent. */
495                 list_del(&t->list);
496                 old_parent = ignore_destroying_bit(t->parent_child)->parent;
497
498                 if (unlikely(!add_child(newpar, t))) {
499                         /* We can always add to old parent, becuase it has a
500                          * children property already. */
501                         if (!add_child(old_parent, t))
502                                 abort();
503                         return NULL;
504                 }
505                 debug_tal(newpar);
506                 if (notifiers)
507                         notify(t, TAL_NOTIFY_STEAL, new_parent);
508         }
509         return (void *)ctx;
510 }
511
512 bool tal_add_destructor_(const tal_t *ctx, void (*destroy)(void *me))
513 {
514         tal_t *t = debug_tal(to_tal_hdr(ctx));
515         return add_notifier_property(t, TAL_NOTIFY_FREE|NOTIFY_IS_DESTRUCTOR,
516                                      (void *)destroy);
517 }
518
519 bool tal_add_notifier_(const tal_t *ctx, enum tal_notify_type types,
520                        void (*callback)(tal_t *, enum tal_notify_type, void *))
521 {
522         tal_t *t = debug_tal(to_tal_hdr(ctx));
523         struct notifier *n;
524
525         assert(types);
526         assert((types & ~(TAL_NOTIFY_FREE | TAL_NOTIFY_STEAL | TAL_NOTIFY_MOVE
527                           | TAL_NOTIFY_RESIZE | TAL_NOTIFY_RENAME
528                           | TAL_NOTIFY_ADD_CHILD | TAL_NOTIFY_DEL_CHILD
529                           | TAL_NOTIFY_ADD_NOTIFIER
530                           | TAL_NOTIFY_DEL_NOTIFIER)) == 0);
531
532         /* Don't call notifier about itself: set types after! */
533         n = add_notifier_property(t, 0, callback);
534         if (unlikely(!n))
535                 return false;
536
537         if (notifiers)
538                 notify(t, TAL_NOTIFY_ADD_NOTIFIER, callback);
539
540         n->types = types;
541         if (types != TAL_NOTIFY_FREE)
542                 notifiers++;
543         return true;
544 }
545
546 bool tal_del_notifier_(const tal_t *ctx,
547                        void (*callback)(tal_t *, enum tal_notify_type, void *))
548 {
549         struct tal_hdr *t = debug_tal(to_tal_hdr(ctx));
550         enum tal_notify_type types;
551
552         types = del_notifier_property(t, callback);
553         if (types) {
554                 notify(t, TAL_NOTIFY_DEL_NOTIFIER, callback);
555                 if (types != TAL_NOTIFY_FREE)
556                         notifiers--;
557                 return true;
558         }
559         return false;
560 }
561
562 bool tal_del_destructor_(const tal_t *ctx, void (*destroy)(void *me))
563 {
564         return tal_del_notifier_(ctx, (void *)destroy);
565 }
566
567 bool tal_set_name_(tal_t *ctx, const char *name, bool literal)
568 {
569         struct tal_hdr *t = debug_tal(to_tal_hdr(ctx));
570         struct prop_hdr **prop = find_property_ptr(t, NAME);
571
572         /* Get rid of any old name */
573         if (prop) {
574                 struct name *name = (struct name *)*prop;
575                 if (is_literal(&name->hdr))
576                         *prop = NULL;
577                 else {
578                         *prop = name->hdr.next;
579                         freefn(name);
580                 }
581         }
582
583         if (literal && name[0]) {
584                 struct prop_hdr **p;
585
586                 /* Append literal. */
587                 for (p = &t->prop; *p && !is_literal(*p); p = &(*p)->next);
588                 *p = (struct prop_hdr *)name;
589         } else if (!add_name_property(t, name))
590                 return false;
591
592         debug_tal(t);
593         if (notifiers)
594                 notify(t, TAL_NOTIFY_RENAME, name);
595         return true;
596 }
597
598 const char *tal_name(const tal_t *t)
599 {
600         struct name *n;
601
602         n = find_property(debug_tal(to_tal_hdr(t)), NAME);
603         if (!n)
604                 return NULL;
605
606         if (is_literal(&n->hdr))
607                 return (const char *)n;
608         return n->name;
609 }
610
611 size_t tal_count(const tal_t *ptr)
612 {
613         struct length *l;
614
615         l = find_property(debug_tal(to_tal_hdr(ptr)), LENGTH);
616         if (!l)
617                 return 0;
618         return l->count;
619 }
620
621 /* Start one past first child: make stopping natural in circ. list. */
622 static struct tal_hdr *first_child(struct tal_hdr *parent)
623 {
624         struct children *child;
625
626         child = find_property(parent, CHILDREN);
627         if (!child)
628                 return NULL;
629
630         return list_top(&child->children, struct tal_hdr, list);
631 }
632
633 tal_t *tal_first(const tal_t *root)
634 {
635         struct tal_hdr *c, *t = debug_tal(to_tal_hdr_or_null(root));
636
637         c = first_child(t);
638         if (!c)
639                 return NULL;
640         return from_tal_hdr(c);
641 }
642
643 tal_t *tal_next(const tal_t *root, const tal_t *prev)
644 {
645         struct tal_hdr *c, *t = debug_tal(to_tal_hdr(prev)), *top;
646
647         /* Children? */
648         c = first_child(t);
649         if (c)
650                 return from_tal_hdr(c);
651
652         top = to_tal_hdr_or_null(root);
653         do {
654                 struct tal_hdr *next;
655                 struct list_node *end;
656
657                 end = &ignore_destroying_bit(t->parent_child)->children.n;
658
659                 next = list_entry(t->list.next, struct tal_hdr, list);
660                 if (&next->list != end)
661                         return from_tal_hdr(next);
662
663                 /* OK, go back to parent. */
664                 t = ignore_destroying_bit(t->parent_child)->parent;
665         } while (t != top);
666
667         return NULL;
668 }
669
670 tal_t *tal_parent(const tal_t *ctx)
671 {
672         struct tal_hdr *t;
673
674         if (!ctx)
675                 return NULL;
676
677         t = debug_tal(to_tal_hdr(ctx));
678         if (ignore_destroying_bit(t->parent_child)->parent == &null_parent.hdr)
679                 return NULL;
680         return from_tal_hdr(ignore_destroying_bit(t->parent_child)->parent);
681 }
682
683 bool tal_resize_(tal_t **ctxp, size_t size, size_t count)
684 {
685         struct tal_hdr *old_t, *t;
686         struct children *child;
687         struct prop_hdr **lenp;
688         struct length len;
689         size_t extra = 0;
690
691         old_t = debug_tal(to_tal_hdr(*ctxp));
692
693         if (!adjust_size(&size, count))
694                 return false;
695
696         lenp = find_property_ptr(old_t, LENGTH);
697         if (lenp) {
698                 /* Copy here, in case we're shrinking! */
699                 len = *(struct length *)*lenp;
700                 extra = extra_for_length(size);
701         }
702
703         t = resizefn(old_t, sizeof(struct tal_hdr) + size + extra);
704         if (!t) {
705                 call_error("Reallocation failure");
706                 return false;
707         }
708
709         /* Copy length to end. */
710         if (lenp) {
711                 struct length *new_len;
712
713                 new_len = (struct length *)((char *)(t + 1) + size);
714                 len.count = count;
715                 *new_len = len;
716
717                 /* Be careful replacing next ptr; could be old hdr. */
718                 if (lenp == &old_t->prop)
719                         t->prop = &new_len->hdr;
720                 else
721                         *lenp = &new_len->hdr;
722         }
723
724         update_bounds(t, sizeof(struct tal_hdr) + size + extra);
725
726         /* If it didn't move, we're done! */
727         if (t != old_t) {
728                 /* Fix up linked list pointers. */
729                 t->list.next->prev = t->list.prev->next = &t->list;
730
731                 /* Fix up child property's parent pointer. */
732                 child = find_property(t, CHILDREN);
733                 if (child) {
734                         assert(child->parent == old_t);
735                         child->parent = t;
736                 }
737                 *ctxp = from_tal_hdr(debug_tal(t));
738                 if (notifiers)
739                         notify(t, TAL_NOTIFY_MOVE, from_tal_hdr(old_t));
740         }
741         if (notifiers)
742                 notify(t, TAL_NOTIFY_RESIZE, (void *)size);
743
744         return true;
745 }
746
747 bool tal_expand_(tal_t **ctxp, const void *src, size_t size, size_t count)
748 {
749         struct length *l;
750         size_t old_count;
751         bool ret = false;
752
753         l = find_property(debug_tal(to_tal_hdr(*ctxp)), LENGTH);
754         old_count = l->count;
755
756         /* Check for additive overflow */
757         if (old_count + count < count) {
758                 call_error("dup size overflow");
759                 goto out;
760         }
761
762         /* Don't point src inside thing we're expanding! */
763         assert(src < *ctxp
764                || (char *)src >= (char *)(*ctxp) + (size * old_count));
765
766         if (!tal_resize_(ctxp, size, old_count + count))
767                 goto out;
768
769         memcpy((char *)*ctxp + size * old_count, src, count * size);
770         ret = true;
771
772 out:
773         if (taken(src))
774                 tal_free(src);
775         return ret;
776 }
777
778 void *tal_dup_(const tal_t *ctx, const void *p, size_t size,
779                size_t n, size_t extra, bool add_count,
780                const char *label)
781 {
782         void *ret;
783         size_t nbytes = size;
784
785         if (!adjust_size(&nbytes, n)) {
786                 if (taken(p))
787                         tal_free(p);
788                 return NULL;
789         }
790
791         /* Beware addition overflow! */
792         if (n + extra < n) {
793                 call_error("dup size overflow");
794                 if (taken(p))
795                         tal_free(p);
796                 return NULL;
797         }
798
799         if (taken(p)) {
800                 if (unlikely(!p))
801                         return NULL;
802                 if (unlikely(!tal_resize_((void **)&p, size, n + extra)))
803                         return tal_free(p);
804                 if (unlikely(!tal_steal(ctx, p)))
805                         return tal_free(p);
806                 return (void *)p;
807         }
808
809         ret = tal_alloc_arr_(ctx, size, n + extra, false, add_count, label);
810         if (ret)
811                 memcpy(ret, p, nbytes);
812         return ret;
813 }
814
815 void tal_set_backend(void *(*alloc_fn)(size_t size),
816                      void *(*resize_fn)(void *, size_t size),
817                      void (*free_fn)(void *),
818                      void (*error_fn)(const char *msg))
819 {
820         if (alloc_fn)
821                 allocfn = alloc_fn;
822         if (resize_fn)
823                 resizefn = resize_fn;
824         if (free_fn)
825                 freefn = free_fn;
826         if (error_fn)
827                 errorfn = error_fn;
828 }
829
830 #ifdef CCAN_TAL_DEBUG
831 static void dump_node(unsigned int indent, const struct tal_hdr *t)
832 {
833         unsigned int i;
834         const struct prop_hdr *p;
835
836         for (i = 0; i < indent; i++)
837                 printf("  ");
838         printf("%p", t);
839         for (p = t->prop; p; p = p->next) {
840                 struct children *c;
841                 struct name *n;
842                 struct notifier *no;
843                 struct length *l;
844                 if (is_literal(p)) {
845                         printf(" \"%s\"", (const char *)p);
846                         break;
847                 }
848                 switch (p->type) {
849                 case CHILDREN:
850                         c = (struct children *)p;
851                         printf(" CHILDREN(%p):parent=%p,children={%p,%p}\n",
852                                p, c->parent,
853                                c->children.n.prev, c->children.n.next);
854                         break;
855                 case NAME:
856                         n = (struct name *)p;
857                         printf(" NAME(%p):%s", p, n->name);
858                         break;
859                 case NOTIFIER:
860                         no = (struct notifier *)p;
861                         printf(" NOTIFIER(%p):fn=%p", p, no->u.notifyfn);
862                         break;
863                 case LENGTH:
864                         l = (struct length *)p;
865                         printf(" LENGTH(%p):count=%zu", p, l->count);
866                         break;
867                 default:
868                         printf(" **UNKNOWN(%p):%i**", p, p->type);
869                 }
870         }
871         printf("\n");
872 }
873
874 static void tal_dump_(unsigned int level, const struct tal_hdr *t)
875 {
876         struct children *children;
877
878         dump_node(level, t);
879
880         children = find_property(t, CHILDREN);
881         if (children) {
882                 struct tal_hdr *i;
883
884                 list_for_each(&children->children, i, list)
885                         tal_dump_(level + 1, i);
886         }
887 }
888
889 void tal_dump(void)
890 {
891         tal_dump_(0, &null_parent.hdr);
892 }
893 #endif /* CCAN_TAL_DEBUG */
894
895 #ifndef NDEBUG
896 static bool check_err(struct tal_hdr *t, const char *errorstr,
897                       const char *errmsg)
898 {
899         if (errorstr) {
900                 /* Try not to malloc: it may be corrupted. */
901                 char msg[strlen(errorstr) + 20 + strlen(errmsg) + 1];
902                 sprintf(msg, "%s:%p %s", errorstr, from_tal_hdr(t), errmsg);
903                 call_error(msg);
904         }
905         return false;
906 }
907
908 static bool check_node(struct children *parent_child,
909                        struct tal_hdr *t, const char *errorstr)
910 {
911         struct prop_hdr *p;
912         struct name *name = NULL;
913         struct children *children = NULL;
914         struct length *length = NULL;
915
916         if (!in_bounds(t))
917                 return check_err(t, errorstr, "invalid pointer");
918
919         if (ignore_destroying_bit(t->parent_child) != parent_child)
920                 return check_err(t, errorstr, "incorrect parent");
921
922         for (p = t->prop; p; p = p->next) {
923                 if (is_literal(p)) {
924                         if (name)
925                                 return check_err(t, errorstr,
926                                                  "has extra literal");
927                         name = (struct name *)p;
928                         break;
929                 }
930                 if (!in_bounds(p))
931                         return check_err(t, errorstr,
932                                          "has bad property pointer");
933
934                 switch (p->type) {
935                 case CHILDREN:
936                         if (children)
937                                 return check_err(t, errorstr,
938                                                  "has two child nodes");
939                         children = (struct children *)p;
940                         break;
941                 case LENGTH:
942                         if (length)
943                                 return check_err(t, errorstr,
944                                                  "has two lengths");
945                         length = (struct length *)p;
946                         break;
947                 case NOTIFIER:
948                         break;
949                 case NAME:
950                         if (name)
951                                 return check_err(t, errorstr,
952                                                  "has two names");
953                         name = (struct name *)p;
954                         break;
955                 default:
956                         return check_err(t, errorstr, "has unknown property");
957                 }
958         }
959         if (children) {
960                 struct tal_hdr *i;
961
962                 if (!list_check(&children->children, errorstr))
963                         return false;
964                 list_for_each(&children->children, i, list) {
965                         if (!check_node(children, i, errorstr))
966                                 return false;
967                 }
968         }
969         return true;
970 }
971
972 bool tal_check(const tal_t *ctx, const char *errorstr)
973 {
974         struct tal_hdr *t = to_tal_hdr_or_null(ctx);
975
976         return check_node(ignore_destroying_bit(t->parent_child), t, errorstr);
977 }
978 #else /* NDEBUG */
979 bool tal_check(const tal_t *ctx, const char *errorstr)
980 {
981         return true;
982 }
983 #endif