You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
136 lines
4.9 KiB
136 lines
4.9 KiB
From 774d759c39336b9650be285a88729cbfb791fce9 Mon Sep 17 00:00:00 2001
|
|
From: Dan Streetman <ddstreet@ieee.org>
|
|
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) {
|