1/* ----------------------------------------------------------------------------
2Copyright (c) 2018-2020, Microsoft Research, Daan Leijen
3This is free software; you can redistribute it and/or modify it under the
4terms of the MIT license. A copy of the license can be found in the file
5"LICENSE" at the root of this distribution.
6-----------------------------------------------------------------------------*/
7#include "mimalloc.h"
8#include "mimalloc-types.h"
9
10#include "testhelper.h"
11
12// ---------------------------------------------------------------------------
13// Helper functions
14// ---------------------------------------------------------------------------
15bool check_zero_init(uint8_t* p, size_t size);
16#if MI_DEBUG >= 2
17bool check_debug_fill_uninit(uint8_t* p, size_t size);
18bool check_debug_fill_freed(uint8_t* p, size_t size);
19#endif
20
21// ---------------------------------------------------------------------------
22// Main testing
23// ---------------------------------------------------------------------------
24int main(void) {
25 mi_option_disable(mi_option_verbose);
26
27 // ---------------------------------------------------
28 // Zeroing allocation
29 // ---------------------------------------------------
30 CHECK_BODY("zeroinit-zalloc-small") {
31 size_t zalloc_size = MI_SMALL_SIZE_MAX / 2;
32 uint8_t* p = (uint8_t*)mi_zalloc(zalloc_size);
33 result = check_zero_init(p, zalloc_size);
34 mi_free(p);
35 };
36 CHECK_BODY("zeroinit-zalloc-large") {
37 size_t zalloc_size = MI_SMALL_SIZE_MAX * 2;
38 uint8_t* p = (uint8_t*)mi_zalloc(zalloc_size);
39 result = check_zero_init(p, zalloc_size);
40 mi_free(p);
41 };
42 CHECK_BODY("zeroinit-zalloc_small") {
43 size_t zalloc_size = MI_SMALL_SIZE_MAX / 2;
44 uint8_t* p = (uint8_t*)mi_zalloc_small(zalloc_size);
45 result = check_zero_init(p, zalloc_size);
46 mi_free(p);
47 };
48
49 CHECK_BODY("zeroinit-calloc-small") {
50 size_t calloc_size = MI_SMALL_SIZE_MAX / 2;
51 uint8_t* p = (uint8_t*)mi_calloc(calloc_size, 1);
52 result = check_zero_init(p, calloc_size);
53 mi_free(p);
54 };
55 CHECK_BODY("zeroinit-calloc-large") {
56 size_t calloc_size = MI_SMALL_SIZE_MAX * 2;
57 uint8_t* p = (uint8_t*)mi_calloc(calloc_size, 1);
58 result = check_zero_init(p, calloc_size);
59 mi_free(p);
60 };
61
62 CHECK_BODY("zeroinit-rezalloc-small") {
63 size_t zalloc_size = MI_SMALL_SIZE_MAX / 2;
64 uint8_t* p = (uint8_t*)mi_zalloc(zalloc_size);
65 result = check_zero_init(p, zalloc_size);
66 zalloc_size *= 3;
67 p = (uint8_t*)mi_rezalloc(p, zalloc_size);
68 result &= check_zero_init(p, zalloc_size);
69 mi_free(p);
70 };
71 CHECK_BODY("zeroinit-rezalloc-large") {
72 size_t zalloc_size = MI_SMALL_SIZE_MAX * 2;
73 uint8_t* p = (uint8_t*)mi_zalloc(zalloc_size);
74 result = check_zero_init(p, zalloc_size);
75 zalloc_size *= 3;
76 p = (uint8_t*)mi_rezalloc(p, zalloc_size);
77 result &= check_zero_init(p, zalloc_size);
78 mi_free(p);
79 };
80
81 CHECK_BODY("zeroinit-recalloc-small") {
82 size_t calloc_size = MI_SMALL_SIZE_MAX / 2;
83 uint8_t* p = (uint8_t*)mi_calloc(calloc_size, 1);
84 result = check_zero_init(p, calloc_size);
85 calloc_size *= 3;
86 p = (uint8_t*)mi_recalloc(p, calloc_size, 1);
87 result &= check_zero_init(p, calloc_size);
88 mi_free(p);
89 };
90 CHECK_BODY("zeroinit-recalloc-large") {
91 size_t calloc_size = MI_SMALL_SIZE_MAX * 2;
92 uint8_t* p = (uint8_t*)mi_calloc(calloc_size, 1);
93 result = check_zero_init(p, calloc_size);
94 calloc_size *= 3;
95 p = (uint8_t*)mi_recalloc(p, calloc_size, 1);
96 result &= check_zero_init(p, calloc_size);
97 mi_free(p);
98 };
99
100 // ---------------------------------------------------
101 // Zeroing in aligned API
102 // ---------------------------------------------------
103 CHECK_BODY("zeroinit-zalloc_aligned-small") {
104 size_t zalloc_size = MI_SMALL_SIZE_MAX / 2;
105 uint8_t* p = (uint8_t*)mi_zalloc_aligned(zalloc_size, MI_MAX_ALIGN_SIZE * 2);
106 result = check_zero_init(p, zalloc_size);
107 mi_free(p);
108 };
109 CHECK_BODY("zeroinit-zalloc_aligned-large") {
110 size_t zalloc_size = MI_SMALL_SIZE_MAX * 2;
111 uint8_t* p = (uint8_t*)mi_zalloc_aligned(zalloc_size, MI_MAX_ALIGN_SIZE * 2);
112 result = check_zero_init(p, zalloc_size);
113 mi_free(p);
114 };
115
116 CHECK_BODY("zeroinit-calloc_aligned-small") {
117 size_t calloc_size = MI_SMALL_SIZE_MAX / 2;
118 uint8_t* p = (uint8_t*)mi_calloc_aligned(calloc_size, 1, MI_MAX_ALIGN_SIZE * 2);
119 result = check_zero_init(p, calloc_size);
120 mi_free(p);
121 };
122 CHECK_BODY("zeroinit-calloc_aligned-large") {
123 size_t calloc_size = MI_SMALL_SIZE_MAX * 2;
124 uint8_t* p = (uint8_t*)mi_calloc_aligned(calloc_size, 1, MI_MAX_ALIGN_SIZE * 2);
125 result = check_zero_init(p, calloc_size);
126 mi_free(p);
127 };
128
129 CHECK_BODY("zeroinit-rezalloc_aligned-small") {
130 size_t zalloc_size = MI_SMALL_SIZE_MAX / 2;
131 uint8_t* p = (uint8_t*)mi_zalloc_aligned(zalloc_size, MI_MAX_ALIGN_SIZE * 2);
132 result = check_zero_init(p, zalloc_size);
133 zalloc_size *= 3;
134 p = (uint8_t*)mi_rezalloc_aligned(p, zalloc_size, MI_MAX_ALIGN_SIZE * 2);
135 result &= check_zero_init(p, zalloc_size);
136 mi_free(p);
137 };
138 CHECK_BODY("zeroinit-rezalloc_aligned-large") {
139 size_t zalloc_size = MI_SMALL_SIZE_MAX * 2;
140 uint8_t* p = (uint8_t*)mi_zalloc_aligned(zalloc_size, MI_MAX_ALIGN_SIZE * 2);
141 result = check_zero_init(p, zalloc_size);
142 zalloc_size *= 3;
143 p = (uint8_t*)mi_rezalloc_aligned(p, zalloc_size, MI_MAX_ALIGN_SIZE * 2);
144 result &= check_zero_init(p, zalloc_size);
145 mi_free(p);
146 };
147
148 CHECK_BODY("zeroinit-recalloc_aligned-small") {
149 size_t calloc_size = MI_SMALL_SIZE_MAX / 2;
150 uint8_t* p = (uint8_t*)mi_calloc_aligned(calloc_size, 1, MI_MAX_ALIGN_SIZE * 2);
151 result = check_zero_init(p, calloc_size);
152 calloc_size *= 3;
153 p = (uint8_t*)mi_recalloc_aligned(p, calloc_size, 1, MI_MAX_ALIGN_SIZE * 2);
154 result &= check_zero_init(p, calloc_size);
155 mi_free(p);
156 };
157 CHECK_BODY("zeroinit-recalloc_aligned-large") {
158 size_t calloc_size = MI_SMALL_SIZE_MAX * 2;
159 uint8_t* p = (uint8_t*)mi_calloc_aligned(calloc_size, 1, MI_MAX_ALIGN_SIZE * 2);
160 result = check_zero_init(p, calloc_size);
161 calloc_size *= 3;
162 p = (uint8_t*)mi_recalloc_aligned(p, calloc_size, 1, MI_MAX_ALIGN_SIZE * 2);
163 result &= check_zero_init(p, calloc_size);
164 mi_free(p);
165 };
166
167#if MI_DEBUG >= 2
168 // ---------------------------------------------------
169 // Debug filling
170 // ---------------------------------------------------
171 CHECK_BODY("uninit-malloc-small") {
172 size_t malloc_size = MI_SMALL_SIZE_MAX / 2;
173 uint8_t* p = (uint8_t*)mi_malloc(malloc_size);
174 result = check_debug_fill_uninit(p, malloc_size);
175 mi_free(p);
176 };
177 CHECK_BODY("uninit-malloc-large") {
178 size_t malloc_size = MI_SMALL_SIZE_MAX * 2;
179 uint8_t* p = (uint8_t*)mi_malloc(malloc_size);
180 result = check_debug_fill_uninit(p, malloc_size);
181 mi_free(p);
182 };
183
184 CHECK_BODY("uninit-malloc_small") {
185 size_t malloc_size = MI_SMALL_SIZE_MAX / 2;
186 uint8_t* p = (uint8_t*)mi_malloc_small(malloc_size);
187 result = check_debug_fill_uninit(p, malloc_size);
188 mi_free(p);
189 };
190
191 CHECK_BODY("uninit-realloc-small") {
192 size_t malloc_size = MI_SMALL_SIZE_MAX / 2;
193 uint8_t* p = (uint8_t*)mi_malloc(malloc_size);
194 result = check_debug_fill_uninit(p, malloc_size);
195 malloc_size *= 3;
196 p = (uint8_t*)mi_realloc(p, malloc_size);
197 result &= check_debug_fill_uninit(p, malloc_size);
198 mi_free(p);
199 };
200 CHECK_BODY("uninit-realloc-large") {
201 size_t malloc_size = MI_SMALL_SIZE_MAX * 2;
202 uint8_t* p = (uint8_t*)mi_malloc(malloc_size);
203 result = check_debug_fill_uninit(p, malloc_size);
204 malloc_size *= 3;
205 p = (uint8_t*)mi_realloc(p, malloc_size);
206 result &= check_debug_fill_uninit(p, malloc_size);
207 mi_free(p);
208 };
209
210 CHECK_BODY("uninit-mallocn-small") {
211 size_t malloc_size = MI_SMALL_SIZE_MAX / 2;
212 uint8_t* p = (uint8_t*)mi_mallocn(malloc_size, 1);
213 result = check_debug_fill_uninit(p, malloc_size);
214 mi_free(p);
215 };
216 CHECK_BODY("uninit-mallocn-large") {
217 size_t malloc_size = MI_SMALL_SIZE_MAX * 2;
218 uint8_t* p = (uint8_t*)mi_mallocn(malloc_size, 1);
219 result = check_debug_fill_uninit(p, malloc_size);
220 mi_free(p);
221 };
222
223 CHECK_BODY("uninit-reallocn-small") {
224 size_t malloc_size = MI_SMALL_SIZE_MAX / 2;
225 uint8_t* p = (uint8_t*)mi_mallocn(malloc_size, 1);
226 result = check_debug_fill_uninit(p, malloc_size);
227 malloc_size *= 3;
228 p = (uint8_t*)mi_reallocn(p, malloc_size, 1);
229 result &= check_debug_fill_uninit(p, malloc_size);
230 mi_free(p);
231 };
232 CHECK_BODY("uninit-reallocn-large") {
233 size_t malloc_size = MI_SMALL_SIZE_MAX * 2;
234 uint8_t* p = (uint8_t*)mi_mallocn(malloc_size, 1);
235 result = check_debug_fill_uninit(p, malloc_size);
236 malloc_size *= 3;
237 p = (uint8_t*)mi_reallocn(p, malloc_size, 1);
238 result &= check_debug_fill_uninit(p, malloc_size);
239 mi_free(p);
240 };
241
242 CHECK_BODY("uninit-malloc_aligned-small") {
243 size_t malloc_size = MI_SMALL_SIZE_MAX / 2;
244 uint8_t* p = (uint8_t*)mi_malloc_aligned(malloc_size, MI_MAX_ALIGN_SIZE * 2);
245 result = check_debug_fill_uninit(p, malloc_size);
246 mi_free(p);
247 };
248 CHECK_BODY("uninit-malloc_aligned-large") {
249 size_t malloc_size = MI_SMALL_SIZE_MAX * 2;
250 uint8_t* p = (uint8_t*)mi_malloc_aligned(malloc_size, MI_MAX_ALIGN_SIZE * 2);
251 result = check_debug_fill_uninit(p, malloc_size);
252 mi_free(p);
253 };
254
255 CHECK_BODY("uninit-realloc_aligned-small") {
256 size_t malloc_size = MI_SMALL_SIZE_MAX / 2;
257 uint8_t* p = (uint8_t*)mi_malloc_aligned(malloc_size, MI_MAX_ALIGN_SIZE * 2);
258 result = check_debug_fill_uninit(p, malloc_size);
259 malloc_size *= 3;
260 p = (uint8_t*)mi_realloc_aligned(p, malloc_size, MI_MAX_ALIGN_SIZE * 2);
261 result &= check_debug_fill_uninit(p, malloc_size);
262 mi_free(p);
263 };
264 CHECK_BODY("uninit-realloc_aligned-large") {
265 size_t malloc_size = MI_SMALL_SIZE_MAX * 2;
266 uint8_t* p = (uint8_t*)mi_malloc_aligned(malloc_size, MI_MAX_ALIGN_SIZE * 2);
267 result = check_debug_fill_uninit(p, malloc_size);
268 malloc_size *= 3;
269 p = (uint8_t*)mi_realloc_aligned(p, malloc_size, MI_MAX_ALIGN_SIZE * 2);
270 result &= check_debug_fill_uninit(p, malloc_size);
271 mi_free(p);
272 };
273
274
275 CHECK_BODY("fill-freed-small") {
276 size_t malloc_size = MI_SMALL_SIZE_MAX / 2;
277 uint8_t* p = (uint8_t*)mi_malloc(malloc_size);
278 mi_free(p);
279 // First sizeof(void*) bytes will contain housekeeping data, skip these
280 result = check_debug_fill_freed(p + sizeof(void*), malloc_size - sizeof(void*));
281 };
282 CHECK_BODY("fill-freed-large") {
283 size_t malloc_size = MI_SMALL_SIZE_MAX * 2;
284 uint8_t* p = (uint8_t*)mi_malloc(malloc_size);
285 mi_free(p);
286 // First sizeof(void*) bytes will contain housekeeping data, skip these
287 result = check_debug_fill_freed(p + sizeof(void*), malloc_size - sizeof(void*));
288 };
289#endif
290
291 // ---------------------------------------------------
292 // Done
293 // ---------------------------------------------------[]
294 return print_test_summary();
295}
296
297// ---------------------------------------------------------------------------
298// Helper functions
299// ---------------------------------------------------------------------------
300bool check_zero_init(uint8_t* p, size_t size) {
301 if(!p)
302 return false;
303 bool result = true;
304 for (size_t i = 0; i < size; ++i) {
305 result &= p[i] == 0;
306 }
307 return result;
308}
309
310#if MI_DEBUG >= 2
311bool check_debug_fill_uninit(uint8_t* p, size_t size) {
312#if MI_VALGRIND
313 (void)p; (void)size;
314 return true; // when compiled with valgrind we don't init on purpose
315#else
316 if(!p)
317 return false;
318
319 bool result = true;
320 for (size_t i = 0; i < size; ++i) {
321 result &= p[i] == MI_DEBUG_UNINIT;
322 }
323 return result;
324#endif
325}
326
327bool check_debug_fill_freed(uint8_t* p, size_t size) {
328#if MI_VALGRIND
329 (void)p; (void)size;
330 return true; // when compiled with valgrind we don't fill on purpose
331#else
332 if(!p)
333 return false;
334
335 bool result = true;
336 for (size_t i = 0; i < size; ++i) {
337 result &= p[i] == MI_DEBUG_FREED;
338 }
339 return result;
340#endif
341}
342#endif
343