1 /*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <gtest/gtest.h>
18
19 #include <limits.h>
20 #include <stdint.h>
21 #include <stdlib.h>
22 #include <malloc.h>
23 #include <unistd.h>
24
25 #include <tinyxml2.h>
26
27 #include "private/bionic_config.h"
28
TEST(malloc,malloc_std)29 TEST(malloc, malloc_std) {
30 // Simple malloc test.
31 void *ptr = malloc(100);
32 ASSERT_TRUE(ptr != NULL);
33 ASSERT_LE(100U, malloc_usable_size(ptr));
34 free(ptr);
35 }
36
TEST(malloc,malloc_overflow)37 TEST(malloc, malloc_overflow) {
38 errno = 0;
39 ASSERT_EQ(NULL, malloc(SIZE_MAX));
40 ASSERT_EQ(ENOMEM, errno);
41 }
42
TEST(malloc,calloc_std)43 TEST(malloc, calloc_std) {
44 // Simple calloc test.
45 size_t alloc_len = 100;
46 char *ptr = (char *)calloc(1, alloc_len);
47 ASSERT_TRUE(ptr != NULL);
48 ASSERT_LE(alloc_len, malloc_usable_size(ptr));
49 for (size_t i = 0; i < alloc_len; i++) {
50 ASSERT_EQ(0, ptr[i]);
51 }
52 free(ptr);
53 }
54
TEST(malloc,calloc_illegal)55 TEST(malloc, calloc_illegal) {
56 errno = 0;
57 ASSERT_EQ(NULL, calloc(-1, 100));
58 ASSERT_EQ(ENOMEM, errno);
59 }
60
TEST(malloc,calloc_overflow)61 TEST(malloc, calloc_overflow) {
62 errno = 0;
63 ASSERT_EQ(NULL, calloc(1, SIZE_MAX));
64 ASSERT_EQ(ENOMEM, errno);
65 errno = 0;
66 ASSERT_EQ(NULL, calloc(SIZE_MAX, SIZE_MAX));
67 ASSERT_EQ(ENOMEM, errno);
68 errno = 0;
69 ASSERT_EQ(NULL, calloc(2, SIZE_MAX));
70 ASSERT_EQ(ENOMEM, errno);
71 errno = 0;
72 ASSERT_EQ(NULL, calloc(SIZE_MAX, 2));
73 ASSERT_EQ(ENOMEM, errno);
74 }
75
TEST(malloc,memalign_multiple)76 TEST(malloc, memalign_multiple) {
77 // Memalign test where the alignment is any value.
78 for (size_t i = 0; i <= 12; i++) {
79 for (size_t alignment = 1 << i; alignment < (1U << (i+1)); alignment++) {
80 char *ptr = reinterpret_cast<char*>(memalign(alignment, 100));
81 ASSERT_TRUE(ptr != NULL) << "Failed at alignment " << alignment;
82 ASSERT_LE(100U, malloc_usable_size(ptr)) << "Failed at alignment " << alignment;
83 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(ptr) % ((1U << i)))
84 << "Failed at alignment " << alignment;
85 free(ptr);
86 }
87 }
88 }
89
TEST(malloc,memalign_overflow)90 TEST(malloc, memalign_overflow) {
91 ASSERT_EQ(NULL, memalign(4096, SIZE_MAX));
92 }
93
TEST(malloc,memalign_non_power2)94 TEST(malloc, memalign_non_power2) {
95 void* ptr;
96 for (size_t align = 0; align <= 256; align++) {
97 ptr = memalign(align, 1024);
98 ASSERT_TRUE(ptr != NULL) << "Failed at align " << align;
99 free(ptr);
100 }
101 }
102
TEST(malloc,memalign_realloc)103 TEST(malloc, memalign_realloc) {
104 // Memalign and then realloc the pointer a couple of times.
105 for (size_t alignment = 1; alignment <= 4096; alignment <<= 1) {
106 char *ptr = (char*)memalign(alignment, 100);
107 ASSERT_TRUE(ptr != NULL);
108 ASSERT_LE(100U, malloc_usable_size(ptr));
109 ASSERT_EQ(0U, (intptr_t)ptr % alignment);
110 memset(ptr, 0x23, 100);
111
112 ptr = (char*)realloc(ptr, 200);
113 ASSERT_TRUE(ptr != NULL);
114 ASSERT_LE(200U, malloc_usable_size(ptr));
115 ASSERT_TRUE(ptr != NULL);
116 for (size_t i = 0; i < 100; i++) {
117 ASSERT_EQ(0x23, ptr[i]);
118 }
119 memset(ptr, 0x45, 200);
120
121 ptr = (char*)realloc(ptr, 300);
122 ASSERT_TRUE(ptr != NULL);
123 ASSERT_LE(300U, malloc_usable_size(ptr));
124 for (size_t i = 0; i < 200; i++) {
125 ASSERT_EQ(0x45, ptr[i]);
126 }
127 memset(ptr, 0x67, 300);
128
129 ptr = (char*)realloc(ptr, 250);
130 ASSERT_TRUE(ptr != NULL);
131 ASSERT_LE(250U, malloc_usable_size(ptr));
132 for (size_t i = 0; i < 250; i++) {
133 ASSERT_EQ(0x67, ptr[i]);
134 }
135 free(ptr);
136 }
137 }
138
TEST(malloc,malloc_realloc_larger)139 TEST(malloc, malloc_realloc_larger) {
140 // Realloc to a larger size, malloc is used for the original allocation.
141 char *ptr = (char *)malloc(100);
142 ASSERT_TRUE(ptr != NULL);
143 ASSERT_LE(100U, malloc_usable_size(ptr));
144 memset(ptr, 67, 100);
145
146 ptr = (char *)realloc(ptr, 200);
147 ASSERT_TRUE(ptr != NULL);
148 ASSERT_LE(200U, malloc_usable_size(ptr));
149 for (size_t i = 0; i < 100; i++) {
150 ASSERT_EQ(67, ptr[i]);
151 }
152 free(ptr);
153 }
154
TEST(malloc,malloc_realloc_smaller)155 TEST(malloc, malloc_realloc_smaller) {
156 // Realloc to a smaller size, malloc is used for the original allocation.
157 char *ptr = (char *)malloc(200);
158 ASSERT_TRUE(ptr != NULL);
159 ASSERT_LE(200U, malloc_usable_size(ptr));
160 memset(ptr, 67, 200);
161
162 ptr = (char *)realloc(ptr, 100);
163 ASSERT_TRUE(ptr != NULL);
164 ASSERT_LE(100U, malloc_usable_size(ptr));
165 for (size_t i = 0; i < 100; i++) {
166 ASSERT_EQ(67, ptr[i]);
167 }
168 free(ptr);
169 }
170
TEST(malloc,malloc_multiple_realloc)171 TEST(malloc, malloc_multiple_realloc) {
172 // Multiple reallocs, malloc is used for the original allocation.
173 char *ptr = (char *)malloc(200);
174 ASSERT_TRUE(ptr != NULL);
175 ASSERT_LE(200U, malloc_usable_size(ptr));
176 memset(ptr, 0x23, 200);
177
178 ptr = (char *)realloc(ptr, 100);
179 ASSERT_TRUE(ptr != NULL);
180 ASSERT_LE(100U, malloc_usable_size(ptr));
181 for (size_t i = 0; i < 100; i++) {
182 ASSERT_EQ(0x23, ptr[i]);
183 }
184
185 ptr = (char*)realloc(ptr, 50);
186 ASSERT_TRUE(ptr != NULL);
187 ASSERT_LE(50U, malloc_usable_size(ptr));
188 for (size_t i = 0; i < 50; i++) {
189 ASSERT_EQ(0x23, ptr[i]);
190 }
191
192 ptr = (char*)realloc(ptr, 150);
193 ASSERT_TRUE(ptr != NULL);
194 ASSERT_LE(150U, malloc_usable_size(ptr));
195 for (size_t i = 0; i < 50; i++) {
196 ASSERT_EQ(0x23, ptr[i]);
197 }
198 memset(ptr, 0x23, 150);
199
200 ptr = (char*)realloc(ptr, 425);
201 ASSERT_TRUE(ptr != NULL);
202 ASSERT_LE(425U, malloc_usable_size(ptr));
203 for (size_t i = 0; i < 150; i++) {
204 ASSERT_EQ(0x23, ptr[i]);
205 }
206 free(ptr);
207 }
208
TEST(malloc,calloc_realloc_larger)209 TEST(malloc, calloc_realloc_larger) {
210 // Realloc to a larger size, calloc is used for the original allocation.
211 char *ptr = (char *)calloc(1, 100);
212 ASSERT_TRUE(ptr != NULL);
213 ASSERT_LE(100U, malloc_usable_size(ptr));
214
215 ptr = (char *)realloc(ptr, 200);
216 ASSERT_TRUE(ptr != NULL);
217 ASSERT_LE(200U, malloc_usable_size(ptr));
218 for (size_t i = 0; i < 100; i++) {
219 ASSERT_EQ(0, ptr[i]);
220 }
221 free(ptr);
222 }
223
TEST(malloc,calloc_realloc_smaller)224 TEST(malloc, calloc_realloc_smaller) {
225 // Realloc to a smaller size, calloc is used for the original allocation.
226 char *ptr = (char *)calloc(1, 200);
227 ASSERT_TRUE(ptr != NULL);
228 ASSERT_LE(200U, malloc_usable_size(ptr));
229
230 ptr = (char *)realloc(ptr, 100);
231 ASSERT_TRUE(ptr != NULL);
232 ASSERT_LE(100U, malloc_usable_size(ptr));
233 for (size_t i = 0; i < 100; i++) {
234 ASSERT_EQ(0, ptr[i]);
235 }
236 free(ptr);
237 }
238
TEST(malloc,calloc_multiple_realloc)239 TEST(malloc, calloc_multiple_realloc) {
240 // Multiple reallocs, calloc is used for the original allocation.
241 char *ptr = (char *)calloc(1, 200);
242 ASSERT_TRUE(ptr != NULL);
243 ASSERT_LE(200U, malloc_usable_size(ptr));
244
245 ptr = (char *)realloc(ptr, 100);
246 ASSERT_TRUE(ptr != NULL);
247 ASSERT_LE(100U, malloc_usable_size(ptr));
248 for (size_t i = 0; i < 100; i++) {
249 ASSERT_EQ(0, ptr[i]);
250 }
251
252 ptr = (char*)realloc(ptr, 50);
253 ASSERT_TRUE(ptr != NULL);
254 ASSERT_LE(50U, malloc_usable_size(ptr));
255 for (size_t i = 0; i < 50; i++) {
256 ASSERT_EQ(0, ptr[i]);
257 }
258
259 ptr = (char*)realloc(ptr, 150);
260 ASSERT_TRUE(ptr != NULL);
261 ASSERT_LE(150U, malloc_usable_size(ptr));
262 for (size_t i = 0; i < 50; i++) {
263 ASSERT_EQ(0, ptr[i]);
264 }
265 memset(ptr, 0, 150);
266
267 ptr = (char*)realloc(ptr, 425);
268 ASSERT_TRUE(ptr != NULL);
269 ASSERT_LE(425U, malloc_usable_size(ptr));
270 for (size_t i = 0; i < 150; i++) {
271 ASSERT_EQ(0, ptr[i]);
272 }
273 free(ptr);
274 }
275
TEST(malloc,realloc_overflow)276 TEST(malloc, realloc_overflow) {
277 errno = 0;
278 ASSERT_EQ(NULL, realloc(NULL, SIZE_MAX));
279 ASSERT_EQ(ENOMEM, errno);
280 void* ptr = malloc(100);
281 ASSERT_TRUE(ptr != NULL);
282 errno = 0;
283 ASSERT_EQ(NULL, realloc(ptr, SIZE_MAX));
284 ASSERT_EQ(ENOMEM, errno);
285 free(ptr);
286 }
287
288 #if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
289 extern "C" void* pvalloc(size_t);
290 extern "C" void* valloc(size_t);
291
TEST(malloc,pvalloc_std)292 TEST(malloc, pvalloc_std) {
293 size_t pagesize = sysconf(_SC_PAGESIZE);
294 void* ptr = pvalloc(100);
295 ASSERT_TRUE(ptr != NULL);
296 ASSERT_TRUE((reinterpret_cast<uintptr_t>(ptr) & (pagesize-1)) == 0);
297 ASSERT_LE(pagesize, malloc_usable_size(ptr));
298 free(ptr);
299 }
300
TEST(malloc,pvalloc_overflow)301 TEST(malloc, pvalloc_overflow) {
302 ASSERT_EQ(NULL, pvalloc(SIZE_MAX));
303 }
304
TEST(malloc,valloc_std)305 TEST(malloc, valloc_std) {
306 size_t pagesize = sysconf(_SC_PAGESIZE);
307 void* ptr = pvalloc(100);
308 ASSERT_TRUE(ptr != NULL);
309 ASSERT_TRUE((reinterpret_cast<uintptr_t>(ptr) & (pagesize-1)) == 0);
310 free(ptr);
311 }
312
TEST(malloc,valloc_overflow)313 TEST(malloc, valloc_overflow) {
314 ASSERT_EQ(NULL, valloc(SIZE_MAX));
315 }
316 #endif
317
TEST(malloc,malloc_info)318 TEST(malloc, malloc_info) {
319 #ifdef __BIONIC__
320 char* buf;
321 size_t bufsize;
322 FILE* memstream = open_memstream(&buf, &bufsize);
323 ASSERT_NE(nullptr, memstream);
324 ASSERT_EQ(0, malloc_info(0, memstream));
325 ASSERT_EQ(0, fclose(memstream));
326
327 tinyxml2::XMLDocument doc;
328 ASSERT_EQ(tinyxml2::XML_SUCCESS, doc.Parse(buf));
329
330 auto root = doc.FirstChildElement();
331 ASSERT_NE(nullptr, root);
332 ASSERT_STREQ("malloc", root->Name());
333 ASSERT_STREQ("jemalloc-1", root->Attribute("version"));
334
335 auto arena = root->FirstChildElement();
336 for (; arena != nullptr; arena = arena->NextSiblingElement()) {
337 int val;
338
339 ASSERT_STREQ("heap", arena->Name());
340 ASSERT_EQ(tinyxml2::XML_SUCCESS, arena->QueryIntAttribute("nr", &val));
341 ASSERT_EQ(tinyxml2::XML_SUCCESS,
342 arena->FirstChildElement("allocated-large")->QueryIntText(&val));
343 ASSERT_EQ(tinyxml2::XML_SUCCESS,
344 arena->FirstChildElement("allocated-huge")->QueryIntText(&val));
345 ASSERT_EQ(tinyxml2::XML_SUCCESS,
346 arena->FirstChildElement("allocated-bins")->QueryIntText(&val));
347 ASSERT_EQ(tinyxml2::XML_SUCCESS,
348 arena->FirstChildElement("bins-total")->QueryIntText(&val));
349
350 auto bin = arena->FirstChildElement("bin");
351 for (; bin != nullptr; bin = bin ->NextSiblingElement()) {
352 if (strcmp(bin->Name(), "bin") == 0) {
353 ASSERT_EQ(tinyxml2::XML_SUCCESS, bin->QueryIntAttribute("nr", &val));
354 ASSERT_EQ(tinyxml2::XML_SUCCESS,
355 bin->FirstChildElement("allocated")->QueryIntText(&val));
356 ASSERT_EQ(tinyxml2::XML_SUCCESS,
357 bin->FirstChildElement("nmalloc")->QueryIntText(&val));
358 ASSERT_EQ(tinyxml2::XML_SUCCESS,
359 bin->FirstChildElement("ndalloc")->QueryIntText(&val));
360 }
361 }
362 }
363 #endif
364 }
365
TEST(malloc,calloc_usable_size)366 TEST(malloc, calloc_usable_size) {
367 for (size_t size = 1; size <= 2048; size++) {
368 void* pointer = malloc(size);
369 ASSERT_TRUE(pointer != nullptr);
370 memset(pointer, 0xeb, malloc_usable_size(pointer));
371 free(pointer);
372
373 // We should get a previous pointer that has been set to non-zero.
374 // If calloc does not zero out all of the data, this will fail.
375 uint8_t* zero_mem = reinterpret_cast<uint8_t*>(calloc(1, size));
376 ASSERT_TRUE(pointer != nullptr);
377 size_t usable_size = malloc_usable_size(zero_mem);
378 for (size_t i = 0; i < usable_size; i++) {
379 ASSERT_EQ(0, zero_mem[i]) << "Failed at allocation size " << size << " at byte " << i;
380 }
381 free(zero_mem);
382 }
383 }
384
TEST(malloc,malloc_0)385 TEST(malloc, malloc_0) {
386 void* p = malloc(0);
387 ASSERT_TRUE(p != nullptr);
388 free(p);
389 }
390
TEST(malloc,calloc_0_0)391 TEST(malloc, calloc_0_0) {
392 void* p = calloc(0, 0);
393 ASSERT_TRUE(p != nullptr);
394 free(p);
395 }
396
TEST(malloc,calloc_0_1)397 TEST(malloc, calloc_0_1) {
398 void* p = calloc(0, 1);
399 ASSERT_TRUE(p != nullptr);
400 free(p);
401 }
402
TEST(malloc,calloc_1_0)403 TEST(malloc, calloc_1_0) {
404 void* p = calloc(1, 0);
405 ASSERT_TRUE(p != nullptr);
406 free(p);
407 }
408
TEST(malloc,realloc_nullptr_0)409 TEST(malloc, realloc_nullptr_0) {
410 // realloc(nullptr, size) is actually malloc(size).
411 void* p = realloc(nullptr, 0);
412 ASSERT_TRUE(p != nullptr);
413 free(p);
414 }
415
TEST(malloc,realloc_0)416 TEST(malloc, realloc_0) {
417 void* p = malloc(1024);
418 ASSERT_TRUE(p != nullptr);
419 // realloc(p, 0) is actually free(p).
420 void* p2 = realloc(p, 0);
421 ASSERT_TRUE(p2 == nullptr);
422 }
423
424 constexpr size_t MAX_LOOPS = 200;
425
426 // Make sure that memory returned by malloc is aligned to allow these data types.
TEST(malloc,verify_alignment)427 TEST(malloc, verify_alignment) {
428 uint32_t** values_32 = new uint32_t*[MAX_LOOPS];
429 uint64_t** values_64 = new uint64_t*[MAX_LOOPS];
430 long double** values_ldouble = new long double*[MAX_LOOPS];
431 // Use filler to attempt to force the allocator to get potentially bad alignments.
432 void** filler = new void*[MAX_LOOPS];
433
434 for (size_t i = 0; i < MAX_LOOPS; i++) {
435 // Check uint32_t pointers.
436 filler[i] = malloc(1);
437 ASSERT_TRUE(filler[i] != nullptr);
438
439 values_32[i] = reinterpret_cast<uint32_t*>(malloc(sizeof(uint32_t)));
440 ASSERT_TRUE(values_32[i] != nullptr);
441 *values_32[i] = i;
442 ASSERT_EQ(*values_32[i], i);
443 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(values_32[i]) & (sizeof(uint32_t) - 1));
444
445 free(filler[i]);
446 }
447
448 for (size_t i = 0; i < MAX_LOOPS; i++) {
449 // Check uint64_t pointers.
450 filler[i] = malloc(1);
451 ASSERT_TRUE(filler[i] != nullptr);
452
453 values_64[i] = reinterpret_cast<uint64_t*>(malloc(sizeof(uint64_t)));
454 ASSERT_TRUE(values_64[i] != nullptr);
455 *values_64[i] = 0x1000 + i;
456 ASSERT_EQ(*values_64[i], 0x1000 + i);
457 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(values_64[i]) & (sizeof(uint64_t) - 1));
458
459 free(filler[i]);
460 }
461
462 for (size_t i = 0; i < MAX_LOOPS; i++) {
463 // Check long double pointers.
464 filler[i] = malloc(1);
465 ASSERT_TRUE(filler[i] != nullptr);
466
467 values_ldouble[i] = reinterpret_cast<long double*>(malloc(sizeof(long double)));
468 ASSERT_TRUE(values_ldouble[i] != nullptr);
469 *values_ldouble[i] = 5.5 + i;
470 ASSERT_DOUBLE_EQ(*values_ldouble[i], 5.5 + i);
471 // 32 bit glibc has a long double size of 12 bytes, so hardcode the
472 // required alignment to 0x7.
473 #if !defined(__BIONIC__) && !defined(__LP64__)
474 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(values_ldouble[i]) & 0x7);
475 #else
476 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(values_ldouble[i]) & (sizeof(long double) - 1));
477 #endif
478
479 free(filler[i]);
480 }
481
482 for (size_t i = 0; i < MAX_LOOPS; i++) {
483 free(values_32[i]);
484 free(values_64[i]);
485 free(values_ldouble[i]);
486 }
487
488 delete[] filler;
489 delete[] values_32;
490 delete[] values_64;
491 delete[] values_ldouble;
492 }
493
TEST(malloc,mallopt_smoke)494 TEST(malloc, mallopt_smoke) {
495 errno = 0;
496 ASSERT_EQ(0, mallopt(-1000, 1));
497 // mallopt doesn't set errno.
498 ASSERT_EQ(0, errno);
499 }
500