blob: fcdae85af69f1c1d4a323b2100ad971282c58ce0 [file] [log] [blame]
Christopher Ferris885f3b92013-05-21 17:48:01 -07001/*
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
Christopher Ferrise4cdbc42019-02-08 17:30:58 -080019#include <elf.h>
Christopher Ferrisa4037802014-06-09 19:14:11 -070020#include <limits.h>
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -080021#include <pthread.h>
Christopher Ferrisa4037802014-06-09 19:14:11 -070022#include <stdint.h>
Christopher Ferris6c619a02019-03-01 17:59:51 -080023#include <stdio.h>
Christopher Ferris885f3b92013-05-21 17:48:01 -070024#include <stdlib.h>
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -080025#include <string.h>
26#include <sys/types.h>
27#include <sys/wait.h>
Christopher Ferris885f3b92013-05-21 17:48:01 -070028#include <malloc.h>
Christopher Ferrisa4037802014-06-09 19:14:11 -070029#include <unistd.h>
Christopher Ferris885f3b92013-05-21 17:48:01 -070030
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -080031#include <atomic>
Christopher Ferrisf32494c2020-01-08 14:19:10 -080032#include <thread>
33
Dan Albert4caa1f02014-08-20 09:16:57 -070034#include <tinyxml2.h>
35
Christopher Ferrise4cdbc42019-02-08 17:30:58 -080036#include <android-base/file.h>
37
Christopher Ferris2b0638e2019-09-11 19:05:29 -070038#include "platform/bionic/malloc.h"
Christopher Ferris63619642014-06-16 23:35:53 -070039#include "private/bionic_config.h"
Evgenii Stepanovacd6f4f2018-11-06 16:48:27 -080040#include "utils.h"
Dan Alberte5fdaa42014-06-14 01:04:31 +000041
Elliott Hughesb1770852018-09-18 12:52:42 -070042#if defined(__BIONIC__)
43#define HAVE_REALLOCARRAY 1
44#else
45#define HAVE_REALLOCARRAY __GLIBC_PREREQ(2, 26)
46#endif
47
Christopher Ferris885f3b92013-05-21 17:48:01 -070048TEST(malloc, malloc_std) {
49 // Simple malloc test.
50 void *ptr = malloc(100);
Yi Kong32bc0fc2018-08-02 17:31:13 -070051 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -070052 ASSERT_LE(100U, malloc_usable_size(ptr));
Christopher Ferris885f3b92013-05-21 17:48:01 -070053 free(ptr);
54}
55
Christopher Ferrisa4037802014-06-09 19:14:11 -070056TEST(malloc, malloc_overflow) {
Evgenii Stepanovacd6f4f2018-11-06 16:48:27 -080057 SKIP_WITH_HWASAN;
Christopher Ferrisa4037802014-06-09 19:14:11 -070058 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -070059 ASSERT_EQ(nullptr, malloc(SIZE_MAX));
Christopher Ferrisa4037802014-06-09 19:14:11 -070060 ASSERT_EQ(ENOMEM, errno);
61}
62
Christopher Ferris885f3b92013-05-21 17:48:01 -070063TEST(malloc, calloc_std) {
64 // Simple calloc test.
65 size_t alloc_len = 100;
66 char *ptr = (char *)calloc(1, alloc_len);
Yi Kong32bc0fc2018-08-02 17:31:13 -070067 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -070068 ASSERT_LE(alloc_len, malloc_usable_size(ptr));
69 for (size_t i = 0; i < alloc_len; i++) {
70 ASSERT_EQ(0, ptr[i]);
71 }
Christopher Ferris885f3b92013-05-21 17:48:01 -070072 free(ptr);
73}
74
Christopher Ferrisa4037802014-06-09 19:14:11 -070075TEST(malloc, calloc_illegal) {
Evgenii Stepanovacd6f4f2018-11-06 16:48:27 -080076 SKIP_WITH_HWASAN;
Christopher Ferrisa4037802014-06-09 19:14:11 -070077 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -070078 ASSERT_EQ(nullptr, calloc(-1, 100));
Christopher Ferrisa4037802014-06-09 19:14:11 -070079 ASSERT_EQ(ENOMEM, errno);
80}
81
82TEST(malloc, calloc_overflow) {
Evgenii Stepanovacd6f4f2018-11-06 16:48:27 -080083 SKIP_WITH_HWASAN;
Christopher Ferrisa4037802014-06-09 19:14:11 -070084 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -070085 ASSERT_EQ(nullptr, calloc(1, SIZE_MAX));
Christopher Ferrisa4037802014-06-09 19:14:11 -070086 ASSERT_EQ(ENOMEM, errno);
87 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -070088 ASSERT_EQ(nullptr, calloc(SIZE_MAX, SIZE_MAX));
Christopher Ferrisa4037802014-06-09 19:14:11 -070089 ASSERT_EQ(ENOMEM, errno);
90 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -070091 ASSERT_EQ(nullptr, calloc(2, SIZE_MAX));
Christopher Ferrisa4037802014-06-09 19:14:11 -070092 ASSERT_EQ(ENOMEM, errno);
93 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -070094 ASSERT_EQ(nullptr, calloc(SIZE_MAX, 2));
Christopher Ferrisa4037802014-06-09 19:14:11 -070095 ASSERT_EQ(ENOMEM, errno);
96}
97
Christopher Ferris885f3b92013-05-21 17:48:01 -070098TEST(malloc, memalign_multiple) {
Elliott Hughesbcaa4542019-03-08 15:20:23 -080099 SKIP_WITH_HWASAN << "hwasan requires power of 2 alignment";
Christopher Ferris885f3b92013-05-21 17:48:01 -0700100 // Memalign test where the alignment is any value.
101 for (size_t i = 0; i <= 12; i++) {
102 for (size_t alignment = 1 << i; alignment < (1U << (i+1)); alignment++) {
Christopher Ferrisa4037802014-06-09 19:14:11 -0700103 char *ptr = reinterpret_cast<char*>(memalign(alignment, 100));
Yi Kong32bc0fc2018-08-02 17:31:13 -0700104 ASSERT_TRUE(ptr != nullptr) << "Failed at alignment " << alignment;
Christopher Ferrisa4037802014-06-09 19:14:11 -0700105 ASSERT_LE(100U, malloc_usable_size(ptr)) << "Failed at alignment " << alignment;
106 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(ptr) % ((1U << i)))
107 << "Failed at alignment " << alignment;
Christopher Ferris885f3b92013-05-21 17:48:01 -0700108 free(ptr);
109 }
110 }
111}
112
Christopher Ferrisa4037802014-06-09 19:14:11 -0700113TEST(malloc, memalign_overflow) {
Evgenii Stepanovacd6f4f2018-11-06 16:48:27 -0800114 SKIP_WITH_HWASAN;
Yi Kong32bc0fc2018-08-02 17:31:13 -0700115 ASSERT_EQ(nullptr, memalign(4096, SIZE_MAX));
Christopher Ferrisa4037802014-06-09 19:14:11 -0700116}
117
118TEST(malloc, memalign_non_power2) {
Evgenii Stepanovacd6f4f2018-11-06 16:48:27 -0800119 SKIP_WITH_HWASAN;
Christopher Ferrisa4037802014-06-09 19:14:11 -0700120 void* ptr;
121 for (size_t align = 0; align <= 256; align++) {
122 ptr = memalign(align, 1024);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700123 ASSERT_TRUE(ptr != nullptr) << "Failed at align " << align;
Christopher Ferrisa4037802014-06-09 19:14:11 -0700124 free(ptr);
125 }
126}
127
Christopher Ferris885f3b92013-05-21 17:48:01 -0700128TEST(malloc, memalign_realloc) {
129 // Memalign and then realloc the pointer a couple of times.
130 for (size_t alignment = 1; alignment <= 4096; alignment <<= 1) {
131 char *ptr = (char*)memalign(alignment, 100);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700132 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700133 ASSERT_LE(100U, malloc_usable_size(ptr));
134 ASSERT_EQ(0U, (intptr_t)ptr % alignment);
135 memset(ptr, 0x23, 100);
136
137 ptr = (char*)realloc(ptr, 200);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700138 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700139 ASSERT_LE(200U, malloc_usable_size(ptr));
Yi Kong32bc0fc2018-08-02 17:31:13 -0700140 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700141 for (size_t i = 0; i < 100; i++) {
142 ASSERT_EQ(0x23, ptr[i]);
143 }
144 memset(ptr, 0x45, 200);
145
146 ptr = (char*)realloc(ptr, 300);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700147 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700148 ASSERT_LE(300U, malloc_usable_size(ptr));
149 for (size_t i = 0; i < 200; i++) {
150 ASSERT_EQ(0x45, ptr[i]);
151 }
152 memset(ptr, 0x67, 300);
153
154 ptr = (char*)realloc(ptr, 250);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700155 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700156 ASSERT_LE(250U, malloc_usable_size(ptr));
157 for (size_t i = 0; i < 250; i++) {
158 ASSERT_EQ(0x67, ptr[i]);
159 }
Christopher Ferris885f3b92013-05-21 17:48:01 -0700160 free(ptr);
161 }
162}
163
164TEST(malloc, malloc_realloc_larger) {
165 // Realloc to a larger size, malloc is used for the original allocation.
166 char *ptr = (char *)malloc(100);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700167 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700168 ASSERT_LE(100U, malloc_usable_size(ptr));
169 memset(ptr, 67, 100);
170
171 ptr = (char *)realloc(ptr, 200);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700172 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700173 ASSERT_LE(200U, malloc_usable_size(ptr));
174 for (size_t i = 0; i < 100; i++) {
175 ASSERT_EQ(67, ptr[i]);
176 }
Christopher Ferris885f3b92013-05-21 17:48:01 -0700177 free(ptr);
178}
179
180TEST(malloc, malloc_realloc_smaller) {
181 // Realloc to a smaller size, malloc is used for the original allocation.
182 char *ptr = (char *)malloc(200);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700183 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700184 ASSERT_LE(200U, malloc_usable_size(ptr));
185 memset(ptr, 67, 200);
186
187 ptr = (char *)realloc(ptr, 100);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700188 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700189 ASSERT_LE(100U, malloc_usable_size(ptr));
190 for (size_t i = 0; i < 100; i++) {
191 ASSERT_EQ(67, ptr[i]);
192 }
Christopher Ferris885f3b92013-05-21 17:48:01 -0700193 free(ptr);
194}
195
196TEST(malloc, malloc_multiple_realloc) {
197 // Multiple reallocs, malloc is used for the original allocation.
198 char *ptr = (char *)malloc(200);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700199 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700200 ASSERT_LE(200U, malloc_usable_size(ptr));
201 memset(ptr, 0x23, 200);
202
203 ptr = (char *)realloc(ptr, 100);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700204 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700205 ASSERT_LE(100U, malloc_usable_size(ptr));
206 for (size_t i = 0; i < 100; i++) {
207 ASSERT_EQ(0x23, ptr[i]);
208 }
209
210 ptr = (char*)realloc(ptr, 50);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700211 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700212 ASSERT_LE(50U, malloc_usable_size(ptr));
213 for (size_t i = 0; i < 50; i++) {
214 ASSERT_EQ(0x23, ptr[i]);
215 }
216
217 ptr = (char*)realloc(ptr, 150);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700218 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700219 ASSERT_LE(150U, malloc_usable_size(ptr));
220 for (size_t i = 0; i < 50; i++) {
221 ASSERT_EQ(0x23, ptr[i]);
222 }
223 memset(ptr, 0x23, 150);
224
225 ptr = (char*)realloc(ptr, 425);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700226 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700227 ASSERT_LE(425U, malloc_usable_size(ptr));
228 for (size_t i = 0; i < 150; i++) {
229 ASSERT_EQ(0x23, ptr[i]);
230 }
Christopher Ferris885f3b92013-05-21 17:48:01 -0700231 free(ptr);
232}
Christopher Ferrisa4037802014-06-09 19:14:11 -0700233
Christopher Ferris885f3b92013-05-21 17:48:01 -0700234TEST(malloc, calloc_realloc_larger) {
235 // Realloc to a larger size, calloc is used for the original allocation.
236 char *ptr = (char *)calloc(1, 100);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700237 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700238 ASSERT_LE(100U, malloc_usable_size(ptr));
239
240 ptr = (char *)realloc(ptr, 200);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700241 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700242 ASSERT_LE(200U, malloc_usable_size(ptr));
243 for (size_t i = 0; i < 100; i++) {
244 ASSERT_EQ(0, ptr[i]);
245 }
Christopher Ferris885f3b92013-05-21 17:48:01 -0700246 free(ptr);
247}
248
249TEST(malloc, calloc_realloc_smaller) {
250 // Realloc to a smaller size, calloc is used for the original allocation.
251 char *ptr = (char *)calloc(1, 200);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700252 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700253 ASSERT_LE(200U, malloc_usable_size(ptr));
254
255 ptr = (char *)realloc(ptr, 100);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700256 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700257 ASSERT_LE(100U, malloc_usable_size(ptr));
258 for (size_t i = 0; i < 100; i++) {
259 ASSERT_EQ(0, ptr[i]);
260 }
Christopher Ferris885f3b92013-05-21 17:48:01 -0700261 free(ptr);
262}
263
264TEST(malloc, calloc_multiple_realloc) {
265 // Multiple reallocs, calloc is used for the original allocation.
266 char *ptr = (char *)calloc(1, 200);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700267 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700268 ASSERT_LE(200U, malloc_usable_size(ptr));
269
270 ptr = (char *)realloc(ptr, 100);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700271 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700272 ASSERT_LE(100U, malloc_usable_size(ptr));
273 for (size_t i = 0; i < 100; i++) {
274 ASSERT_EQ(0, ptr[i]);
275 }
276
277 ptr = (char*)realloc(ptr, 50);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700278 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700279 ASSERT_LE(50U, malloc_usable_size(ptr));
280 for (size_t i = 0; i < 50; i++) {
281 ASSERT_EQ(0, ptr[i]);
282 }
283
284 ptr = (char*)realloc(ptr, 150);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700285 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700286 ASSERT_LE(150U, malloc_usable_size(ptr));
287 for (size_t i = 0; i < 50; i++) {
288 ASSERT_EQ(0, ptr[i]);
289 }
290 memset(ptr, 0, 150);
291
292 ptr = (char*)realloc(ptr, 425);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700293 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700294 ASSERT_LE(425U, malloc_usable_size(ptr));
295 for (size_t i = 0; i < 150; i++) {
296 ASSERT_EQ(0, ptr[i]);
297 }
Christopher Ferris885f3b92013-05-21 17:48:01 -0700298 free(ptr);
299}
Christopher Ferris72bbd422014-05-08 11:14:03 -0700300
Christopher Ferrisa4037802014-06-09 19:14:11 -0700301TEST(malloc, realloc_overflow) {
Evgenii Stepanovacd6f4f2018-11-06 16:48:27 -0800302 SKIP_WITH_HWASAN;
Christopher Ferrisa4037802014-06-09 19:14:11 -0700303 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -0700304 ASSERT_EQ(nullptr, realloc(nullptr, SIZE_MAX));
Christopher Ferrisa4037802014-06-09 19:14:11 -0700305 ASSERT_EQ(ENOMEM, errno);
306 void* ptr = malloc(100);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700307 ASSERT_TRUE(ptr != nullptr);
Christopher Ferrisa4037802014-06-09 19:14:11 -0700308 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -0700309 ASSERT_EQ(nullptr, realloc(ptr, SIZE_MAX));
Christopher Ferrisa4037802014-06-09 19:14:11 -0700310 ASSERT_EQ(ENOMEM, errno);
311 free(ptr);
Christopher Ferris72bbd422014-05-08 11:14:03 -0700312}
313
Dan Alberte5fdaa42014-06-14 01:04:31 +0000314#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
315extern "C" void* pvalloc(size_t);
316extern "C" void* valloc(size_t);
Christopher Ferris804cebe2019-06-20 08:50:23 -0700317#endif
Dan Alberte5fdaa42014-06-14 01:04:31 +0000318
Christopher Ferrisa4037802014-06-09 19:14:11 -0700319TEST(malloc, pvalloc_std) {
Christopher Ferris804cebe2019-06-20 08:50:23 -0700320#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
Christopher Ferrisa4037802014-06-09 19:14:11 -0700321 size_t pagesize = sysconf(_SC_PAGESIZE);
322 void* ptr = pvalloc(100);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700323 ASSERT_TRUE(ptr != nullptr);
Christopher Ferrisa4037802014-06-09 19:14:11 -0700324 ASSERT_TRUE((reinterpret_cast<uintptr_t>(ptr) & (pagesize-1)) == 0);
325 ASSERT_LE(pagesize, malloc_usable_size(ptr));
326 free(ptr);
Christopher Ferris804cebe2019-06-20 08:50:23 -0700327#else
328 GTEST_SKIP() << "pvalloc not supported.";
329#endif
Christopher Ferrisa4037802014-06-09 19:14:11 -0700330}
331
332TEST(malloc, pvalloc_overflow) {
Christopher Ferris804cebe2019-06-20 08:50:23 -0700333#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
Yi Kong32bc0fc2018-08-02 17:31:13 -0700334 ASSERT_EQ(nullptr, pvalloc(SIZE_MAX));
Christopher Ferris804cebe2019-06-20 08:50:23 -0700335#else
336 GTEST_SKIP() << "pvalloc not supported.";
337#endif
Christopher Ferrisa4037802014-06-09 19:14:11 -0700338}
339
340TEST(malloc, valloc_std) {
Christopher Ferris804cebe2019-06-20 08:50:23 -0700341#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
Christopher Ferrisa4037802014-06-09 19:14:11 -0700342 size_t pagesize = sysconf(_SC_PAGESIZE);
Christopher Ferrisd5ab0a52019-06-19 12:03:57 -0700343 void* ptr = valloc(100);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700344 ASSERT_TRUE(ptr != nullptr);
Christopher Ferrisa4037802014-06-09 19:14:11 -0700345 ASSERT_TRUE((reinterpret_cast<uintptr_t>(ptr) & (pagesize-1)) == 0);
346 free(ptr);
Christopher Ferris804cebe2019-06-20 08:50:23 -0700347#else
348 GTEST_SKIP() << "valloc not supported.";
349#endif
Christopher Ferrisa4037802014-06-09 19:14:11 -0700350}
351
352TEST(malloc, valloc_overflow) {
Christopher Ferris804cebe2019-06-20 08:50:23 -0700353#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
Yi Kong32bc0fc2018-08-02 17:31:13 -0700354 ASSERT_EQ(nullptr, valloc(SIZE_MAX));
Christopher Ferris804cebe2019-06-20 08:50:23 -0700355#else
356 GTEST_SKIP() << "valloc not supported.";
Dan Alberte5fdaa42014-06-14 01:04:31 +0000357#endif
Christopher Ferris804cebe2019-06-20 08:50:23 -0700358}
Dan Albert4caa1f02014-08-20 09:16:57 -0700359
360TEST(malloc, malloc_info) {
361#ifdef __BIONIC__
Evgenii Stepanov8de6b462019-03-22 13:22:28 -0700362 SKIP_WITH_HWASAN; // hwasan does not implement malloc_info
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800363
364 TemporaryFile tf;
365 ASSERT_TRUE(tf.fd != -1);
366 FILE* fp = fdopen(tf.fd, "w+");
367 tf.release();
368 ASSERT_TRUE(fp != nullptr);
369 ASSERT_EQ(0, malloc_info(0, fp));
370 ASSERT_EQ(0, fclose(fp));
371
372 std::string contents;
373 ASSERT_TRUE(android::base::ReadFileToString(tf.path, &contents));
Dan Albert4caa1f02014-08-20 09:16:57 -0700374
375 tinyxml2::XMLDocument doc;
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800376 ASSERT_EQ(tinyxml2::XML_SUCCESS, doc.Parse(contents.c_str()));
Dan Albert4caa1f02014-08-20 09:16:57 -0700377
378 auto root = doc.FirstChildElement();
379 ASSERT_NE(nullptr, root);
380 ASSERT_STREQ("malloc", root->Name());
Christopher Ferris85169652019-10-09 18:41:55 -0700381 std::string version(root->Attribute("version"));
382 if (version == "jemalloc-1") {
Christopher Ferris6c619a02019-03-01 17:59:51 -0800383 // Verify jemalloc version of this data.
384 ASSERT_STREQ("jemalloc-1", root->Attribute("version"));
Dan Albert4caa1f02014-08-20 09:16:57 -0700385
Christopher Ferris6c619a02019-03-01 17:59:51 -0800386 auto arena = root->FirstChildElement();
387 for (; arena != nullptr; arena = arena->NextSiblingElement()) {
388 int val;
Dan Albert4caa1f02014-08-20 09:16:57 -0700389
Christopher Ferris6c619a02019-03-01 17:59:51 -0800390 ASSERT_STREQ("heap", arena->Name());
391 ASSERT_EQ(tinyxml2::XML_SUCCESS, arena->QueryIntAttribute("nr", &val));
392 ASSERT_EQ(tinyxml2::XML_SUCCESS,
393 arena->FirstChildElement("allocated-large")->QueryIntText(&val));
394 ASSERT_EQ(tinyxml2::XML_SUCCESS,
395 arena->FirstChildElement("allocated-huge")->QueryIntText(&val));
396 ASSERT_EQ(tinyxml2::XML_SUCCESS,
397 arena->FirstChildElement("allocated-bins")->QueryIntText(&val));
398 ASSERT_EQ(tinyxml2::XML_SUCCESS,
399 arena->FirstChildElement("bins-total")->QueryIntText(&val));
Dan Albert4caa1f02014-08-20 09:16:57 -0700400
Christopher Ferris6c619a02019-03-01 17:59:51 -0800401 auto bin = arena->FirstChildElement("bin");
402 for (; bin != nullptr; bin = bin ->NextSiblingElement()) {
403 if (strcmp(bin->Name(), "bin") == 0) {
404 ASSERT_EQ(tinyxml2::XML_SUCCESS, bin->QueryIntAttribute("nr", &val));
405 ASSERT_EQ(tinyxml2::XML_SUCCESS,
406 bin->FirstChildElement("allocated")->QueryIntText(&val));
407 ASSERT_EQ(tinyxml2::XML_SUCCESS,
408 bin->FirstChildElement("nmalloc")->QueryIntText(&val));
409 ASSERT_EQ(tinyxml2::XML_SUCCESS,
410 bin->FirstChildElement("ndalloc")->QueryIntText(&val));
411 }
Dan Albert4caa1f02014-08-20 09:16:57 -0700412 }
413 }
Christopher Ferris6c619a02019-03-01 17:59:51 -0800414 } else {
Christopher Ferris85169652019-10-09 18:41:55 -0700415 // Do not verify output for scudo or debug malloc.
416 ASSERT_TRUE(version == "scudo-1" || version == "debug-malloc-1")
417 << "Unknown version: " << version;
Dan Albert4caa1f02014-08-20 09:16:57 -0700418 }
419#endif
420}
Christopher Ferrisad33ebe2015-12-16 12:07:25 -0800421
Christopher Ferrisdb9706a2019-05-02 18:33:11 -0700422TEST(malloc, malloc_info_matches_mallinfo) {
423#ifdef __BIONIC__
424 SKIP_WITH_HWASAN; // hwasan does not implement malloc_info
425
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800426 TemporaryFile tf;
427 ASSERT_TRUE(tf.fd != -1);
428 FILE* fp = fdopen(tf.fd, "w+");
429 tf.release();
430 ASSERT_TRUE(fp != nullptr);
Christopher Ferrisdb9706a2019-05-02 18:33:11 -0700431 size_t mallinfo_before_allocated_bytes = mallinfo().uordblks;
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800432 ASSERT_EQ(0, malloc_info(0, fp));
Christopher Ferrisdb9706a2019-05-02 18:33:11 -0700433 size_t mallinfo_after_allocated_bytes = mallinfo().uordblks;
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800434 ASSERT_EQ(0, fclose(fp));
435
436 std::string contents;
437 ASSERT_TRUE(android::base::ReadFileToString(tf.path, &contents));
Christopher Ferrisdb9706a2019-05-02 18:33:11 -0700438
439 tinyxml2::XMLDocument doc;
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800440 ASSERT_EQ(tinyxml2::XML_SUCCESS, doc.Parse(contents.c_str()));
Christopher Ferrisdb9706a2019-05-02 18:33:11 -0700441
442 size_t total_allocated_bytes = 0;
443 auto root = doc.FirstChildElement();
444 ASSERT_NE(nullptr, root);
445 ASSERT_STREQ("malloc", root->Name());
Christopher Ferris85169652019-10-09 18:41:55 -0700446 std::string version(root->Attribute("version"));
447 if (version == "jemalloc-1") {
Christopher Ferrisdb9706a2019-05-02 18:33:11 -0700448 // Verify jemalloc version of this data.
449 ASSERT_STREQ("jemalloc-1", root->Attribute("version"));
450
451 auto arena = root->FirstChildElement();
452 for (; arena != nullptr; arena = arena->NextSiblingElement()) {
453 int val;
454
455 ASSERT_STREQ("heap", arena->Name());
456 ASSERT_EQ(tinyxml2::XML_SUCCESS, arena->QueryIntAttribute("nr", &val));
457 ASSERT_EQ(tinyxml2::XML_SUCCESS,
458 arena->FirstChildElement("allocated-large")->QueryIntText(&val));
459 total_allocated_bytes += val;
460 ASSERT_EQ(tinyxml2::XML_SUCCESS,
461 arena->FirstChildElement("allocated-huge")->QueryIntText(&val));
462 total_allocated_bytes += val;
463 ASSERT_EQ(tinyxml2::XML_SUCCESS,
464 arena->FirstChildElement("allocated-bins")->QueryIntText(&val));
465 total_allocated_bytes += val;
466 ASSERT_EQ(tinyxml2::XML_SUCCESS,
467 arena->FirstChildElement("bins-total")->QueryIntText(&val));
468 }
469 // The total needs to be between the mallinfo call before and after
470 // since malloc_info allocates some memory.
471 EXPECT_LE(mallinfo_before_allocated_bytes, total_allocated_bytes);
472 EXPECT_GE(mallinfo_after_allocated_bytes, total_allocated_bytes);
473 } else {
Christopher Ferris85169652019-10-09 18:41:55 -0700474 // Do not verify output for scudo or debug malloc.
475 ASSERT_TRUE(version == "scudo-1" || version == "debug-malloc-1")
476 << "Unknown version: " << version;
Christopher Ferrisdb9706a2019-05-02 18:33:11 -0700477 }
478#endif
479}
480
Christopher Ferrisad33ebe2015-12-16 12:07:25 -0800481TEST(malloc, calloc_usable_size) {
482 for (size_t size = 1; size <= 2048; size++) {
483 void* pointer = malloc(size);
484 ASSERT_TRUE(pointer != nullptr);
485 memset(pointer, 0xeb, malloc_usable_size(pointer));
486 free(pointer);
487
488 // We should get a previous pointer that has been set to non-zero.
489 // If calloc does not zero out all of the data, this will fail.
490 uint8_t* zero_mem = reinterpret_cast<uint8_t*>(calloc(1, size));
491 ASSERT_TRUE(pointer != nullptr);
492 size_t usable_size = malloc_usable_size(zero_mem);
493 for (size_t i = 0; i < usable_size; i++) {
494 ASSERT_EQ(0, zero_mem[i]) << "Failed at allocation size " << size << " at byte " << i;
495 }
496 free(zero_mem);
497 }
498}
Elliott Hughes884f76e2016-02-10 20:43:22 -0800499
500TEST(malloc, malloc_0) {
501 void* p = malloc(0);
502 ASSERT_TRUE(p != nullptr);
503 free(p);
504}
505
506TEST(malloc, calloc_0_0) {
507 void* p = calloc(0, 0);
508 ASSERT_TRUE(p != nullptr);
509 free(p);
510}
511
512TEST(malloc, calloc_0_1) {
513 void* p = calloc(0, 1);
514 ASSERT_TRUE(p != nullptr);
515 free(p);
516}
517
518TEST(malloc, calloc_1_0) {
519 void* p = calloc(1, 0);
520 ASSERT_TRUE(p != nullptr);
521 free(p);
522}
523
524TEST(malloc, realloc_nullptr_0) {
525 // realloc(nullptr, size) is actually malloc(size).
526 void* p = realloc(nullptr, 0);
527 ASSERT_TRUE(p != nullptr);
528 free(p);
529}
530
531TEST(malloc, realloc_0) {
532 void* p = malloc(1024);
533 ASSERT_TRUE(p != nullptr);
534 // realloc(p, 0) is actually free(p).
535 void* p2 = realloc(p, 0);
536 ASSERT_TRUE(p2 == nullptr);
537}
Christopher Ferris72df6702016-02-11 15:51:31 -0800538
539constexpr size_t MAX_LOOPS = 200;
540
541// Make sure that memory returned by malloc is aligned to allow these data types.
542TEST(malloc, verify_alignment) {
543 uint32_t** values_32 = new uint32_t*[MAX_LOOPS];
544 uint64_t** values_64 = new uint64_t*[MAX_LOOPS];
545 long double** values_ldouble = new long double*[MAX_LOOPS];
546 // Use filler to attempt to force the allocator to get potentially bad alignments.
547 void** filler = new void*[MAX_LOOPS];
548
549 for (size_t i = 0; i < MAX_LOOPS; i++) {
550 // Check uint32_t pointers.
551 filler[i] = malloc(1);
552 ASSERT_TRUE(filler[i] != nullptr);
553
554 values_32[i] = reinterpret_cast<uint32_t*>(malloc(sizeof(uint32_t)));
555 ASSERT_TRUE(values_32[i] != nullptr);
556 *values_32[i] = i;
557 ASSERT_EQ(*values_32[i], i);
558 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(values_32[i]) & (sizeof(uint32_t) - 1));
559
560 free(filler[i]);
561 }
562
563 for (size_t i = 0; i < MAX_LOOPS; i++) {
564 // Check uint64_t pointers.
565 filler[i] = malloc(1);
566 ASSERT_TRUE(filler[i] != nullptr);
567
568 values_64[i] = reinterpret_cast<uint64_t*>(malloc(sizeof(uint64_t)));
569 ASSERT_TRUE(values_64[i] != nullptr);
570 *values_64[i] = 0x1000 + i;
571 ASSERT_EQ(*values_64[i], 0x1000 + i);
572 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(values_64[i]) & (sizeof(uint64_t) - 1));
573
574 free(filler[i]);
575 }
576
577 for (size_t i = 0; i < MAX_LOOPS; i++) {
578 // Check long double pointers.
579 filler[i] = malloc(1);
580 ASSERT_TRUE(filler[i] != nullptr);
581
582 values_ldouble[i] = reinterpret_cast<long double*>(malloc(sizeof(long double)));
583 ASSERT_TRUE(values_ldouble[i] != nullptr);
584 *values_ldouble[i] = 5.5 + i;
585 ASSERT_DOUBLE_EQ(*values_ldouble[i], 5.5 + i);
586 // 32 bit glibc has a long double size of 12 bytes, so hardcode the
587 // required alignment to 0x7.
588#if !defined(__BIONIC__) && !defined(__LP64__)
589 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(values_ldouble[i]) & 0x7);
590#else
591 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(values_ldouble[i]) & (sizeof(long double) - 1));
592#endif
593
594 free(filler[i]);
595 }
596
597 for (size_t i = 0; i < MAX_LOOPS; i++) {
598 free(values_32[i]);
599 free(values_64[i]);
600 free(values_ldouble[i]);
601 }
602
603 delete[] filler;
604 delete[] values_32;
605 delete[] values_64;
606 delete[] values_ldouble;
607}
Christopher Ferrisa1c0d2f2017-05-15 15:50:19 -0700608
609TEST(malloc, mallopt_smoke) {
610 errno = 0;
611 ASSERT_EQ(0, mallopt(-1000, 1));
612 // mallopt doesn't set errno.
613 ASSERT_EQ(0, errno);
614}
Elliott Hughesb1770852018-09-18 12:52:42 -0700615
Christopher Ferrisaf1b8dd2018-11-07 15:28:16 -0800616TEST(malloc, mallopt_decay) {
617#if defined(__BIONIC__)
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800618 SKIP_WITH_HWASAN << "hwasan does not implement mallopt";
Christopher Ferrisaf1b8dd2018-11-07 15:28:16 -0800619 errno = 0;
620 ASSERT_EQ(1, mallopt(M_DECAY_TIME, 1));
621 ASSERT_EQ(1, mallopt(M_DECAY_TIME, 0));
622 ASSERT_EQ(1, mallopt(M_DECAY_TIME, 1));
623 ASSERT_EQ(1, mallopt(M_DECAY_TIME, 0));
624#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800625 GTEST_SKIP() << "bionic-only test";
Christopher Ferrisaf1b8dd2018-11-07 15:28:16 -0800626#endif
627}
628
629TEST(malloc, mallopt_purge) {
630#if defined(__BIONIC__)
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800631 SKIP_WITH_HWASAN << "hwasan does not implement mallopt";
Christopher Ferrisaf1b8dd2018-11-07 15:28:16 -0800632 errno = 0;
633 ASSERT_EQ(1, mallopt(M_PURGE, 0));
634#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800635 GTEST_SKIP() << "bionic-only test";
Christopher Ferrisaf1b8dd2018-11-07 15:28:16 -0800636#endif
637}
638
Elliott Hughesb1770852018-09-18 12:52:42 -0700639TEST(malloc, reallocarray_overflow) {
640#if HAVE_REALLOCARRAY
641 // Values that cause overflow to a result small enough (8 on LP64) that malloc would "succeed".
642 size_t a = static_cast<size_t>(INTPTR_MIN + 4);
643 size_t b = 2;
644
645 errno = 0;
646 ASSERT_TRUE(reallocarray(nullptr, a, b) == nullptr);
647 ASSERT_EQ(ENOMEM, errno);
648
649 errno = 0;
650 ASSERT_TRUE(reallocarray(nullptr, b, a) == nullptr);
651 ASSERT_EQ(ENOMEM, errno);
652#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800653 GTEST_SKIP() << "reallocarray not available";
Elliott Hughesb1770852018-09-18 12:52:42 -0700654#endif
655}
656
657TEST(malloc, reallocarray) {
658#if HAVE_REALLOCARRAY
659 void* p = reallocarray(nullptr, 2, 32);
660 ASSERT_TRUE(p != nullptr);
661 ASSERT_GE(malloc_usable_size(p), 64U);
662#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800663 GTEST_SKIP() << "reallocarray not available";
Elliott Hughesb1770852018-09-18 12:52:42 -0700664#endif
665}
Christopher Ferris09a19aa2018-11-16 13:28:56 -0800666
667TEST(malloc, mallinfo) {
668#if defined(__BIONIC__)
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800669 SKIP_WITH_HWASAN << "hwasan does not implement mallinfo";
Christopher Ferris09a19aa2018-11-16 13:28:56 -0800670 static size_t sizes[] = {
671 8, 32, 128, 4096, 32768, 131072, 1024000, 10240000, 20480000, 300000000
672 };
673
674 constexpr static size_t kMaxAllocs = 50;
675
676 for (size_t size : sizes) {
677 // If some of these allocations are stuck in a thread cache, then keep
678 // looping until we make an allocation that changes the total size of the
679 // memory allocated.
680 // jemalloc implementations counts the thread cache allocations against
681 // total memory allocated.
682 void* ptrs[kMaxAllocs] = {};
683 bool pass = false;
684 for (size_t i = 0; i < kMaxAllocs; i++) {
685 size_t allocated = mallinfo().uordblks;
686 ptrs[i] = malloc(size);
687 ASSERT_TRUE(ptrs[i] != nullptr);
688 size_t new_allocated = mallinfo().uordblks;
689 if (allocated != new_allocated) {
690 size_t usable_size = malloc_usable_size(ptrs[i]);
Christopher Ferris4e562282019-02-07 14:20:03 -0800691 // Only check if the total got bigger by at least allocation size.
692 // Sometimes the mallinfo numbers can go backwards due to compaction
693 // and/or freeing of cached data.
694 if (new_allocated >= allocated + usable_size) {
695 pass = true;
696 break;
697 }
Christopher Ferris09a19aa2018-11-16 13:28:56 -0800698 }
699 }
700 for (void* ptr : ptrs) {
701 free(ptr);
702 }
703 ASSERT_TRUE(pass)
704 << "For size " << size << " allocated bytes did not increase after "
705 << kMaxAllocs << " allocations.";
706 }
707#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800708 GTEST_SKIP() << "glibc is broken";
Christopher Ferris09a19aa2018-11-16 13:28:56 -0800709#endif
710}
Ryan Savitskiecc37e32018-12-14 15:57:21 +0000711
Christopher Ferrisf32494c2020-01-08 14:19:10 -0800712template <typename Type>
713void __attribute__((optnone)) VerifyAlignment(Type* floating) {
714 size_t expected_alignment = alignof(Type);
715 if (expected_alignment != 0) {
716 ASSERT_EQ(0U, (expected_alignment - 1) & reinterpret_cast<uintptr_t>(floating))
717 << "Expected alignment " << expected_alignment << " ptr value " << floating;
718 }
719}
720
721template <typename Type>
722void __attribute__((optnone)) TestAllocateType() {
723 // The number of allocations to do in a row. This is to attempt to
724 // expose the worst case alignment for native allocators that use
725 // bins.
726 static constexpr size_t kMaxConsecutiveAllocs = 100;
727
728 // Verify using new directly.
729 Type* types[kMaxConsecutiveAllocs];
730 for (size_t i = 0; i < kMaxConsecutiveAllocs; i++) {
731 types[i] = new Type;
732 VerifyAlignment(types[i]);
733 if (::testing::Test::HasFatalFailure()) {
734 return;
735 }
736 }
737 for (size_t i = 0; i < kMaxConsecutiveAllocs; i++) {
738 delete types[i];
739 }
740
741 // Verify using malloc.
742 for (size_t i = 0; i < kMaxConsecutiveAllocs; i++) {
743 types[i] = reinterpret_cast<Type*>(malloc(sizeof(Type)));
744 ASSERT_TRUE(types[i] != nullptr);
745 VerifyAlignment(types[i]);
746 if (::testing::Test::HasFatalFailure()) {
747 return;
748 }
749 }
750 for (size_t i = 0; i < kMaxConsecutiveAllocs; i++) {
751 free(types[i]);
752 }
753
754 // Verify using a vector.
755 std::vector<Type> type_vector(kMaxConsecutiveAllocs);
756 for (size_t i = 0; i < type_vector.size(); i++) {
757 VerifyAlignment(&type_vector[i]);
758 if (::testing::Test::HasFatalFailure()) {
759 return;
760 }
761 }
762}
763
764#if defined(__ANDROID__)
765static void __attribute__((optnone)) AndroidVerifyAlignment(size_t alloc_size, size_t aligned_bytes) {
766 void* ptrs[100];
767 uintptr_t mask = aligned_bytes - 1;
768 for (size_t i = 0; i < sizeof(ptrs) / sizeof(void*); i++) {
769 ptrs[i] = malloc(alloc_size);
770 ASSERT_TRUE(ptrs[i] != nullptr);
771 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(ptrs[i]) & mask)
772 << "Expected at least " << aligned_bytes << " byte alignment: size "
773 << alloc_size << " actual ptr " << ptrs[i];
774 }
775}
776#endif
777
778TEST(malloc, align_check) {
779 // See http://www.open-std.org/jtc1/sc22/wg14/www/docs/summary.htm#dr_445
780 // for a discussion of type alignment.
781 ASSERT_NO_FATAL_FAILURE(TestAllocateType<float>());
782 ASSERT_NO_FATAL_FAILURE(TestAllocateType<double>());
783 ASSERT_NO_FATAL_FAILURE(TestAllocateType<long double>());
784
785 ASSERT_NO_FATAL_FAILURE(TestAllocateType<char>());
786 ASSERT_NO_FATAL_FAILURE(TestAllocateType<char16_t>());
787 ASSERT_NO_FATAL_FAILURE(TestAllocateType<char32_t>());
788 ASSERT_NO_FATAL_FAILURE(TestAllocateType<wchar_t>());
789 ASSERT_NO_FATAL_FAILURE(TestAllocateType<signed char>());
790 ASSERT_NO_FATAL_FAILURE(TestAllocateType<short int>());
791 ASSERT_NO_FATAL_FAILURE(TestAllocateType<int>());
792 ASSERT_NO_FATAL_FAILURE(TestAllocateType<long int>());
793 ASSERT_NO_FATAL_FAILURE(TestAllocateType<long long int>());
794 ASSERT_NO_FATAL_FAILURE(TestAllocateType<unsigned char>());
795 ASSERT_NO_FATAL_FAILURE(TestAllocateType<unsigned short int>());
796 ASSERT_NO_FATAL_FAILURE(TestAllocateType<unsigned int>());
797 ASSERT_NO_FATAL_FAILURE(TestAllocateType<unsigned long int>());
798 ASSERT_NO_FATAL_FAILURE(TestAllocateType<unsigned long long int>());
799
800#if defined(__ANDROID__)
801 // On Android, there is a lot of code that expects certain alignments:
802 // - Allocations of a size that rounds up to a multiple of 16 bytes
803 // must have at least 16 byte alignment.
804 // - Allocations of a size that rounds up to a multiple of 8 bytes and
805 // not 16 bytes, are only required to have at least 8 byte alignment.
806 // This is regardless of whether it is in a 32 bit or 64 bit environment.
807
808 // See http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2293.htm for
809 // a discussion of this alignment mess. The code below is enforcing
810 // strong-alignment, since who knows what code depends on this behavior now.
811 for (size_t i = 1; i <= 128; i++) {
812 size_t rounded = (i + 7) & ~7;
813 if ((rounded % 16) == 0) {
814 AndroidVerifyAlignment(i, 16);
815 } else {
816 AndroidVerifyAlignment(i, 8);
817 }
818 if (::testing::Test::HasFatalFailure()) {
819 return;
820 }
821 }
822#endif
823}
824
Ryan Savitskiecc37e32018-12-14 15:57:21 +0000825TEST(android_mallopt, error_on_unexpected_option) {
826#if defined(__BIONIC__)
827 const int unrecognized_option = -1;
828 errno = 0;
829 EXPECT_EQ(false, android_mallopt(unrecognized_option, nullptr, 0));
830 EXPECT_EQ(ENOTSUP, errno);
831#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800832 GTEST_SKIP() << "bionic-only test";
Ryan Savitskiecc37e32018-12-14 15:57:21 +0000833#endif
834}
835
Christopher Ferrise4cdbc42019-02-08 17:30:58 -0800836bool IsDynamic() {
837#if defined(__LP64__)
838 Elf64_Ehdr ehdr;
839#else
840 Elf32_Ehdr ehdr;
841#endif
842 std::string path(android::base::GetExecutablePath());
843
844 int fd = open(path.c_str(), O_RDONLY | O_CLOEXEC);
845 if (fd == -1) {
846 // Assume dynamic on error.
847 return true;
848 }
849 bool read_completed = android::base::ReadFully(fd, &ehdr, sizeof(ehdr));
850 close(fd);
851 // Assume dynamic in error cases.
852 return !read_completed || ehdr.e_type == ET_DYN;
853}
854
Ryan Savitskiecc37e32018-12-14 15:57:21 +0000855TEST(android_mallopt, init_zygote_child_profiling) {
856#if defined(__BIONIC__)
857 // Successful call.
858 errno = 0;
Christopher Ferrise4cdbc42019-02-08 17:30:58 -0800859 if (IsDynamic()) {
860 EXPECT_EQ(true, android_mallopt(M_INIT_ZYGOTE_CHILD_PROFILING, nullptr, 0));
861 EXPECT_EQ(0, errno);
862 } else {
863 // Not supported in static executables.
864 EXPECT_EQ(false, android_mallopt(M_INIT_ZYGOTE_CHILD_PROFILING, nullptr, 0));
865 EXPECT_EQ(ENOTSUP, errno);
866 }
Ryan Savitskiecc37e32018-12-14 15:57:21 +0000867
868 // Unexpected arguments rejected.
869 errno = 0;
870 char unexpected = 0;
871 EXPECT_EQ(false, android_mallopt(M_INIT_ZYGOTE_CHILD_PROFILING, &unexpected, 1));
Christopher Ferrise4cdbc42019-02-08 17:30:58 -0800872 if (IsDynamic()) {
873 EXPECT_EQ(EINVAL, errno);
874 } else {
875 EXPECT_EQ(ENOTSUP, errno);
876 }
Ryan Savitskiecc37e32018-12-14 15:57:21 +0000877#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800878 GTEST_SKIP() << "bionic-only test";
Ryan Savitskiecc37e32018-12-14 15:57:21 +0000879#endif
880}
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -0800881
882#if defined(__BIONIC__)
883template <typename FuncType>
884void CheckAllocationFunction(FuncType func) {
885 // Assumes that no more than 108MB of memory is allocated before this.
886 size_t limit = 128 * 1024 * 1024;
887 ASSERT_TRUE(android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit)));
888 if (!func(20 * 1024 * 1024))
889 exit(1);
890 if (func(128 * 1024 * 1024))
891 exit(1);
892 exit(0);
893}
894#endif
895
896TEST(android_mallopt, set_allocation_limit) {
897#if defined(__BIONIC__)
898 EXPECT_EXIT(CheckAllocationFunction([](size_t bytes) { return calloc(bytes, 1) != nullptr; }),
899 testing::ExitedWithCode(0), "");
900 EXPECT_EXIT(CheckAllocationFunction([](size_t bytes) { return calloc(1, bytes) != nullptr; }),
901 testing::ExitedWithCode(0), "");
902 EXPECT_EXIT(CheckAllocationFunction([](size_t bytes) { return malloc(bytes) != nullptr; }),
903 testing::ExitedWithCode(0), "");
904 EXPECT_EXIT(CheckAllocationFunction(
905 [](size_t bytes) { return memalign(sizeof(void*), bytes) != nullptr; }),
906 testing::ExitedWithCode(0), "");
907 EXPECT_EXIT(CheckAllocationFunction([](size_t bytes) {
908 void* ptr;
909 return posix_memalign(&ptr, sizeof(void *), bytes) == 0;
910 }),
911 testing::ExitedWithCode(0), "");
912 EXPECT_EXIT(CheckAllocationFunction(
913 [](size_t bytes) { return aligned_alloc(sizeof(void*), bytes) != nullptr; }),
914 testing::ExitedWithCode(0), "");
915 EXPECT_EXIT(CheckAllocationFunction([](size_t bytes) {
916 void* p = malloc(1024 * 1024);
917 return realloc(p, bytes) != nullptr;
918 }),
919 testing::ExitedWithCode(0), "");
920#if !defined(__LP64__)
921 EXPECT_EXIT(CheckAllocationFunction([](size_t bytes) { return pvalloc(bytes) != nullptr; }),
922 testing::ExitedWithCode(0), "");
923 EXPECT_EXIT(CheckAllocationFunction([](size_t bytes) { return valloc(bytes) != nullptr; }),
924 testing::ExitedWithCode(0), "");
925#endif
926#else
Elliott Hughes10907202019-03-27 08:51:02 -0700927 GTEST_SKIP() << "bionic extension";
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -0800928#endif
929}
930
931TEST(android_mallopt, set_allocation_limit_multiple) {
932#if defined(__BIONIC__)
933 // Only the first set should work.
934 size_t limit = 256 * 1024 * 1024;
935 ASSERT_TRUE(android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit)));
936 limit = 32 * 1024 * 1024;
937 ASSERT_FALSE(android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit)));
938#else
Elliott Hughes10907202019-03-27 08:51:02 -0700939 GTEST_SKIP() << "bionic extension";
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -0800940#endif
941}
942
943#if defined(__BIONIC__)
944static constexpr size_t kAllocationSize = 8 * 1024 * 1024;
945
946static size_t GetMaxAllocations() {
947 size_t max_pointers = 0;
948 void* ptrs[20];
949 for (size_t i = 0; i < sizeof(ptrs) / sizeof(void*); i++) {
950 ptrs[i] = malloc(kAllocationSize);
951 if (ptrs[i] == nullptr) {
952 max_pointers = i;
953 break;
954 }
955 }
956 for (size_t i = 0; i < max_pointers; i++) {
957 free(ptrs[i]);
958 }
959 return max_pointers;
960}
961
962static void VerifyMaxPointers(size_t max_pointers) {
963 // Now verify that we can allocate the same number as before.
964 void* ptrs[20];
965 for (size_t i = 0; i < max_pointers; i++) {
966 ptrs[i] = malloc(kAllocationSize);
967 ASSERT_TRUE(ptrs[i] != nullptr) << "Failed to allocate on iteration " << i;
968 }
969
970 // Make sure the next allocation still fails.
971 ASSERT_TRUE(malloc(kAllocationSize) == nullptr);
972 for (size_t i = 0; i < max_pointers; i++) {
973 free(ptrs[i]);
974 }
975}
976#endif
977
978TEST(android_mallopt, set_allocation_limit_realloc_increase) {
979#if defined(__BIONIC__)
980 size_t limit = 128 * 1024 * 1024;
981 ASSERT_TRUE(android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit)));
982
983 size_t max_pointers = GetMaxAllocations();
984 ASSERT_TRUE(max_pointers != 0) << "Limit never reached.";
985
986 void* memory = malloc(10 * 1024 * 1024);
987 ASSERT_TRUE(memory != nullptr);
988
989 // Increase size.
990 memory = realloc(memory, 20 * 1024 * 1024);
991 ASSERT_TRUE(memory != nullptr);
992 memory = realloc(memory, 40 * 1024 * 1024);
993 ASSERT_TRUE(memory != nullptr);
994 memory = realloc(memory, 60 * 1024 * 1024);
995 ASSERT_TRUE(memory != nullptr);
996 memory = realloc(memory, 80 * 1024 * 1024);
997 ASSERT_TRUE(memory != nullptr);
998 // Now push past limit.
999 memory = realloc(memory, 130 * 1024 * 1024);
1000 ASSERT_TRUE(memory == nullptr);
1001
1002 VerifyMaxPointers(max_pointers);
1003#else
Elliott Hughes10907202019-03-27 08:51:02 -07001004 GTEST_SKIP() << "bionic extension";
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -08001005#endif
1006}
1007
1008TEST(android_mallopt, set_allocation_limit_realloc_decrease) {
1009#if defined(__BIONIC__)
1010 size_t limit = 100 * 1024 * 1024;
1011 ASSERT_TRUE(android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit)));
1012
1013 size_t max_pointers = GetMaxAllocations();
1014 ASSERT_TRUE(max_pointers != 0) << "Limit never reached.";
1015
1016 void* memory = malloc(80 * 1024 * 1024);
1017 ASSERT_TRUE(memory != nullptr);
1018
1019 // Decrease size.
1020 memory = realloc(memory, 60 * 1024 * 1024);
1021 ASSERT_TRUE(memory != nullptr);
1022 memory = realloc(memory, 40 * 1024 * 1024);
1023 ASSERT_TRUE(memory != nullptr);
1024 memory = realloc(memory, 20 * 1024 * 1024);
1025 ASSERT_TRUE(memory != nullptr);
1026 memory = realloc(memory, 10 * 1024 * 1024);
1027 ASSERT_TRUE(memory != nullptr);
1028 free(memory);
1029
1030 VerifyMaxPointers(max_pointers);
1031#else
Elliott Hughes10907202019-03-27 08:51:02 -07001032 GTEST_SKIP() << "bionic extension";
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -08001033#endif
1034}
1035
1036TEST(android_mallopt, set_allocation_limit_realloc_free) {
1037#if defined(__BIONIC__)
1038 size_t limit = 100 * 1024 * 1024;
1039 ASSERT_TRUE(android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit)));
1040
1041 size_t max_pointers = GetMaxAllocations();
1042 ASSERT_TRUE(max_pointers != 0) << "Limit never reached.";
1043
1044 void* memory = malloc(60 * 1024 * 1024);
1045 ASSERT_TRUE(memory != nullptr);
1046
1047 memory = realloc(memory, 0);
1048 ASSERT_TRUE(memory == nullptr);
1049
1050 VerifyMaxPointers(max_pointers);
1051#else
Elliott Hughes10907202019-03-27 08:51:02 -07001052 GTEST_SKIP() << "bionic extension";
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -08001053#endif
1054}
1055
1056#if defined(__BIONIC__)
1057static void* SetAllocationLimit(void* data) {
1058 std::atomic_bool* go = reinterpret_cast<std::atomic_bool*>(data);
1059 while (!go->load()) {
1060 }
1061 size_t limit = 500 * 1024 * 1024;
1062 if (android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit))) {
1063 return reinterpret_cast<void*>(-1);
1064 }
1065 return nullptr;
1066}
1067
1068static void SetAllocationLimitMultipleThreads() {
1069 std::atomic_bool go;
1070 go = false;
1071
1072 static constexpr size_t kNumThreads = 4;
1073 pthread_t threads[kNumThreads];
1074 for (size_t i = 0; i < kNumThreads; i++) {
1075 ASSERT_EQ(0, pthread_create(&threads[i], nullptr, SetAllocationLimit, &go));
1076 }
1077
1078 // Let them go all at once.
1079 go = true;
1080 ASSERT_EQ(0, kill(getpid(), __SIGRTMIN + 4));
1081
1082 size_t num_successful = 0;
1083 for (size_t i = 0; i < kNumThreads; i++) {
1084 void* result;
1085 ASSERT_EQ(0, pthread_join(threads[i], &result));
1086 if (result != nullptr) {
1087 num_successful++;
1088 }
1089 }
1090 ASSERT_EQ(1U, num_successful);
1091 exit(0);
1092}
1093#endif
1094
1095TEST(android_mallopt, set_allocation_limit_multiple_threads) {
1096#if defined(__BIONIC__)
1097 if (IsDynamic()) {
1098 ASSERT_TRUE(android_mallopt(M_INIT_ZYGOTE_CHILD_PROFILING, nullptr, 0));
1099 }
1100
1101 // Run this a number of times as a stress test.
1102 for (size_t i = 0; i < 100; i++) {
1103 // Not using ASSERT_EXIT because errors messages are not displayed.
1104 pid_t pid;
1105 if ((pid = fork()) == 0) {
1106 ASSERT_NO_FATAL_FAILURE(SetAllocationLimitMultipleThreads());
1107 }
1108 ASSERT_NE(-1, pid);
1109 int status;
1110 ASSERT_EQ(pid, wait(&status));
1111 ASSERT_EQ(0, WEXITSTATUS(status));
1112 }
1113#else
Elliott Hughes10907202019-03-27 08:51:02 -07001114 GTEST_SKIP() << "bionic extension";
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -08001115#endif
1116}