1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 
3 #include <malloc.h>
4 #include <stdint.h>
5 
6 #include "alloc-util.h"
7 #include "macro.h"
8 #include "memory-util.h"
9 #include "random-util.h"
10 #include "tests.h"
11 
TEST(alloca)12 TEST(alloca) {
13         static const uint8_t zero[997] = { };
14         char *t;
15 
16         t = alloca_align(17, 512);
17         assert_se(!((uintptr_t)t & 0xff));
18         memzero(t, 17);
19 
20         t = alloca0_align(997, 1024);
21         assert_se(!((uintptr_t)t & 0x1ff));
22         assert_se(!memcmp(t, zero, 997));
23 }
24 
TEST(GREEDY_REALLOC)25 TEST(GREEDY_REALLOC) {
26         _cleanup_free_ int *a = NULL, *b = NULL;
27         size_t i, j;
28 
29         /* Give valgrind a chance to verify our realloc() operations */
30 
31         for (i = 0; i < 20480; i++) {
32                 assert_se(GREEDY_REALLOC(a, i + 1));
33                 assert_se(MALLOC_ELEMENTSOF(a) >= i + 1);
34                 assert_se(MALLOC_SIZEOF_SAFE(a) >= (i + 1) * sizeof(int));
35                 a[i] = (int) i;
36                 assert_se(GREEDY_REALLOC(a, i / 2));
37                 assert_se(MALLOC_ELEMENTSOF(a) >= i / 2);
38                 assert_se(MALLOC_SIZEOF_SAFE(a) >= (i / 2) * sizeof(int));
39         }
40 
41         for (j = 0; j < i / 2; j++)
42                 assert_se(a[j] == (int) j);
43 
44         for (i = 30; i < 20480; i += 7) {
45                 assert_se(GREEDY_REALLOC(b, i + 1));
46                 assert_se(MALLOC_ELEMENTSOF(b) >= i + 1);
47                 assert_se(MALLOC_SIZEOF_SAFE(b) >= (i + 1) * sizeof(int));
48                 b[i] = (int) i;
49                 assert_se(GREEDY_REALLOC(b, i / 2));
50                 assert_se(MALLOC_ELEMENTSOF(b) >= i / 2);
51                 assert_se(MALLOC_SIZEOF_SAFE(b) >= (i / 2) * sizeof(int));
52         }
53 
54         for (j = 30; j < i / 2; j += 7)
55                 assert_se(b[j] == (int) j);
56 }
57 
TEST(memdup_multiply_and_greedy_realloc)58 TEST(memdup_multiply_and_greedy_realloc) {
59         static const int org[] = { 1, 2, 3 };
60         _cleanup_free_ int *dup;
61         size_t i;
62         int *p;
63 
64         dup = memdup_suffix0_multiply(org, sizeof(int), 3);
65         assert_se(dup);
66         assert_se(dup[0] == 1);
67         assert_se(dup[1] == 2);
68         assert_se(dup[2] == 3);
69         assert_se(((uint8_t*) dup)[sizeof(int) * 3] == 0);
70         free(dup);
71 
72         dup = memdup_multiply(org, sizeof(int), 3);
73         assert_se(dup);
74         assert_se(dup[0] == 1);
75         assert_se(dup[1] == 2);
76         assert_se(dup[2] == 3);
77 
78         memzero(dup + 3, malloc_usable_size(dup) - sizeof(int) * 3);
79 
80         p = dup;
81         assert_se(GREEDY_REALLOC0(dup, 2) == p);
82 
83         p = GREEDY_REALLOC0(dup, 10);
84         assert_se(p == dup);
85         assert_se(MALLOC_ELEMENTSOF(p) >= 10);
86         assert_se(p[0] == 1);
87         assert_se(p[1] == 2);
88         assert_se(p[2] == 3);
89         for (i = 3; i < MALLOC_ELEMENTSOF(p); i++)
90                 assert_se(p[i] == 0);
91 }
92 
TEST(bool_assign)93 TEST(bool_assign) {
94         bool b, c, *cp = &c, d, e, f, g, h;
95 
96         b = 123;
97         *cp = -11;
98         d = 0xF & 0xFF;
99         e = b & d;
100         f = 0x0;
101         g = cp;    /* cast from pointer */
102         h = NULL;  /* cast from pointer */
103 
104         assert_se(b);
105         assert_se(c);
106         assert_se(d);
107         assert_se(e);
108         assert_se(!f);
109         assert_se(g);
110         assert_se(!h);
111 }
112 
113 static int cleanup_counter = 0;
114 
cleanup1(void * a)115 static void cleanup1(void *a) {
116         log_info("%s(%p)", __func__, a);
117         assert_se(++cleanup_counter == *(int*) a);
118 }
cleanup2(void * a)119 static void cleanup2(void *a) {
120         log_info("%s(%p)", __func__, a);
121         assert_se(++cleanup_counter == *(int*) a);
122 }
cleanup3(void * a)123 static void cleanup3(void *a) {
124         log_info("%s(%p)", __func__, a);
125         assert_se(++cleanup_counter == *(int*) a);
126 }
127 
TEST(cleanup_order)128 TEST(cleanup_order) {
129         _cleanup_(cleanup1) int x1 = 4, x2 = 3;
130         _cleanup_(cleanup3) int z = 2;
131         _cleanup_(cleanup2) int y = 1;
132         log_debug("x1: %p", &x1);
133         log_debug("x2: %p", &x2);
134         log_debug("y: %p", &y);
135         log_debug("z: %p", &z);
136 }
137 
TEST(auto_erase_memory)138 TEST(auto_erase_memory) {
139         _cleanup_(erase_and_freep) uint8_t *p1, *p2;
140 
141         /* print address of p2, else e.g. clang-11 will optimize it out */
142         log_debug("p1: %p p2: %p", &p1, &p2);
143 
144         assert_se(p1 = new(uint8_t, 4703)); /* use prime size, to ensure that there will be free space at the
145                                              * end of the allocation, since malloc() enforces alignment */
146         assert_se(p2 = new(uint8_t, 4703));
147 
148         assert_se(genuine_random_bytes(p1, 4703, RANDOM_BLOCK) == 0);
149 
150         /* before we exit the scope, do something with this data, so that the compiler won't optimize this away */
151         memcpy(p2, p1, 4703);
152         for (size_t i = 0; i < 4703; i++)
153                 assert_se(p1[i] == p2[i]);
154 }
155 
156 #define TEST_SIZES(f, n)                                                \
157         do {                                                            \
158                 log_debug("requested=%zu vs. malloc_size=%zu vs. gcc_size=%zu", \
159                           n * sizeof(*f),                               \
160                           malloc_usable_size(f),                        \
161                           __builtin_object_size(f, 0));                 \
162                 assert_se(MALLOC_ELEMENTSOF(f) >= n);                   \
163                 assert_se(MALLOC_SIZEOF_SAFE(f) >= sizeof(*f) * n);     \
164                 assert_se(malloc_usable_size(f) >= sizeof(*f) * n);     \
165                 assert_se(__builtin_object_size(f, 0) >= sizeof(*f) * n); \
166         } while (false)
167 
TEST(malloc_size_safe)168 TEST(malloc_size_safe) {
169         _cleanup_free_ uint32_t *f = NULL;
170         size_t n = 4711;
171 
172         /* Let's check the macros and built-ins work on NULL and return the expected values */
173         assert_se(MALLOC_ELEMENTSOF((float*) NULL) == 0);
174         assert_se(MALLOC_SIZEOF_SAFE((float*) NULL) == 0);
175         assert_se(malloc_usable_size(NULL) == 0); /* as per man page, this is safe and defined */
176         assert_se(__builtin_object_size(NULL, 0) == SIZE_MAX); /* as per docs SIZE_MAX is returned for pointers where the size isn't known */
177 
178         /* Then, let's try these macros once with constant size values, so that __builtin_object_size()
179          * definitely can work (as long as -O2 is used when compiling) */
180         assert_se(f = new(uint32_t, n));
181         TEST_SIZES(f, n);
182 
183         /* Finally, let's use some dynamically sized allocations, to make sure this doesn't deteriorate */
184         for (unsigned i = 0; i < 50; i++) {
185                 _cleanup_free_ uint64_t *g = NULL;
186                 size_t m;
187 
188                 m = random_u64_range(16*1024);
189                 assert_se(g = new(uint64_t, m));
190                 TEST_SIZES(g, m);
191         }
192 }
193 
194 DEFINE_TEST_MAIN(LOG_DEBUG);
195