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,posix_memalign_non_power2)103 TEST(malloc, posix_memalign_non_power2) {
104   void* ptr;
105   ASSERT_EQ(EINVAL, posix_memalign(&ptr, 17, 1024));
106 }
107 
TEST(malloc,posix_memalign_overflow)108 TEST(malloc, posix_memalign_overflow) {
109   void* ptr;
110   ASSERT_NE(0, posix_memalign(&ptr, 16, SIZE_MAX));
111 }
112 
TEST(malloc,memalign_realloc)113 TEST(malloc, memalign_realloc) {
114   // Memalign and then realloc the pointer a couple of times.
115   for (size_t alignment = 1; alignment <= 4096; alignment <<= 1) {
116     char *ptr = (char*)memalign(alignment, 100);
117     ASSERT_TRUE(ptr != NULL);
118     ASSERT_LE(100U, malloc_usable_size(ptr));
119     ASSERT_EQ(0U, (intptr_t)ptr % alignment);
120     memset(ptr, 0x23, 100);
121 
122     ptr = (char*)realloc(ptr, 200);
123     ASSERT_TRUE(ptr != NULL);
124     ASSERT_LE(200U, malloc_usable_size(ptr));
125     ASSERT_TRUE(ptr != NULL);
126     for (size_t i = 0; i < 100; i++) {
127       ASSERT_EQ(0x23, ptr[i]);
128     }
129     memset(ptr, 0x45, 200);
130 
131     ptr = (char*)realloc(ptr, 300);
132     ASSERT_TRUE(ptr != NULL);
133     ASSERT_LE(300U, malloc_usable_size(ptr));
134     for (size_t i = 0; i < 200; i++) {
135       ASSERT_EQ(0x45, ptr[i]);
136     }
137     memset(ptr, 0x67, 300);
138 
139     ptr = (char*)realloc(ptr, 250);
140     ASSERT_TRUE(ptr != NULL);
141     ASSERT_LE(250U, malloc_usable_size(ptr));
142     for (size_t i = 0; i < 250; i++) {
143       ASSERT_EQ(0x67, ptr[i]);
144     }
145     free(ptr);
146   }
147 }
148 
TEST(malloc,malloc_realloc_larger)149 TEST(malloc, malloc_realloc_larger) {
150   // Realloc to a larger size, malloc is used for the original allocation.
151   char *ptr = (char *)malloc(100);
152   ASSERT_TRUE(ptr != NULL);
153   ASSERT_LE(100U, malloc_usable_size(ptr));
154   memset(ptr, 67, 100);
155 
156   ptr = (char *)realloc(ptr, 200);
157   ASSERT_TRUE(ptr != NULL);
158   ASSERT_LE(200U, malloc_usable_size(ptr));
159   for (size_t i = 0; i < 100; i++) {
160     ASSERT_EQ(67, ptr[i]);
161   }
162   free(ptr);
163 }
164 
TEST(malloc,malloc_realloc_smaller)165 TEST(malloc, malloc_realloc_smaller) {
166   // Realloc to a smaller size, malloc is used for the original allocation.
167   char *ptr = (char *)malloc(200);
168   ASSERT_TRUE(ptr != NULL);
169   ASSERT_LE(200U, malloc_usable_size(ptr));
170   memset(ptr, 67, 200);
171 
172   ptr = (char *)realloc(ptr, 100);
173   ASSERT_TRUE(ptr != NULL);
174   ASSERT_LE(100U, malloc_usable_size(ptr));
175   for (size_t i = 0; i < 100; i++) {
176     ASSERT_EQ(67, ptr[i]);
177   }
178   free(ptr);
179 }
180 
TEST(malloc,malloc_multiple_realloc)181 TEST(malloc, malloc_multiple_realloc) {
182   // Multiple reallocs, malloc is used for the original allocation.
183   char *ptr = (char *)malloc(200);
184   ASSERT_TRUE(ptr != NULL);
185   ASSERT_LE(200U, malloc_usable_size(ptr));
186   memset(ptr, 0x23, 200);
187 
188   ptr = (char *)realloc(ptr, 100);
189   ASSERT_TRUE(ptr != NULL);
190   ASSERT_LE(100U, malloc_usable_size(ptr));
191   for (size_t i = 0; i < 100; i++) {
192     ASSERT_EQ(0x23, ptr[i]);
193   }
194 
195   ptr = (char*)realloc(ptr, 50);
196   ASSERT_TRUE(ptr != NULL);
197   ASSERT_LE(50U, malloc_usable_size(ptr));
198   for (size_t i = 0; i < 50; i++) {
199     ASSERT_EQ(0x23, ptr[i]);
200   }
201 
202   ptr = (char*)realloc(ptr, 150);
203   ASSERT_TRUE(ptr != NULL);
204   ASSERT_LE(150U, malloc_usable_size(ptr));
205   for (size_t i = 0; i < 50; i++) {
206     ASSERT_EQ(0x23, ptr[i]);
207   }
208   memset(ptr, 0x23, 150);
209 
210   ptr = (char*)realloc(ptr, 425);
211   ASSERT_TRUE(ptr != NULL);
212   ASSERT_LE(425U, malloc_usable_size(ptr));
213   for (size_t i = 0; i < 150; i++) {
214     ASSERT_EQ(0x23, ptr[i]);
215   }
216   free(ptr);
217 }
218 
TEST(malloc,calloc_realloc_larger)219 TEST(malloc, calloc_realloc_larger) {
220   // Realloc to a larger size, calloc is used for the original allocation.
221   char *ptr = (char *)calloc(1, 100);
222   ASSERT_TRUE(ptr != NULL);
223   ASSERT_LE(100U, malloc_usable_size(ptr));
224 
225   ptr = (char *)realloc(ptr, 200);
226   ASSERT_TRUE(ptr != NULL);
227   ASSERT_LE(200U, malloc_usable_size(ptr));
228   for (size_t i = 0; i < 100; i++) {
229     ASSERT_EQ(0, ptr[i]);
230   }
231   free(ptr);
232 }
233 
TEST(malloc,calloc_realloc_smaller)234 TEST(malloc, calloc_realloc_smaller) {
235   // Realloc to a smaller size, calloc is used for the original allocation.
236   char *ptr = (char *)calloc(1, 200);
237   ASSERT_TRUE(ptr != NULL);
238   ASSERT_LE(200U, malloc_usable_size(ptr));
239 
240   ptr = (char *)realloc(ptr, 100);
241   ASSERT_TRUE(ptr != NULL);
242   ASSERT_LE(100U, malloc_usable_size(ptr));
243   for (size_t i = 0; i < 100; i++) {
244     ASSERT_EQ(0, ptr[i]);
245   }
246   free(ptr);
247 }
248 
TEST(malloc,calloc_multiple_realloc)249 TEST(malloc, calloc_multiple_realloc) {
250   // Multiple reallocs, calloc is used for the original allocation.
251   char *ptr = (char *)calloc(1, 200);
252   ASSERT_TRUE(ptr != NULL);
253   ASSERT_LE(200U, malloc_usable_size(ptr));
254 
255   ptr = (char *)realloc(ptr, 100);
256   ASSERT_TRUE(ptr != NULL);
257   ASSERT_LE(100U, malloc_usable_size(ptr));
258   for (size_t i = 0; i < 100; i++) {
259     ASSERT_EQ(0, ptr[i]);
260   }
261 
262   ptr = (char*)realloc(ptr, 50);
263   ASSERT_TRUE(ptr != NULL);
264   ASSERT_LE(50U, malloc_usable_size(ptr));
265   for (size_t i = 0; i < 50; i++) {
266     ASSERT_EQ(0, ptr[i]);
267   }
268 
269   ptr = (char*)realloc(ptr, 150);
270   ASSERT_TRUE(ptr != NULL);
271   ASSERT_LE(150U, malloc_usable_size(ptr));
272   for (size_t i = 0; i < 50; i++) {
273     ASSERT_EQ(0, ptr[i]);
274   }
275   memset(ptr, 0, 150);
276 
277   ptr = (char*)realloc(ptr, 425);
278   ASSERT_TRUE(ptr != NULL);
279   ASSERT_LE(425U, malloc_usable_size(ptr));
280   for (size_t i = 0; i < 150; i++) {
281     ASSERT_EQ(0, ptr[i]);
282   }
283   free(ptr);
284 }
285 
TEST(malloc,realloc_overflow)286 TEST(malloc, realloc_overflow) {
287   errno = 0;
288   ASSERT_EQ(NULL, realloc(NULL, SIZE_MAX));
289   ASSERT_EQ(ENOMEM, errno);
290   void* ptr = malloc(100);
291   ASSERT_TRUE(ptr != NULL);
292   errno = 0;
293   ASSERT_EQ(NULL, realloc(ptr, SIZE_MAX));
294   ASSERT_EQ(ENOMEM, errno);
295   free(ptr);
296 }
297 
298 #if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
299 extern "C" void* pvalloc(size_t);
300 extern "C" void* valloc(size_t);
301 
TEST(malloc,pvalloc_std)302 TEST(malloc, pvalloc_std) {
303   size_t pagesize = sysconf(_SC_PAGESIZE);
304   void* ptr = pvalloc(100);
305   ASSERT_TRUE(ptr != NULL);
306   ASSERT_TRUE((reinterpret_cast<uintptr_t>(ptr) & (pagesize-1)) == 0);
307   ASSERT_LE(pagesize, malloc_usable_size(ptr));
308   free(ptr);
309 }
310 
TEST(malloc,pvalloc_overflow)311 TEST(malloc, pvalloc_overflow) {
312   ASSERT_EQ(NULL, pvalloc(SIZE_MAX));
313 }
314 
TEST(malloc,valloc_std)315 TEST(malloc, valloc_std) {
316   size_t pagesize = sysconf(_SC_PAGESIZE);
317   void* ptr = pvalloc(100);
318   ASSERT_TRUE(ptr != NULL);
319   ASSERT_TRUE((reinterpret_cast<uintptr_t>(ptr) & (pagesize-1)) == 0);
320   free(ptr);
321 }
322 
TEST(malloc,valloc_overflow)323 TEST(malloc, valloc_overflow) {
324   ASSERT_EQ(NULL, valloc(SIZE_MAX));
325 }
326 #endif
327 
TEST(malloc,malloc_info)328 TEST(malloc, malloc_info) {
329 #ifdef __BIONIC__
330   char* buf;
331   size_t bufsize;
332   FILE* memstream = open_memstream(&buf, &bufsize);
333   ASSERT_NE(nullptr, memstream);
334   ASSERT_EQ(0, malloc_info(0, memstream));
335   ASSERT_EQ(0, fclose(memstream));
336 
337   tinyxml2::XMLDocument doc;
338   ASSERT_EQ(tinyxml2::XML_SUCCESS, doc.Parse(buf));
339 
340   auto root = doc.FirstChildElement();
341   ASSERT_NE(nullptr, root);
342   ASSERT_STREQ("malloc", root->Name());
343   ASSERT_STREQ("jemalloc-1", root->Attribute("version"));
344 
345   auto arena = root->FirstChildElement();
346   for (; arena != nullptr; arena = arena->NextSiblingElement()) {
347     int val;
348 
349     ASSERT_STREQ("heap", arena->Name());
350     ASSERT_EQ(tinyxml2::XML_SUCCESS, arena->QueryIntAttribute("nr", &val));
351     ASSERT_EQ(tinyxml2::XML_SUCCESS,
352               arena->FirstChildElement("allocated-large")->QueryIntText(&val));
353     ASSERT_EQ(tinyxml2::XML_SUCCESS,
354               arena->FirstChildElement("allocated-huge")->QueryIntText(&val));
355     ASSERT_EQ(tinyxml2::XML_SUCCESS,
356               arena->FirstChildElement("allocated-bins")->QueryIntText(&val));
357     ASSERT_EQ(tinyxml2::XML_SUCCESS,
358               arena->FirstChildElement("bins-total")->QueryIntText(&val));
359 
360     auto bin = arena->FirstChildElement("bin");
361     for (; bin != nullptr; bin = bin ->NextSiblingElement()) {
362       if (strcmp(bin->Name(), "bin") == 0) {
363         ASSERT_EQ(tinyxml2::XML_SUCCESS, bin->QueryIntAttribute("nr", &val));
364         ASSERT_EQ(tinyxml2::XML_SUCCESS,
365                   bin->FirstChildElement("allocated")->QueryIntText(&val));
366         ASSERT_EQ(tinyxml2::XML_SUCCESS,
367                   bin->FirstChildElement("nmalloc")->QueryIntText(&val));
368         ASSERT_EQ(tinyxml2::XML_SUCCESS,
369                   bin->FirstChildElement("ndalloc")->QueryIntText(&val));
370       }
371     }
372   }
373 #endif
374 }
375 
TEST(malloc,calloc_usable_size)376 TEST(malloc, calloc_usable_size) {
377   for (size_t size = 1; size <= 2048; size++) {
378     void* pointer = malloc(size);
379     ASSERT_TRUE(pointer != nullptr);
380     memset(pointer, 0xeb, malloc_usable_size(pointer));
381     free(pointer);
382 
383     // We should get a previous pointer that has been set to non-zero.
384     // If calloc does not zero out all of the data, this will fail.
385     uint8_t* zero_mem = reinterpret_cast<uint8_t*>(calloc(1, size));
386     ASSERT_TRUE(pointer != nullptr);
387     size_t usable_size = malloc_usable_size(zero_mem);
388     for (size_t i = 0; i < usable_size; i++) {
389       ASSERT_EQ(0, zero_mem[i]) << "Failed at allocation size " << size << " at byte " << i;
390     }
391     free(zero_mem);
392   }
393 }
394 
TEST(malloc,malloc_0)395 TEST(malloc, malloc_0) {
396   void* p = malloc(0);
397   ASSERT_TRUE(p != nullptr);
398   free(p);
399 }
400 
TEST(malloc,calloc_0_0)401 TEST(malloc, calloc_0_0) {
402   void* p = calloc(0, 0);
403   ASSERT_TRUE(p != nullptr);
404   free(p);
405 }
406 
TEST(malloc,calloc_0_1)407 TEST(malloc, calloc_0_1) {
408   void* p = calloc(0, 1);
409   ASSERT_TRUE(p != nullptr);
410   free(p);
411 }
412 
TEST(malloc,calloc_1_0)413 TEST(malloc, calloc_1_0) {
414   void* p = calloc(1, 0);
415   ASSERT_TRUE(p != nullptr);
416   free(p);
417 }
418 
TEST(malloc,realloc_nullptr_0)419 TEST(malloc, realloc_nullptr_0) {
420   // realloc(nullptr, size) is actually malloc(size).
421   void* p = realloc(nullptr, 0);
422   ASSERT_TRUE(p != nullptr);
423   free(p);
424 }
425 
TEST(malloc,realloc_0)426 TEST(malloc, realloc_0) {
427   void* p = malloc(1024);
428   ASSERT_TRUE(p != nullptr);
429   // realloc(p, 0) is actually free(p).
430   void* p2 = realloc(p, 0);
431   ASSERT_TRUE(p2 == nullptr);
432 }
433 
434 constexpr size_t MAX_LOOPS = 200;
435 
436 // Make sure that memory returned by malloc is aligned to allow these data types.
TEST(malloc,verify_alignment)437 TEST(malloc, verify_alignment) {
438   uint32_t** values_32 = new uint32_t*[MAX_LOOPS];
439   uint64_t** values_64 = new uint64_t*[MAX_LOOPS];
440   long double** values_ldouble = new long double*[MAX_LOOPS];
441   // Use filler to attempt to force the allocator to get potentially bad alignments.
442   void** filler = new void*[MAX_LOOPS];
443 
444   for (size_t i = 0; i < MAX_LOOPS; i++) {
445     // Check uint32_t pointers.
446     filler[i] = malloc(1);
447     ASSERT_TRUE(filler[i] != nullptr);
448 
449     values_32[i] = reinterpret_cast<uint32_t*>(malloc(sizeof(uint32_t)));
450     ASSERT_TRUE(values_32[i] != nullptr);
451     *values_32[i] = i;
452     ASSERT_EQ(*values_32[i], i);
453     ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(values_32[i]) & (sizeof(uint32_t) - 1));
454 
455     free(filler[i]);
456   }
457 
458   for (size_t i = 0; i < MAX_LOOPS; i++) {
459     // Check uint64_t pointers.
460     filler[i] = malloc(1);
461     ASSERT_TRUE(filler[i] != nullptr);
462 
463     values_64[i] = reinterpret_cast<uint64_t*>(malloc(sizeof(uint64_t)));
464     ASSERT_TRUE(values_64[i] != nullptr);
465     *values_64[i] = 0x1000 + i;
466     ASSERT_EQ(*values_64[i], 0x1000 + i);
467     ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(values_64[i]) & (sizeof(uint64_t) - 1));
468 
469     free(filler[i]);
470   }
471 
472   for (size_t i = 0; i < MAX_LOOPS; i++) {
473     // Check long double pointers.
474     filler[i] = malloc(1);
475     ASSERT_TRUE(filler[i] != nullptr);
476 
477     values_ldouble[i] = reinterpret_cast<long double*>(malloc(sizeof(long double)));
478     ASSERT_TRUE(values_ldouble[i] != nullptr);
479     *values_ldouble[i] = 5.5 + i;
480     ASSERT_DOUBLE_EQ(*values_ldouble[i], 5.5 + i);
481     // 32 bit glibc has a long double size of 12 bytes, so hardcode the
482     // required alignment to 0x7.
483 #if !defined(__BIONIC__) && !defined(__LP64__)
484     ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(values_ldouble[i]) & 0x7);
485 #else
486     ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(values_ldouble[i]) & (sizeof(long double) - 1));
487 #endif
488 
489     free(filler[i]);
490   }
491 
492   for (size_t i = 0; i < MAX_LOOPS; i++) {
493     free(values_32[i]);
494     free(values_64[i]);
495     free(values_ldouble[i]);
496   }
497 
498   delete[] filler;
499   delete[] values_32;
500   delete[] values_64;
501   delete[] values_ldouble;
502 }
503