X-Git-Url: https://git.ozlabs.org/?p=ccan;a=blobdiff_plain;f=ccan%2Ftal%2Ftal.c;h=88bcb5ab6135257529eda0e999df024507c0386d;hp=474c0ff045c72f3f03c426851dc3e47ed365e4ba;hb=84b29c907c7608a024f65c4ef6803a1f5bb80ccd;hpb=f243444490e8dcdaa399942b70e72d03005370f7 diff --git a/ccan/tal/tal.c b/ccan/tal/tal.c index 474c0ff0..88bcb5ab 100644 --- a/ccan/tal/tal.c +++ b/ccan/tal/tal.c @@ -9,6 +9,7 @@ #include #include #include +#include //#define TAL_DEBUG 1 @@ -482,6 +483,7 @@ static struct tal_hdr *remove_node(struct tal_hdr *t) void tal_free(const tal_t *ctx) { struct tal_hdr *t; + int saved_errno = errno; if (!ctx) return; @@ -489,6 +491,7 @@ void tal_free(const tal_t *ctx) t = debug_tal(to_tal_hdr(ctx)); remove_node(t); del_tree(t); + errno = saved_errno; } void *tal_steal_(const tal_t *new_parent, const tal_t *ctx) @@ -654,22 +657,29 @@ tal_t *tal_parent(const tal_t *ctx) return from_tal_hdr(group->parent_child->parent); } -void *tal_realloc_(tal_t *ctx, size_t size) +bool tal_resize_(tal_t **ctxp, size_t size) { struct tal_hdr *old_t, *t, **prev; struct group *group; struct children *child; - old_t = debug_tal(to_tal_hdr(ctx)); + old_t = debug_tal(to_tal_hdr(*ctxp)); + + /* Don't hand silly sizes to realloc. */ + if (size >> (CHAR_BIT*sizeof(size) - 1)) { + call_error("Reallocation size overflow"); + return false; + } t = resizefn(old_t, size + sizeof(struct tal_hdr)); if (!t) { call_error("Reallocation failure"); - tal_free(old_t); - return NULL; + return false; } + + /* If it didn't move, we're done! */ if (t == old_t) - return ctx; + return true; update_bounds(t); /* Fix up linked list pointer. */ @@ -689,13 +699,13 @@ void *tal_realloc_(tal_t *ctx, size_t size) assert(child->parent == old_t); child->parent = t; } - - return from_tal_hdr(debug_tal(t)); + *ctxp = from_tal_hdr(debug_tal(t)); + return true; } char *tal_strdup(const tal_t *ctx, const char *p) { - return tal_memdup(ctx, p, strlen(p)+1); + return tal_dup(ctx, char, p, strlen(p)+1, 0); } char *tal_strndup(const tal_t *ctx, const char *p, size_t n) @@ -704,20 +714,35 @@ char *tal_strndup(const tal_t *ctx, const char *p, size_t n) if (strlen(p) < n) n = strlen(p); - ret = tal_memdup(ctx, p, n+1); + ret = tal_dup(ctx, char, p, n, 1); if (ret) ret[n] = '\0'; return ret; } -void *tal_memdup(const tal_t *ctx, const void *p, size_t n) +void *tal_dup_(const tal_t *ctx, const void *p, size_t n, size_t extra, + const char *label) { void *ret; - if (ctx == TAL_TAKE) - return (void *)p; + /* Beware overflow! */ + if (n + extra < n || n + extra + sizeof(struct tal_hdr) < n) { + call_error("dup size overflow"); + if (ctx == TAL_TAKE) + tal_free(p); + return NULL; + } - ret = tal_arr(ctx, char, n); + if (ctx == TAL_TAKE) { + if (unlikely(!p)) + return NULL; + if (!tal_resize_((void **)&p, n + extra)) { + tal_free(p); + return NULL; + } + return (void *)p; + } + ret = tal_alloc_(ctx, n + extra, false, label); if (ret) memcpy(ret, p, n); return ret; @@ -755,7 +780,10 @@ char *tal_vasprintf(const tal_t *ctx, const char *fmt, va_list ap) if (ret < max) break; - buf = tal_resize(buf, max *= 2); + if (!tal_resize(&buf, max *= 2)) { + tal_free(buf); + buf = NULL; + } } if (ctx == TAL_TAKE) tal_free(fmt);