blob: c7050dc68e08549d4e8eb699f8fea28b088c26ab [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>
Ryan Savitski175c8862020-01-02 19:54:57 +000021#include <malloc.h>
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -080022#include <pthread.h>
Ryan Savitski175c8862020-01-02 19:54:57 +000023#include <signal.h>
Christopher Ferrisa4037802014-06-09 19:14:11 -070024#include <stdint.h>
Christopher Ferris6c619a02019-03-01 17:59:51 -080025#include <stdio.h>
Christopher Ferris885f3b92013-05-21 17:48:01 -070026#include <stdlib.h>
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -080027#include <string.h>
28#include <sys/types.h>
29#include <sys/wait.h>
Christopher Ferrisa4037802014-06-09 19:14:11 -070030#include <unistd.h>
Christopher Ferris885f3b92013-05-21 17:48:01 -070031
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -080032#include <atomic>
Dan Albert4caa1f02014-08-20 09:16:57 -070033#include <tinyxml2.h>
34
Christopher Ferrise4cdbc42019-02-08 17:30:58 -080035#include <android-base/file.h>
36
Christopher Ferris2b0638e2019-09-11 19:05:29 -070037#include "platform/bionic/malloc.h"
Christopher Ferris63619642014-06-16 23:35:53 -070038#include "private/bionic_config.h"
Evgenii Stepanovacd6f4f2018-11-06 16:48:27 -080039#include "utils.h"
Dan Alberte5fdaa42014-06-14 01:04:31 +000040
Elliott Hughesb1770852018-09-18 12:52:42 -070041#if defined(__BIONIC__)
42#define HAVE_REALLOCARRAY 1
43#else
44#define HAVE_REALLOCARRAY __GLIBC_PREREQ(2, 26)
45#endif
46
Christopher Ferris885f3b92013-05-21 17:48:01 -070047TEST(malloc, malloc_std) {
48 // Simple malloc test.
49 void *ptr = malloc(100);
Yi Kong32bc0fc2018-08-02 17:31:13 -070050 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -070051 ASSERT_LE(100U, malloc_usable_size(ptr));
Christopher Ferris885f3b92013-05-21 17:48:01 -070052 free(ptr);
53}
54
Christopher Ferrisa4037802014-06-09 19:14:11 -070055TEST(malloc, malloc_overflow) {
Evgenii Stepanovacd6f4f2018-11-06 16:48:27 -080056 SKIP_WITH_HWASAN;
Christopher Ferrisa4037802014-06-09 19:14:11 -070057 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -070058 ASSERT_EQ(nullptr, malloc(SIZE_MAX));
Christopher Ferrisa4037802014-06-09 19:14:11 -070059 ASSERT_EQ(ENOMEM, errno);
60}
61
Christopher Ferris885f3b92013-05-21 17:48:01 -070062TEST(malloc, calloc_std) {
63 // Simple calloc test.
64 size_t alloc_len = 100;
65 char *ptr = (char *)calloc(1, alloc_len);
Yi Kong32bc0fc2018-08-02 17:31:13 -070066 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -070067 ASSERT_LE(alloc_len, malloc_usable_size(ptr));
68 for (size_t i = 0; i < alloc_len; i++) {
69 ASSERT_EQ(0, ptr[i]);
70 }
Christopher Ferris885f3b92013-05-21 17:48:01 -070071 free(ptr);
72}
73
Christopher Ferrisa4037802014-06-09 19:14:11 -070074TEST(malloc, calloc_illegal) {
Evgenii Stepanovacd6f4f2018-11-06 16:48:27 -080075 SKIP_WITH_HWASAN;
Christopher Ferrisa4037802014-06-09 19:14:11 -070076 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -070077 ASSERT_EQ(nullptr, calloc(-1, 100));
Christopher Ferrisa4037802014-06-09 19:14:11 -070078 ASSERT_EQ(ENOMEM, errno);
79}
80
81TEST(malloc, calloc_overflow) {
Evgenii Stepanovacd6f4f2018-11-06 16:48:27 -080082 SKIP_WITH_HWASAN;
Christopher Ferrisa4037802014-06-09 19:14:11 -070083 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -070084 ASSERT_EQ(nullptr, calloc(1, SIZE_MAX));
Christopher Ferrisa4037802014-06-09 19:14:11 -070085 ASSERT_EQ(ENOMEM, errno);
86 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -070087 ASSERT_EQ(nullptr, calloc(SIZE_MAX, SIZE_MAX));
Christopher Ferrisa4037802014-06-09 19:14:11 -070088 ASSERT_EQ(ENOMEM, errno);
89 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -070090 ASSERT_EQ(nullptr, calloc(2, SIZE_MAX));
Christopher Ferrisa4037802014-06-09 19:14:11 -070091 ASSERT_EQ(ENOMEM, errno);
92 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -070093 ASSERT_EQ(nullptr, calloc(SIZE_MAX, 2));
Christopher Ferrisa4037802014-06-09 19:14:11 -070094 ASSERT_EQ(ENOMEM, errno);
95}
96
Christopher Ferris885f3b92013-05-21 17:48:01 -070097TEST(malloc, memalign_multiple) {
Elliott Hughesbcaa4542019-03-08 15:20:23 -080098 SKIP_WITH_HWASAN << "hwasan requires power of 2 alignment";
Christopher Ferris885f3b92013-05-21 17:48:01 -070099 // Memalign test where the alignment is any value.
100 for (size_t i = 0; i <= 12; i++) {
101 for (size_t alignment = 1 << i; alignment < (1U << (i+1)); alignment++) {
Christopher Ferrisa4037802014-06-09 19:14:11 -0700102 char *ptr = reinterpret_cast<char*>(memalign(alignment, 100));
Yi Kong32bc0fc2018-08-02 17:31:13 -0700103 ASSERT_TRUE(ptr != nullptr) << "Failed at alignment " << alignment;
Christopher Ferrisa4037802014-06-09 19:14:11 -0700104 ASSERT_LE(100U, malloc_usable_size(ptr)) << "Failed at alignment " << alignment;
105 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(ptr) % ((1U << i)))
106 << "Failed at alignment " << alignment;
Christopher Ferris885f3b92013-05-21 17:48:01 -0700107 free(ptr);
108 }
109 }
110}
111
Christopher Ferrisa4037802014-06-09 19:14:11 -0700112TEST(malloc, memalign_overflow) {
Evgenii Stepanovacd6f4f2018-11-06 16:48:27 -0800113 SKIP_WITH_HWASAN;
Yi Kong32bc0fc2018-08-02 17:31:13 -0700114 ASSERT_EQ(nullptr, memalign(4096, SIZE_MAX));
Christopher Ferrisa4037802014-06-09 19:14:11 -0700115}
116
117TEST(malloc, memalign_non_power2) {
Evgenii Stepanovacd6f4f2018-11-06 16:48:27 -0800118 SKIP_WITH_HWASAN;
Christopher Ferrisa4037802014-06-09 19:14:11 -0700119 void* ptr;
120 for (size_t align = 0; align <= 256; align++) {
121 ptr = memalign(align, 1024);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700122 ASSERT_TRUE(ptr != nullptr) << "Failed at align " << align;
Christopher Ferrisa4037802014-06-09 19:14:11 -0700123 free(ptr);
124 }
125}
126
Christopher Ferris885f3b92013-05-21 17:48:01 -0700127TEST(malloc, memalign_realloc) {
128 // Memalign and then realloc the pointer a couple of times.
129 for (size_t alignment = 1; alignment <= 4096; alignment <<= 1) {
130 char *ptr = (char*)memalign(alignment, 100);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700131 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700132 ASSERT_LE(100U, malloc_usable_size(ptr));
133 ASSERT_EQ(0U, (intptr_t)ptr % alignment);
134 memset(ptr, 0x23, 100);
135
136 ptr = (char*)realloc(ptr, 200);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700137 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700138 ASSERT_LE(200U, malloc_usable_size(ptr));
Yi Kong32bc0fc2018-08-02 17:31:13 -0700139 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700140 for (size_t i = 0; i < 100; i++) {
141 ASSERT_EQ(0x23, ptr[i]);
142 }
143 memset(ptr, 0x45, 200);
144
145 ptr = (char*)realloc(ptr, 300);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700146 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700147 ASSERT_LE(300U, malloc_usable_size(ptr));
148 for (size_t i = 0; i < 200; i++) {
149 ASSERT_EQ(0x45, ptr[i]);
150 }
151 memset(ptr, 0x67, 300);
152
153 ptr = (char*)realloc(ptr, 250);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700154 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700155 ASSERT_LE(250U, malloc_usable_size(ptr));
156 for (size_t i = 0; i < 250; i++) {
157 ASSERT_EQ(0x67, ptr[i]);
158 }
Christopher Ferris885f3b92013-05-21 17:48:01 -0700159 free(ptr);
160 }
161}
162
163TEST(malloc, malloc_realloc_larger) {
164 // Realloc to a larger size, malloc is used for the original allocation.
165 char *ptr = (char *)malloc(100);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700166 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700167 ASSERT_LE(100U, malloc_usable_size(ptr));
168 memset(ptr, 67, 100);
169
170 ptr = (char *)realloc(ptr, 200);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700171 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700172 ASSERT_LE(200U, malloc_usable_size(ptr));
173 for (size_t i = 0; i < 100; i++) {
174 ASSERT_EQ(67, ptr[i]);
175 }
Christopher Ferris885f3b92013-05-21 17:48:01 -0700176 free(ptr);
177}
178
179TEST(malloc, malloc_realloc_smaller) {
180 // Realloc to a smaller size, malloc is used for the original allocation.
181 char *ptr = (char *)malloc(200);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700182 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700183 ASSERT_LE(200U, malloc_usable_size(ptr));
184 memset(ptr, 67, 200);
185
186 ptr = (char *)realloc(ptr, 100);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700187 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700188 ASSERT_LE(100U, malloc_usable_size(ptr));
189 for (size_t i = 0; i < 100; i++) {
190 ASSERT_EQ(67, ptr[i]);
191 }
Christopher Ferris885f3b92013-05-21 17:48:01 -0700192 free(ptr);
193}
194
195TEST(malloc, malloc_multiple_realloc) {
196 // Multiple reallocs, malloc is used for the original allocation.
197 char *ptr = (char *)malloc(200);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700198 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700199 ASSERT_LE(200U, malloc_usable_size(ptr));
200 memset(ptr, 0x23, 200);
201
202 ptr = (char *)realloc(ptr, 100);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700203 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700204 ASSERT_LE(100U, malloc_usable_size(ptr));
205 for (size_t i = 0; i < 100; i++) {
206 ASSERT_EQ(0x23, ptr[i]);
207 }
208
209 ptr = (char*)realloc(ptr, 50);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700210 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700211 ASSERT_LE(50U, malloc_usable_size(ptr));
212 for (size_t i = 0; i < 50; i++) {
213 ASSERT_EQ(0x23, ptr[i]);
214 }
215
216 ptr = (char*)realloc(ptr, 150);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700217 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700218 ASSERT_LE(150U, malloc_usable_size(ptr));
219 for (size_t i = 0; i < 50; i++) {
220 ASSERT_EQ(0x23, ptr[i]);
221 }
222 memset(ptr, 0x23, 150);
223
224 ptr = (char*)realloc(ptr, 425);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700225 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700226 ASSERT_LE(425U, malloc_usable_size(ptr));
227 for (size_t i = 0; i < 150; i++) {
228 ASSERT_EQ(0x23, ptr[i]);
229 }
Christopher Ferris885f3b92013-05-21 17:48:01 -0700230 free(ptr);
231}
Christopher Ferrisa4037802014-06-09 19:14:11 -0700232
Christopher Ferris885f3b92013-05-21 17:48:01 -0700233TEST(malloc, calloc_realloc_larger) {
234 // Realloc to a larger size, calloc is used for the original allocation.
235 char *ptr = (char *)calloc(1, 100);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700236 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700237 ASSERT_LE(100U, malloc_usable_size(ptr));
238
239 ptr = (char *)realloc(ptr, 200);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700240 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700241 ASSERT_LE(200U, malloc_usable_size(ptr));
242 for (size_t i = 0; i < 100; i++) {
243 ASSERT_EQ(0, ptr[i]);
244 }
Christopher Ferris885f3b92013-05-21 17:48:01 -0700245 free(ptr);
246}
247
248TEST(malloc, calloc_realloc_smaller) {
249 // Realloc to a smaller size, calloc is used for the original allocation.
250 char *ptr = (char *)calloc(1, 200);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700251 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700252 ASSERT_LE(200U, malloc_usable_size(ptr));
253
254 ptr = (char *)realloc(ptr, 100);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700255 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700256 ASSERT_LE(100U, malloc_usable_size(ptr));
257 for (size_t i = 0; i < 100; i++) {
258 ASSERT_EQ(0, ptr[i]);
259 }
Christopher Ferris885f3b92013-05-21 17:48:01 -0700260 free(ptr);
261}
262
263TEST(malloc, calloc_multiple_realloc) {
264 // Multiple reallocs, calloc is used for the original allocation.
265 char *ptr = (char *)calloc(1, 200);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700266 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700267 ASSERT_LE(200U, malloc_usable_size(ptr));
268
269 ptr = (char *)realloc(ptr, 100);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700270 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700271 ASSERT_LE(100U, malloc_usable_size(ptr));
272 for (size_t i = 0; i < 100; i++) {
273 ASSERT_EQ(0, ptr[i]);
274 }
275
276 ptr = (char*)realloc(ptr, 50);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700277 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700278 ASSERT_LE(50U, malloc_usable_size(ptr));
279 for (size_t i = 0; i < 50; i++) {
280 ASSERT_EQ(0, ptr[i]);
281 }
282
283 ptr = (char*)realloc(ptr, 150);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700284 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700285 ASSERT_LE(150U, malloc_usable_size(ptr));
286 for (size_t i = 0; i < 50; i++) {
287 ASSERT_EQ(0, ptr[i]);
288 }
289 memset(ptr, 0, 150);
290
291 ptr = (char*)realloc(ptr, 425);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700292 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700293 ASSERT_LE(425U, malloc_usable_size(ptr));
294 for (size_t i = 0; i < 150; i++) {
295 ASSERT_EQ(0, ptr[i]);
296 }
Christopher Ferris885f3b92013-05-21 17:48:01 -0700297 free(ptr);
298}
Christopher Ferris72bbd422014-05-08 11:14:03 -0700299
Christopher Ferrisa4037802014-06-09 19:14:11 -0700300TEST(malloc, realloc_overflow) {
Evgenii Stepanovacd6f4f2018-11-06 16:48:27 -0800301 SKIP_WITH_HWASAN;
Christopher Ferrisa4037802014-06-09 19:14:11 -0700302 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -0700303 ASSERT_EQ(nullptr, realloc(nullptr, SIZE_MAX));
Christopher Ferrisa4037802014-06-09 19:14:11 -0700304 ASSERT_EQ(ENOMEM, errno);
305 void* ptr = malloc(100);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700306 ASSERT_TRUE(ptr != nullptr);
Christopher Ferrisa4037802014-06-09 19:14:11 -0700307 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -0700308 ASSERT_EQ(nullptr, realloc(ptr, SIZE_MAX));
Christopher Ferrisa4037802014-06-09 19:14:11 -0700309 ASSERT_EQ(ENOMEM, errno);
310 free(ptr);
Christopher Ferris72bbd422014-05-08 11:14:03 -0700311}
312
Dan Alberte5fdaa42014-06-14 01:04:31 +0000313#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
314extern "C" void* pvalloc(size_t);
315extern "C" void* valloc(size_t);
Christopher Ferris804cebe2019-06-20 08:50:23 -0700316#endif
Dan Alberte5fdaa42014-06-14 01:04:31 +0000317
Christopher Ferrisa4037802014-06-09 19:14:11 -0700318TEST(malloc, pvalloc_std) {
Christopher Ferris804cebe2019-06-20 08:50:23 -0700319#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
Christopher Ferrisa4037802014-06-09 19:14:11 -0700320 size_t pagesize = sysconf(_SC_PAGESIZE);
321 void* ptr = pvalloc(100);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700322 ASSERT_TRUE(ptr != nullptr);
Christopher Ferrisa4037802014-06-09 19:14:11 -0700323 ASSERT_TRUE((reinterpret_cast<uintptr_t>(ptr) & (pagesize-1)) == 0);
324 ASSERT_LE(pagesize, malloc_usable_size(ptr));
325 free(ptr);
Christopher Ferris804cebe2019-06-20 08:50:23 -0700326#else
327 GTEST_SKIP() << "pvalloc not supported.";
328#endif
Christopher Ferrisa4037802014-06-09 19:14:11 -0700329}
330
331TEST(malloc, pvalloc_overflow) {
Christopher Ferris804cebe2019-06-20 08:50:23 -0700332#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
Yi Kong32bc0fc2018-08-02 17:31:13 -0700333 ASSERT_EQ(nullptr, pvalloc(SIZE_MAX));
Christopher Ferris804cebe2019-06-20 08:50:23 -0700334#else
335 GTEST_SKIP() << "pvalloc not supported.";
336#endif
Christopher Ferrisa4037802014-06-09 19:14:11 -0700337}
338
339TEST(malloc, valloc_std) {
Christopher Ferris804cebe2019-06-20 08:50:23 -0700340#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
Christopher Ferrisa4037802014-06-09 19:14:11 -0700341 size_t pagesize = sysconf(_SC_PAGESIZE);
Christopher Ferrisd5ab0a52019-06-19 12:03:57 -0700342 void* ptr = valloc(100);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700343 ASSERT_TRUE(ptr != nullptr);
Christopher Ferrisa4037802014-06-09 19:14:11 -0700344 ASSERT_TRUE((reinterpret_cast<uintptr_t>(ptr) & (pagesize-1)) == 0);
345 free(ptr);
Christopher Ferris804cebe2019-06-20 08:50:23 -0700346#else
347 GTEST_SKIP() << "valloc not supported.";
348#endif
Christopher Ferrisa4037802014-06-09 19:14:11 -0700349}
350
351TEST(malloc, valloc_overflow) {
Christopher Ferris804cebe2019-06-20 08:50:23 -0700352#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
Yi Kong32bc0fc2018-08-02 17:31:13 -0700353 ASSERT_EQ(nullptr, valloc(SIZE_MAX));
Christopher Ferris804cebe2019-06-20 08:50:23 -0700354#else
355 GTEST_SKIP() << "valloc not supported.";
Dan Alberte5fdaa42014-06-14 01:04:31 +0000356#endif
Christopher Ferris804cebe2019-06-20 08:50:23 -0700357}
Dan Albert4caa1f02014-08-20 09:16:57 -0700358
359TEST(malloc, malloc_info) {
360#ifdef __BIONIC__
Evgenii Stepanov8de6b462019-03-22 13:22:28 -0700361 SKIP_WITH_HWASAN; // hwasan does not implement malloc_info
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800362
363 TemporaryFile tf;
364 ASSERT_TRUE(tf.fd != -1);
365 FILE* fp = fdopen(tf.fd, "w+");
366 tf.release();
367 ASSERT_TRUE(fp != nullptr);
368 ASSERT_EQ(0, malloc_info(0, fp));
369 ASSERT_EQ(0, fclose(fp));
370
371 std::string contents;
372 ASSERT_TRUE(android::base::ReadFileToString(tf.path, &contents));
Dan Albert4caa1f02014-08-20 09:16:57 -0700373
374 tinyxml2::XMLDocument doc;
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800375 ASSERT_EQ(tinyxml2::XML_SUCCESS, doc.Parse(contents.c_str()));
Dan Albert4caa1f02014-08-20 09:16:57 -0700376
377 auto root = doc.FirstChildElement();
378 ASSERT_NE(nullptr, root);
379 ASSERT_STREQ("malloc", root->Name());
Christopher Ferris85169652019-10-09 18:41:55 -0700380 std::string version(root->Attribute("version"));
381 if (version == "jemalloc-1") {
Christopher Ferris6c619a02019-03-01 17:59:51 -0800382 // Verify jemalloc version of this data.
383 ASSERT_STREQ("jemalloc-1", root->Attribute("version"));
Dan Albert4caa1f02014-08-20 09:16:57 -0700384
Christopher Ferris6c619a02019-03-01 17:59:51 -0800385 auto arena = root->FirstChildElement();
386 for (; arena != nullptr; arena = arena->NextSiblingElement()) {
387 int val;
Dan Albert4caa1f02014-08-20 09:16:57 -0700388
Christopher Ferris6c619a02019-03-01 17:59:51 -0800389 ASSERT_STREQ("heap", arena->Name());
390 ASSERT_EQ(tinyxml2::XML_SUCCESS, arena->QueryIntAttribute("nr", &val));
391 ASSERT_EQ(tinyxml2::XML_SUCCESS,
392 arena->FirstChildElement("allocated-large")->QueryIntText(&val));
393 ASSERT_EQ(tinyxml2::XML_SUCCESS,
394 arena->FirstChildElement("allocated-huge")->QueryIntText(&val));
395 ASSERT_EQ(tinyxml2::XML_SUCCESS,
396 arena->FirstChildElement("allocated-bins")->QueryIntText(&val));
397 ASSERT_EQ(tinyxml2::XML_SUCCESS,
398 arena->FirstChildElement("bins-total")->QueryIntText(&val));
Dan Albert4caa1f02014-08-20 09:16:57 -0700399
Christopher Ferris6c619a02019-03-01 17:59:51 -0800400 auto bin = arena->FirstChildElement("bin");
401 for (; bin != nullptr; bin = bin ->NextSiblingElement()) {
402 if (strcmp(bin->Name(), "bin") == 0) {
403 ASSERT_EQ(tinyxml2::XML_SUCCESS, bin->QueryIntAttribute("nr", &val));
404 ASSERT_EQ(tinyxml2::XML_SUCCESS,
405 bin->FirstChildElement("allocated")->QueryIntText(&val));
406 ASSERT_EQ(tinyxml2::XML_SUCCESS,
407 bin->FirstChildElement("nmalloc")->QueryIntText(&val));
408 ASSERT_EQ(tinyxml2::XML_SUCCESS,
409 bin->FirstChildElement("ndalloc")->QueryIntText(&val));
410 }
Dan Albert4caa1f02014-08-20 09:16:57 -0700411 }
412 }
Christopher Ferris6c619a02019-03-01 17:59:51 -0800413 } else {
Christopher Ferris85169652019-10-09 18:41:55 -0700414 // Do not verify output for scudo or debug malloc.
415 ASSERT_TRUE(version == "scudo-1" || version == "debug-malloc-1")
416 << "Unknown version: " << version;
Dan Albert4caa1f02014-08-20 09:16:57 -0700417 }
418#endif
419}
Christopher Ferrisad33ebe2015-12-16 12:07:25 -0800420
Christopher Ferrisdb9706a2019-05-02 18:33:11 -0700421TEST(malloc, malloc_info_matches_mallinfo) {
422#ifdef __BIONIC__
423 SKIP_WITH_HWASAN; // hwasan does not implement malloc_info
424
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800425 TemporaryFile tf;
426 ASSERT_TRUE(tf.fd != -1);
427 FILE* fp = fdopen(tf.fd, "w+");
428 tf.release();
429 ASSERT_TRUE(fp != nullptr);
Christopher Ferrisdb9706a2019-05-02 18:33:11 -0700430 size_t mallinfo_before_allocated_bytes = mallinfo().uordblks;
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800431 ASSERT_EQ(0, malloc_info(0, fp));
Christopher Ferrisdb9706a2019-05-02 18:33:11 -0700432 size_t mallinfo_after_allocated_bytes = mallinfo().uordblks;
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800433 ASSERT_EQ(0, fclose(fp));
434
435 std::string contents;
436 ASSERT_TRUE(android::base::ReadFileToString(tf.path, &contents));
Christopher Ferrisdb9706a2019-05-02 18:33:11 -0700437
438 tinyxml2::XMLDocument doc;
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800439 ASSERT_EQ(tinyxml2::XML_SUCCESS, doc.Parse(contents.c_str()));
Christopher Ferrisdb9706a2019-05-02 18:33:11 -0700440
441 size_t total_allocated_bytes = 0;
442 auto root = doc.FirstChildElement();
443 ASSERT_NE(nullptr, root);
444 ASSERT_STREQ("malloc", root->Name());
Christopher Ferris85169652019-10-09 18:41:55 -0700445 std::string version(root->Attribute("version"));
446 if (version == "jemalloc-1") {
Christopher Ferrisdb9706a2019-05-02 18:33:11 -0700447 // Verify jemalloc version of this data.
448 ASSERT_STREQ("jemalloc-1", root->Attribute("version"));
449
450 auto arena = root->FirstChildElement();
451 for (; arena != nullptr; arena = arena->NextSiblingElement()) {
452 int val;
453
454 ASSERT_STREQ("heap", arena->Name());
455 ASSERT_EQ(tinyxml2::XML_SUCCESS, arena->QueryIntAttribute("nr", &val));
456 ASSERT_EQ(tinyxml2::XML_SUCCESS,
457 arena->FirstChildElement("allocated-large")->QueryIntText(&val));
458 total_allocated_bytes += val;
459 ASSERT_EQ(tinyxml2::XML_SUCCESS,
460 arena->FirstChildElement("allocated-huge")->QueryIntText(&val));
461 total_allocated_bytes += val;
462 ASSERT_EQ(tinyxml2::XML_SUCCESS,
463 arena->FirstChildElement("allocated-bins")->QueryIntText(&val));
464 total_allocated_bytes += val;
465 ASSERT_EQ(tinyxml2::XML_SUCCESS,
466 arena->FirstChildElement("bins-total")->QueryIntText(&val));
467 }
468 // The total needs to be between the mallinfo call before and after
469 // since malloc_info allocates some memory.
470 EXPECT_LE(mallinfo_before_allocated_bytes, total_allocated_bytes);
471 EXPECT_GE(mallinfo_after_allocated_bytes, total_allocated_bytes);
472 } else {
Christopher Ferris85169652019-10-09 18:41:55 -0700473 // Do not verify output for scudo or debug malloc.
474 ASSERT_TRUE(version == "scudo-1" || version == "debug-malloc-1")
475 << "Unknown version: " << version;
Christopher Ferrisdb9706a2019-05-02 18:33:11 -0700476 }
477#endif
478}
479
Christopher Ferrisad33ebe2015-12-16 12:07:25 -0800480TEST(malloc, calloc_usable_size) {
481 for (size_t size = 1; size <= 2048; size++) {
482 void* pointer = malloc(size);
483 ASSERT_TRUE(pointer != nullptr);
484 memset(pointer, 0xeb, malloc_usable_size(pointer));
485 free(pointer);
486
487 // We should get a previous pointer that has been set to non-zero.
488 // If calloc does not zero out all of the data, this will fail.
489 uint8_t* zero_mem = reinterpret_cast<uint8_t*>(calloc(1, size));
490 ASSERT_TRUE(pointer != nullptr);
491 size_t usable_size = malloc_usable_size(zero_mem);
492 for (size_t i = 0; i < usable_size; i++) {
493 ASSERT_EQ(0, zero_mem[i]) << "Failed at allocation size " << size << " at byte " << i;
494 }
495 free(zero_mem);
496 }
497}
Elliott Hughes884f76e2016-02-10 20:43:22 -0800498
499TEST(malloc, malloc_0) {
500 void* p = malloc(0);
501 ASSERT_TRUE(p != nullptr);
502 free(p);
503}
504
505TEST(malloc, calloc_0_0) {
506 void* p = calloc(0, 0);
507 ASSERT_TRUE(p != nullptr);
508 free(p);
509}
510
511TEST(malloc, calloc_0_1) {
512 void* p = calloc(0, 1);
513 ASSERT_TRUE(p != nullptr);
514 free(p);
515}
516
517TEST(malloc, calloc_1_0) {
518 void* p = calloc(1, 0);
519 ASSERT_TRUE(p != nullptr);
520 free(p);
521}
522
523TEST(malloc, realloc_nullptr_0) {
524 // realloc(nullptr, size) is actually malloc(size).
525 void* p = realloc(nullptr, 0);
526 ASSERT_TRUE(p != nullptr);
527 free(p);
528}
529
530TEST(malloc, realloc_0) {
531 void* p = malloc(1024);
532 ASSERT_TRUE(p != nullptr);
533 // realloc(p, 0) is actually free(p).
534 void* p2 = realloc(p, 0);
535 ASSERT_TRUE(p2 == nullptr);
536}
Christopher Ferris72df6702016-02-11 15:51:31 -0800537
538constexpr size_t MAX_LOOPS = 200;
539
540// Make sure that memory returned by malloc is aligned to allow these data types.
541TEST(malloc, verify_alignment) {
542 uint32_t** values_32 = new uint32_t*[MAX_LOOPS];
543 uint64_t** values_64 = new uint64_t*[MAX_LOOPS];
544 long double** values_ldouble = new long double*[MAX_LOOPS];
545 // Use filler to attempt to force the allocator to get potentially bad alignments.
546 void** filler = new void*[MAX_LOOPS];
547
548 for (size_t i = 0; i < MAX_LOOPS; i++) {
549 // Check uint32_t pointers.
550 filler[i] = malloc(1);
551 ASSERT_TRUE(filler[i] != nullptr);
552
553 values_32[i] = reinterpret_cast<uint32_t*>(malloc(sizeof(uint32_t)));
554 ASSERT_TRUE(values_32[i] != nullptr);
555 *values_32[i] = i;
556 ASSERT_EQ(*values_32[i], i);
557 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(values_32[i]) & (sizeof(uint32_t) - 1));
558
559 free(filler[i]);
560 }
561
562 for (size_t i = 0; i < MAX_LOOPS; i++) {
563 // Check uint64_t pointers.
564 filler[i] = malloc(1);
565 ASSERT_TRUE(filler[i] != nullptr);
566
567 values_64[i] = reinterpret_cast<uint64_t*>(malloc(sizeof(uint64_t)));
568 ASSERT_TRUE(values_64[i] != nullptr);
569 *values_64[i] = 0x1000 + i;
570 ASSERT_EQ(*values_64[i], 0x1000 + i);
571 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(values_64[i]) & (sizeof(uint64_t) - 1));
572
573 free(filler[i]);
574 }
575
576 for (size_t i = 0; i < MAX_LOOPS; i++) {
577 // Check long double pointers.
578 filler[i] = malloc(1);
579 ASSERT_TRUE(filler[i] != nullptr);
580
581 values_ldouble[i] = reinterpret_cast<long double*>(malloc(sizeof(long double)));
582 ASSERT_TRUE(values_ldouble[i] != nullptr);
583 *values_ldouble[i] = 5.5 + i;
584 ASSERT_DOUBLE_EQ(*values_ldouble[i], 5.5 + i);
585 // 32 bit glibc has a long double size of 12 bytes, so hardcode the
586 // required alignment to 0x7.
587#if !defined(__BIONIC__) && !defined(__LP64__)
588 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(values_ldouble[i]) & 0x7);
589#else
590 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(values_ldouble[i]) & (sizeof(long double) - 1));
591#endif
592
593 free(filler[i]);
594 }
595
596 for (size_t i = 0; i < MAX_LOOPS; i++) {
597 free(values_32[i]);
598 free(values_64[i]);
599 free(values_ldouble[i]);
600 }
601
602 delete[] filler;
603 delete[] values_32;
604 delete[] values_64;
605 delete[] values_ldouble;
606}
Christopher Ferrisa1c0d2f2017-05-15 15:50:19 -0700607
608TEST(malloc, mallopt_smoke) {
609 errno = 0;
610 ASSERT_EQ(0, mallopt(-1000, 1));
611 // mallopt doesn't set errno.
612 ASSERT_EQ(0, errno);
613}
Elliott Hughesb1770852018-09-18 12:52:42 -0700614
Christopher Ferrisaf1b8dd2018-11-07 15:28:16 -0800615TEST(malloc, mallopt_decay) {
616#if defined(__BIONIC__)
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800617 SKIP_WITH_HWASAN << "hwasan does not implement mallopt";
Christopher Ferrisaf1b8dd2018-11-07 15:28:16 -0800618 errno = 0;
619 ASSERT_EQ(1, mallopt(M_DECAY_TIME, 1));
620 ASSERT_EQ(1, mallopt(M_DECAY_TIME, 0));
621 ASSERT_EQ(1, mallopt(M_DECAY_TIME, 1));
622 ASSERT_EQ(1, mallopt(M_DECAY_TIME, 0));
623#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800624 GTEST_SKIP() << "bionic-only test";
Christopher Ferrisaf1b8dd2018-11-07 15:28:16 -0800625#endif
626}
627
628TEST(malloc, mallopt_purge) {
629#if defined(__BIONIC__)
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800630 SKIP_WITH_HWASAN << "hwasan does not implement mallopt";
Christopher Ferrisaf1b8dd2018-11-07 15:28:16 -0800631 errno = 0;
632 ASSERT_EQ(1, mallopt(M_PURGE, 0));
633#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800634 GTEST_SKIP() << "bionic-only test";
Christopher Ferrisaf1b8dd2018-11-07 15:28:16 -0800635#endif
636}
637
Elliott Hughesb1770852018-09-18 12:52:42 -0700638TEST(malloc, reallocarray_overflow) {
639#if HAVE_REALLOCARRAY
640 // Values that cause overflow to a result small enough (8 on LP64) that malloc would "succeed".
641 size_t a = static_cast<size_t>(INTPTR_MIN + 4);
642 size_t b = 2;
643
644 errno = 0;
645 ASSERT_TRUE(reallocarray(nullptr, a, b) == nullptr);
646 ASSERT_EQ(ENOMEM, errno);
647
648 errno = 0;
649 ASSERT_TRUE(reallocarray(nullptr, b, a) == nullptr);
650 ASSERT_EQ(ENOMEM, errno);
651#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800652 GTEST_SKIP() << "reallocarray not available";
Elliott Hughesb1770852018-09-18 12:52:42 -0700653#endif
654}
655
656TEST(malloc, reallocarray) {
657#if HAVE_REALLOCARRAY
658 void* p = reallocarray(nullptr, 2, 32);
659 ASSERT_TRUE(p != nullptr);
660 ASSERT_GE(malloc_usable_size(p), 64U);
661#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800662 GTEST_SKIP() << "reallocarray not available";
Elliott Hughesb1770852018-09-18 12:52:42 -0700663#endif
664}
Christopher Ferris09a19aa2018-11-16 13:28:56 -0800665
666TEST(malloc, mallinfo) {
667#if defined(__BIONIC__)
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800668 SKIP_WITH_HWASAN << "hwasan does not implement mallinfo";
Christopher Ferris09a19aa2018-11-16 13:28:56 -0800669 static size_t sizes[] = {
670 8, 32, 128, 4096, 32768, 131072, 1024000, 10240000, 20480000, 300000000
671 };
672
673 constexpr static size_t kMaxAllocs = 50;
674
675 for (size_t size : sizes) {
676 // If some of these allocations are stuck in a thread cache, then keep
677 // looping until we make an allocation that changes the total size of the
678 // memory allocated.
679 // jemalloc implementations counts the thread cache allocations against
680 // total memory allocated.
681 void* ptrs[kMaxAllocs] = {};
682 bool pass = false;
683 for (size_t i = 0; i < kMaxAllocs; i++) {
684 size_t allocated = mallinfo().uordblks;
685 ptrs[i] = malloc(size);
686 ASSERT_TRUE(ptrs[i] != nullptr);
687 size_t new_allocated = mallinfo().uordblks;
688 if (allocated != new_allocated) {
689 size_t usable_size = malloc_usable_size(ptrs[i]);
Christopher Ferris4e562282019-02-07 14:20:03 -0800690 // Only check if the total got bigger by at least allocation size.
691 // Sometimes the mallinfo numbers can go backwards due to compaction
692 // and/or freeing of cached data.
693 if (new_allocated >= allocated + usable_size) {
694 pass = true;
695 break;
696 }
Christopher Ferris09a19aa2018-11-16 13:28:56 -0800697 }
698 }
699 for (void* ptr : ptrs) {
700 free(ptr);
701 }
702 ASSERT_TRUE(pass)
703 << "For size " << size << " allocated bytes did not increase after "
704 << kMaxAllocs << " allocations.";
705 }
706#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800707 GTEST_SKIP() << "glibc is broken";
Christopher Ferris09a19aa2018-11-16 13:28:56 -0800708#endif
709}
Ryan Savitskiecc37e32018-12-14 15:57:21 +0000710
711TEST(android_mallopt, error_on_unexpected_option) {
712#if defined(__BIONIC__)
713 const int unrecognized_option = -1;
714 errno = 0;
715 EXPECT_EQ(false, android_mallopt(unrecognized_option, nullptr, 0));
716 EXPECT_EQ(ENOTSUP, errno);
717#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800718 GTEST_SKIP() << "bionic-only test";
Ryan Savitskiecc37e32018-12-14 15:57:21 +0000719#endif
720}
721
Christopher Ferrise4cdbc42019-02-08 17:30:58 -0800722bool IsDynamic() {
723#if defined(__LP64__)
724 Elf64_Ehdr ehdr;
725#else
726 Elf32_Ehdr ehdr;
727#endif
728 std::string path(android::base::GetExecutablePath());
729
730 int fd = open(path.c_str(), O_RDONLY | O_CLOEXEC);
731 if (fd == -1) {
732 // Assume dynamic on error.
733 return true;
734 }
735 bool read_completed = android::base::ReadFully(fd, &ehdr, sizeof(ehdr));
736 close(fd);
737 // Assume dynamic in error cases.
738 return !read_completed || ehdr.e_type == ET_DYN;
739}
740
Ryan Savitskiecc37e32018-12-14 15:57:21 +0000741TEST(android_mallopt, init_zygote_child_profiling) {
742#if defined(__BIONIC__)
743 // Successful call.
744 errno = 0;
Christopher Ferrise4cdbc42019-02-08 17:30:58 -0800745 if (IsDynamic()) {
746 EXPECT_EQ(true, android_mallopt(M_INIT_ZYGOTE_CHILD_PROFILING, nullptr, 0));
747 EXPECT_EQ(0, errno);
748 } else {
749 // Not supported in static executables.
750 EXPECT_EQ(false, android_mallopt(M_INIT_ZYGOTE_CHILD_PROFILING, nullptr, 0));
751 EXPECT_EQ(ENOTSUP, errno);
752 }
Ryan Savitskiecc37e32018-12-14 15:57:21 +0000753
754 // Unexpected arguments rejected.
755 errno = 0;
756 char unexpected = 0;
757 EXPECT_EQ(false, android_mallopt(M_INIT_ZYGOTE_CHILD_PROFILING, &unexpected, 1));
Christopher Ferrise4cdbc42019-02-08 17:30:58 -0800758 if (IsDynamic()) {
759 EXPECT_EQ(EINVAL, errno);
760 } else {
761 EXPECT_EQ(ENOTSUP, errno);
762 }
Ryan Savitskiecc37e32018-12-14 15:57:21 +0000763#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800764 GTEST_SKIP() << "bionic-only test";
Ryan Savitskiecc37e32018-12-14 15:57:21 +0000765#endif
766}
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -0800767
768#if defined(__BIONIC__)
769template <typename FuncType>
770void CheckAllocationFunction(FuncType func) {
771 // Assumes that no more than 108MB of memory is allocated before this.
772 size_t limit = 128 * 1024 * 1024;
773 ASSERT_TRUE(android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit)));
774 if (!func(20 * 1024 * 1024))
775 exit(1);
776 if (func(128 * 1024 * 1024))
777 exit(1);
778 exit(0);
779}
780#endif
781
782TEST(android_mallopt, set_allocation_limit) {
783#if defined(__BIONIC__)
784 EXPECT_EXIT(CheckAllocationFunction([](size_t bytes) { return calloc(bytes, 1) != nullptr; }),
785 testing::ExitedWithCode(0), "");
786 EXPECT_EXIT(CheckAllocationFunction([](size_t bytes) { return calloc(1, bytes) != nullptr; }),
787 testing::ExitedWithCode(0), "");
788 EXPECT_EXIT(CheckAllocationFunction([](size_t bytes) { return malloc(bytes) != nullptr; }),
789 testing::ExitedWithCode(0), "");
790 EXPECT_EXIT(CheckAllocationFunction(
791 [](size_t bytes) { return memalign(sizeof(void*), bytes) != nullptr; }),
792 testing::ExitedWithCode(0), "");
793 EXPECT_EXIT(CheckAllocationFunction([](size_t bytes) {
794 void* ptr;
795 return posix_memalign(&ptr, sizeof(void *), bytes) == 0;
796 }),
797 testing::ExitedWithCode(0), "");
798 EXPECT_EXIT(CheckAllocationFunction(
799 [](size_t bytes) { return aligned_alloc(sizeof(void*), bytes) != nullptr; }),
800 testing::ExitedWithCode(0), "");
801 EXPECT_EXIT(CheckAllocationFunction([](size_t bytes) {
802 void* p = malloc(1024 * 1024);
803 return realloc(p, bytes) != nullptr;
804 }),
805 testing::ExitedWithCode(0), "");
806#if !defined(__LP64__)
807 EXPECT_EXIT(CheckAllocationFunction([](size_t bytes) { return pvalloc(bytes) != nullptr; }),
808 testing::ExitedWithCode(0), "");
809 EXPECT_EXIT(CheckAllocationFunction([](size_t bytes) { return valloc(bytes) != nullptr; }),
810 testing::ExitedWithCode(0), "");
811#endif
812#else
Elliott Hughes10907202019-03-27 08:51:02 -0700813 GTEST_SKIP() << "bionic extension";
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -0800814#endif
815}
816
817TEST(android_mallopt, set_allocation_limit_multiple) {
818#if defined(__BIONIC__)
819 // Only the first set should work.
820 size_t limit = 256 * 1024 * 1024;
821 ASSERT_TRUE(android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit)));
822 limit = 32 * 1024 * 1024;
823 ASSERT_FALSE(android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit)));
824#else
Elliott Hughes10907202019-03-27 08:51:02 -0700825 GTEST_SKIP() << "bionic extension";
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -0800826#endif
827}
828
829#if defined(__BIONIC__)
830static constexpr size_t kAllocationSize = 8 * 1024 * 1024;
831
832static size_t GetMaxAllocations() {
833 size_t max_pointers = 0;
834 void* ptrs[20];
835 for (size_t i = 0; i < sizeof(ptrs) / sizeof(void*); i++) {
836 ptrs[i] = malloc(kAllocationSize);
837 if (ptrs[i] == nullptr) {
838 max_pointers = i;
839 break;
840 }
841 }
842 for (size_t i = 0; i < max_pointers; i++) {
843 free(ptrs[i]);
844 }
845 return max_pointers;
846}
847
848static void VerifyMaxPointers(size_t max_pointers) {
849 // Now verify that we can allocate the same number as before.
850 void* ptrs[20];
851 for (size_t i = 0; i < max_pointers; i++) {
852 ptrs[i] = malloc(kAllocationSize);
853 ASSERT_TRUE(ptrs[i] != nullptr) << "Failed to allocate on iteration " << i;
854 }
855
856 // Make sure the next allocation still fails.
857 ASSERT_TRUE(malloc(kAllocationSize) == nullptr);
858 for (size_t i = 0; i < max_pointers; i++) {
859 free(ptrs[i]);
860 }
861}
862#endif
863
864TEST(android_mallopt, set_allocation_limit_realloc_increase) {
865#if defined(__BIONIC__)
866 size_t limit = 128 * 1024 * 1024;
867 ASSERT_TRUE(android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit)));
868
869 size_t max_pointers = GetMaxAllocations();
870 ASSERT_TRUE(max_pointers != 0) << "Limit never reached.";
871
872 void* memory = malloc(10 * 1024 * 1024);
873 ASSERT_TRUE(memory != nullptr);
874
875 // Increase size.
876 memory = realloc(memory, 20 * 1024 * 1024);
877 ASSERT_TRUE(memory != nullptr);
878 memory = realloc(memory, 40 * 1024 * 1024);
879 ASSERT_TRUE(memory != nullptr);
880 memory = realloc(memory, 60 * 1024 * 1024);
881 ASSERT_TRUE(memory != nullptr);
882 memory = realloc(memory, 80 * 1024 * 1024);
883 ASSERT_TRUE(memory != nullptr);
884 // Now push past limit.
885 memory = realloc(memory, 130 * 1024 * 1024);
886 ASSERT_TRUE(memory == nullptr);
887
888 VerifyMaxPointers(max_pointers);
889#else
Elliott Hughes10907202019-03-27 08:51:02 -0700890 GTEST_SKIP() << "bionic extension";
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -0800891#endif
892}
893
894TEST(android_mallopt, set_allocation_limit_realloc_decrease) {
895#if defined(__BIONIC__)
896 size_t limit = 100 * 1024 * 1024;
897 ASSERT_TRUE(android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit)));
898
899 size_t max_pointers = GetMaxAllocations();
900 ASSERT_TRUE(max_pointers != 0) << "Limit never reached.";
901
902 void* memory = malloc(80 * 1024 * 1024);
903 ASSERT_TRUE(memory != nullptr);
904
905 // Decrease size.
906 memory = realloc(memory, 60 * 1024 * 1024);
907 ASSERT_TRUE(memory != nullptr);
908 memory = realloc(memory, 40 * 1024 * 1024);
909 ASSERT_TRUE(memory != nullptr);
910 memory = realloc(memory, 20 * 1024 * 1024);
911 ASSERT_TRUE(memory != nullptr);
912 memory = realloc(memory, 10 * 1024 * 1024);
913 ASSERT_TRUE(memory != nullptr);
914 free(memory);
915
916 VerifyMaxPointers(max_pointers);
917#else
Elliott Hughes10907202019-03-27 08:51:02 -0700918 GTEST_SKIP() << "bionic extension";
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -0800919#endif
920}
921
922TEST(android_mallopt, set_allocation_limit_realloc_free) {
923#if defined(__BIONIC__)
924 size_t limit = 100 * 1024 * 1024;
925 ASSERT_TRUE(android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit)));
926
927 size_t max_pointers = GetMaxAllocations();
928 ASSERT_TRUE(max_pointers != 0) << "Limit never reached.";
929
930 void* memory = malloc(60 * 1024 * 1024);
931 ASSERT_TRUE(memory != nullptr);
932
933 memory = realloc(memory, 0);
934 ASSERT_TRUE(memory == nullptr);
935
936 VerifyMaxPointers(max_pointers);
937#else
Elliott Hughes10907202019-03-27 08:51:02 -0700938 GTEST_SKIP() << "bionic extension";
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -0800939#endif
940}
941
942#if defined(__BIONIC__)
943static void* SetAllocationLimit(void* data) {
944 std::atomic_bool* go = reinterpret_cast<std::atomic_bool*>(data);
945 while (!go->load()) {
946 }
947 size_t limit = 500 * 1024 * 1024;
948 if (android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit))) {
949 return reinterpret_cast<void*>(-1);
950 }
951 return nullptr;
952}
953
954static void SetAllocationLimitMultipleThreads() {
955 std::atomic_bool go;
956 go = false;
957
958 static constexpr size_t kNumThreads = 4;
959 pthread_t threads[kNumThreads];
960 for (size_t i = 0; i < kNumThreads; i++) {
961 ASSERT_EQ(0, pthread_create(&threads[i], nullptr, SetAllocationLimit, &go));
962 }
963
964 // Let them go all at once.
965 go = true;
Ryan Savitski175c8862020-01-02 19:54:57 +0000966 // Send hardcoded signal (BIONIC_SIGNAL_PROFILER with value 0) to trigger
967 // heapprofd handler.
968 union sigval signal_value;
969 signal_value.sival_int = 0;
970 ASSERT_EQ(0, sigqueue(getpid(), __SIGRTMIN + 4, signal_value));
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -0800971
972 size_t num_successful = 0;
973 for (size_t i = 0; i < kNumThreads; i++) {
974 void* result;
975 ASSERT_EQ(0, pthread_join(threads[i], &result));
976 if (result != nullptr) {
977 num_successful++;
978 }
979 }
980 ASSERT_EQ(1U, num_successful);
981 exit(0);
982}
983#endif
984
985TEST(android_mallopt, set_allocation_limit_multiple_threads) {
986#if defined(__BIONIC__)
987 if (IsDynamic()) {
988 ASSERT_TRUE(android_mallopt(M_INIT_ZYGOTE_CHILD_PROFILING, nullptr, 0));
989 }
990
991 // Run this a number of times as a stress test.
992 for (size_t i = 0; i < 100; i++) {
993 // Not using ASSERT_EXIT because errors messages are not displayed.
994 pid_t pid;
995 if ((pid = fork()) == 0) {
996 ASSERT_NO_FATAL_FAILURE(SetAllocationLimitMultipleThreads());
997 }
998 ASSERT_NE(-1, pid);
999 int status;
1000 ASSERT_EQ(pid, wait(&status));
1001 ASSERT_EQ(0, WEXITSTATUS(status));
1002 }
1003#else
Elliott Hughes10907202019-03-27 08:51:02 -07001004 GTEST_SKIP() << "bionic extension";
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -08001005#endif
1006}