From 774d759c39336b9650be285a88729cbfb791fce9 Mon Sep 17 00:00:00 2001 From: Dan Streetman Date: Fri, 17 Feb 2023 12:59:18 -0500 Subject: [PATCH] basic/alloc-util: add greedy_realloc_append() Add function to perform greedy realloc as well as copying the new data into the newly allocated space. (cherry picked from commit 3f27ba99542385174a1bc40beb737a8622790912) Related: RHEL-16182 --- src/basic/alloc-util.c | 27 ++++++++++++++++++++++++ src/basic/alloc-util.h | 4 ++++ src/test/test-alloc-util.c | 43 ++++++++++++++++++++++++++++++++++++-- 3 files changed, 72 insertions(+), 2 deletions(-) diff --git a/src/basic/alloc-util.c b/src/basic/alloc-util.c index b030f454b2..e566350ba2 100644 --- a/src/basic/alloc-util.c +++ b/src/basic/alloc-util.c @@ -102,3 +102,30 @@ void* greedy_realloc0( return q; } + +void* greedy_realloc_append( + void **p, + size_t *n_p, + const void *from, + size_t n_from, + size_t size) { + + uint8_t *q; + + assert(p); + assert(n_p); + assert(from || n_from == 0); + + if (n_from > SIZE_MAX - *n_p) + return NULL; + + q = greedy_realloc(p, *n_p + n_from, size); + if (!q) + return NULL; + + memcpy_safe(q + *n_p * size, from, n_from * size); + + *n_p += n_from; + + return q; +} diff --git a/src/basic/alloc-util.h b/src/basic/alloc-util.h index e4c8b71a2b..28d0cf5ea9 100644 --- a/src/basic/alloc-util.h +++ b/src/basic/alloc-util.h @@ -146,6 +146,7 @@ static inline void *memdup_suffix0_multiply(const void *p, size_t size, size_t n void* greedy_realloc(void **p, size_t need, size_t size); void* greedy_realloc0(void **p, size_t need, size_t size); +void* greedy_realloc_append(void **p, size_t *n_p, const void *from, size_t n_from, size_t size); #define GREEDY_REALLOC(array, need) \ greedy_realloc((void**) &(array), (need), sizeof((array)[0])) @@ -153,6 +154,9 @@ void* greedy_realloc0(void **p, size_t need, size_t size); #define GREEDY_REALLOC0(array, need) \ greedy_realloc0((void**) &(array), (need), sizeof((array)[0])) +#define GREEDY_REALLOC_APPEND(array, n_array, from, n_from) \ + greedy_realloc_append((void**) &(array), (size_t*) &(n_array), (from), (n_from), sizeof((array)[0])) + #define alloca0(n) \ ({ \ char *_new_; \ diff --git a/src/test/test-alloc-util.c b/src/test/test-alloc-util.c index df6139005f..57cb886c41 100644 --- a/src/test/test-alloc-util.c +++ b/src/test/test-alloc-util.c @@ -23,8 +23,8 @@ TEST(alloca) { } TEST(GREEDY_REALLOC) { - _cleanup_free_ int *a = NULL, *b = NULL; - size_t i, j; + _cleanup_free_ int *a = NULL, *b = NULL, *c = NULL; + size_t i, j, n_c = 0; /* Give valgrind a chance to verify our realloc() operations */ @@ -53,6 +53,45 @@ TEST(GREEDY_REALLOC) { for (j = 30; j < i / 2; j += 7) assert_se(b[j] == (int) j); + + size_t n_from = 10; + int from[n_from]; + for (i = 0; i < 2048; i++) { + for (j = 0; j < n_from; j++) + from[j] = n_from * i + j; + + _cleanup_free_ int *before = NULL; + size_t n_before = 0; + assert_se(GREEDY_REALLOC_APPEND(before, n_before, c, n_c)); + assert_se(before); + assert_se(n_before == n_c); + assert_se(memcmp_safe(c, before, n_c) == 0); + + assert_se(GREEDY_REALLOC_APPEND(c, n_c, from, n_from)); + assert_se(n_c == n_before + n_from); + assert_se(MALLOC_ELEMENTSOF(c) >= n_c); + assert_se(MALLOC_SIZEOF_SAFE(c) >= n_c * sizeof(int)); + assert_se(memcmp_safe(c, before, n_before) == 0); + assert_se(memcmp_safe(&c[n_before], from, n_from) == 0); + + before = mfree(before); + assert_se(!before); + n_before = 0; + assert_se(GREEDY_REALLOC_APPEND(before, n_before, c, n_c)); + assert_se(before); + assert_se(n_before == n_c); + assert_se(memcmp_safe(c, before, n_c) == 0); + + assert_se(GREEDY_REALLOC_APPEND(c, n_c, NULL, 0)); + assert_se(c); + assert_se(n_c == n_before); + assert_se(MALLOC_ELEMENTSOF(c) >= n_c); + assert_se(MALLOC_SIZEOF_SAFE(c) >= n_c * sizeof(int)); + assert_se(memcmp_safe(c, before, n_c) == 0); + } + + for (j = 0; j < i * n_from; j++) + assert_se(c[j] == (int) j); } TEST(memdup_multiply_and_greedy_realloc) {