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