From 680aa496521811e7c60afb940bcae5024f4c6adb Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Mon, 3 Dec 2012 19:29:39 +1030 Subject: [PATCH] tal: add tal_expand(). Helper to reallocate and append to an array. Signed-off-by: Rusty Russell --- ccan/tal/tal.c | 31 +++++++++++++++++++++++++++++++ ccan/tal/tal.h | 23 +++++++++++++++++++++++ ccan/tal/test/run-expand.c | 32 ++++++++++++++++++++++++++++++++ ccan/tal/test/run-overflow.c | 15 ++++++++++++++- 4 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 ccan/tal/test/run-expand.c diff --git a/ccan/tal/tal.c b/ccan/tal/tal.c index 4f7d5678..5c0aec07 100644 --- a/ccan/tal/tal.c +++ b/ccan/tal/tal.c @@ -712,6 +712,37 @@ bool tal_resize_(tal_t **ctxp, size_t size, size_t count) return true; } +bool tal_expand_(tal_t **ctxp, const void *src, size_t size, size_t count) +{ + struct length *l; + bool ret = false; + + l = find_property(debug_tal(to_tal_hdr(*ctxp)), LENGTH); + + /* Check for additive overflow */ + if (l->count + count < count) { + call_error("dup size overflow"); + goto out; + } + + /* Don't point src inside thing we're expanding! */ + assert(src < *ctxp + || (char *)src >= (char *)(*ctxp) + (size * l->count)); + + /* Note: updates l->count. */ + if (!tal_resize_(ctxp, size, l->count + count)) + goto out; + + memcpy((char *)*ctxp + size * (l->count - count), + src, count * size); + ret = true; + +out: + if (taken(src)) + tal_free(src); + return ret; +} + void *tal_dup_(const tal_t *ctx, const void *p, size_t size, size_t n, size_t extra, bool add_count, const char *label) diff --git a/ccan/tal/tal.h b/ccan/tal/tal.h index 091eb034..28be3f20 100644 --- a/ccan/tal/tal.h +++ b/ccan/tal/tal.h @@ -305,6 +305,28 @@ void tal_set_backend(void *(*alloc_fn)(size_t size), void (*free_fn)(void *), void (*error_fn)(const char *msg)); +/** + * tal_expand - expand a tal array with contents. + * @a1p: a pointer to the tal array to expand. + * @a2: the second array (can be take()). + * @num2: the number of elements in the second array. + * + * Note that *@a1 and @a2 should be the same type. tal_count(@a1) will + * be increased by @num2. + * + * Example: + * int *arr1 = tal_arrz(NULL, int, 2); + * int arr2[2] = { 1, 3 }; + * + * tal_expand(&arr1, arr2, 2); + * assert(tal_count(arr1) == 4); + * assert(arr1[2] == 1); + * assert(arr1[3] == 3); + */ +#define tal_expand(a1p, a2, num2) \ + tal_expand_((void **)(a1p), (a2), sizeof**(a1p), \ + (num2) + 0*sizeof(*(a1p) == (a2))) + /** * tal_check - set the allocation or error functions to use @@ -374,6 +396,7 @@ void *tal_dup_(const tal_t *ctx, const void *p, size_t size, tal_t *tal_steal_(const tal_t *new_parent, const tal_t *t); bool tal_resize_(tal_t **ctxp, size_t size, size_t count); +bool tal_expand_(tal_t **ctxp, const void *src, size_t size, size_t count); bool tal_add_destructor_(const tal_t *ctx, void (*destroy)(void *me)); bool tal_del_destructor_(const tal_t *ctx, void (*destroy)(void *me)); diff --git a/ccan/tal/test/run-expand.c b/ccan/tal/test/run-expand.c new file mode 100644 index 00000000..2edb31f6 --- /dev/null +++ b/ccan/tal/test/run-expand.c @@ -0,0 +1,32 @@ +#include +#include +#include + +int main(void) +{ + int *a; + const int arr[] = { 1, 2 }; + + plan_tests(13); + + a = tal_arrz(NULL, int, 1); + ok1(a); + + ok1(tal_expand(&a, arr, 2)); + ok1(tal_count(a) == 3); + ok1(a[0] == 0); + ok1(a[1] == 1); + ok1(a[2] == 2); + + ok1(tal_expand(&a, take(tal_arrz(NULL, int, 1)), 1)); + ok1(tal_count(a) == 4); + ok1(a[0] == 0); + ok1(a[1] == 1); + ok1(a[2] == 2); + ok1(a[3] == 0); + ok1(tal_first(NULL) == a && !tal_next(NULL, a)); + + tal_free(a); + + return exit_status(); +} diff --git a/ccan/tal/test/run-overflow.c b/ccan/tal/test/run-overflow.c index 989fcd2a..c5daf97d 100644 --- a/ccan/tal/test/run-overflow.c +++ b/ccan/tal/test/run-overflow.c @@ -13,8 +13,9 @@ int main(void) { void *p; int *pi, *origpi; + char *cp; - plan_tests(26); + plan_tests(30); tal_set_backend(NULL, NULL, NULL, my_error); @@ -81,5 +82,17 @@ int main(void) ok1(error_count == 1); ok1(!tal_first(NULL)); + /* Overflow on expand addition. */ + cp = tal_arr(p, char, 100); + ok1(!tal_expand(&cp, NULL, (size_t)-99UL)); + ok1(error_count == 2); + tal_free(cp); + + /* Overflow when multiplied by size */ + origpi = tal_arr(NULL, int, 100); + ok1(!tal_expand(&origpi, NULL, (size_t)-1UL / sizeof(int))); + ok1(error_count == 3); + tal_free(origpi); + return exit_status(); } -- 2.39.2