]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
basic/alloc-util: add greedy_realloc_append()
authorDan Streetman <ddstreet@ieee.org>
Fri, 17 Feb 2023 17:59:18 +0000 (12:59 -0500)
committerDan Streetman <ddstreet@ieee.org>
Wed, 5 Jul 2023 21:33:55 +0000 (17:33 -0400)
Add function to perform greedy realloc as well as copying the new data into the
newly allocated space.

src/basic/alloc-util.c
src/basic/alloc-util.h
src/test/test-alloc-util.c

index 6063943c88ab55ba355919f3f1b9d1f902d243d2..fc98610a0f8eaeaf57d3b5afdcaa6edda14c4896 100644 (file)
@@ -103,6 +103,33 @@ 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;
+}
+
 void *expand_to_usable(void *ptr, size_t newsize _unused_) {
         return ptr;
 }
index 9a62381df1d452a6654ee6cd3641cde88a706793..9abe8620c86066bb9d82ae73e8bfa0e2040cc98d 100644 (file)
@@ -147,6 +147,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]))
@@ -154,6 +155,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_;                            \
index df6139005f1f5835f29e5bd52912f846e7c6de8a..57cb886c4111455785f3dd98958b61b863082173 100644 (file)
@@ -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) {