blob: 8272d3920df1dc3a1c86bfe6c2f43b89357f57e1 [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>
Peter Collingbourne5d3aa862020-09-11 15:05:17 -070023#include <semaphore.h>
Ryan Savitski175c8862020-01-02 19:54:57 +000024#include <signal.h>
Christopher Ferrisa4037802014-06-09 19:14:11 -070025#include <stdint.h>
Christopher Ferris6c619a02019-03-01 17:59:51 -080026#include <stdio.h>
Christopher Ferris885f3b92013-05-21 17:48:01 -070027#include <stdlib.h>
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -080028#include <string.h>
Peter Collingbourne45819dd2020-01-09 11:00:43 -080029#include <sys/auxv.h>
Colin Cross4c5595c2021-08-16 15:51:59 -070030#include <sys/cdefs.h>
Peter Collingbourne45819dd2020-01-09 11:00:43 -080031#include <sys/prctl.h>
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -080032#include <sys/types.h>
33#include <sys/wait.h>
Christopher Ferrisa4037802014-06-09 19:14:11 -070034#include <unistd.h>
Christopher Ferris885f3b92013-05-21 17:48:01 -070035
Mitch Phillips9cad8422021-01-20 16:03:27 -080036#include <algorithm>
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -080037#include <atomic>
Christopher Ferrisf32494c2020-01-08 14:19:10 -080038#include <thread>
Mitch Phillips9cad8422021-01-20 16:03:27 -080039#include <vector>
Christopher Ferrisf32494c2020-01-08 14:19:10 -080040
Dan Albert4caa1f02014-08-20 09:16:57 -070041#include <tinyxml2.h>
42
Christopher Ferrise4cdbc42019-02-08 17:30:58 -080043#include <android-base/file.h>
44
Evgenii Stepanovacd6f4f2018-11-06 16:48:27 -080045#include "utils.h"
Dan Alberte5fdaa42014-06-14 01:04:31 +000046
Elliott Hughesb1770852018-09-18 12:52:42 -070047#if defined(__BIONIC__)
Christopher Ferrisb874c332020-01-21 16:39:05 -080048
Peter Collingbourne45819dd2020-01-09 11:00:43 -080049#include "SignalUtils.h"
Peter Collingbourne2659d7b2021-03-05 13:31:41 -080050#include "dlext_private.h"
Peter Collingbourne45819dd2020-01-09 11:00:43 -080051
Christopher Ferrisb874c332020-01-21 16:39:05 -080052#include "platform/bionic/malloc.h"
Peter Collingbourne5d3aa862020-09-11 15:05:17 -070053#include "platform/bionic/mte.h"
Christopher Ferrisb874c332020-01-21 16:39:05 -080054#include "platform/bionic/reserved_signals.h"
55#include "private/bionic_config.h"
56
Elliott Hughesb1770852018-09-18 12:52:42 -070057#define HAVE_REALLOCARRAY 1
Christopher Ferrisb874c332020-01-21 16:39:05 -080058
Colin Cross7da20342021-07-28 11:18:11 -070059#elif defined(__GLIBC__)
Christopher Ferrisb874c332020-01-21 16:39:05 -080060
Elliott Hughesb1770852018-09-18 12:52:42 -070061#define HAVE_REALLOCARRAY __GLIBC_PREREQ(2, 26)
Christopher Ferrisb874c332020-01-21 16:39:05 -080062
Colin Cross4c5595c2021-08-16 15:51:59 -070063#elif defined(ANDROID_HOST_MUSL)
Colin Cross7da20342021-07-28 11:18:11 -070064
65#define HAVE_REALLOCARRAY 1
66
Elliott Hughesb1770852018-09-18 12:52:42 -070067#endif
68
Christopher Ferris885f3b92013-05-21 17:48:01 -070069TEST(malloc, malloc_std) {
70 // Simple malloc test.
71 void *ptr = malloc(100);
Yi Kong32bc0fc2018-08-02 17:31:13 -070072 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -070073 ASSERT_LE(100U, malloc_usable_size(ptr));
Christopher Ferris885f3b92013-05-21 17:48:01 -070074 free(ptr);
75}
76
Christopher Ferrisa4037802014-06-09 19:14:11 -070077TEST(malloc, malloc_overflow) {
Evgenii Stepanovacd6f4f2018-11-06 16:48:27 -080078 SKIP_WITH_HWASAN;
Christopher Ferrisa4037802014-06-09 19:14:11 -070079 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -070080 ASSERT_EQ(nullptr, malloc(SIZE_MAX));
Christopher Ferrisa4037802014-06-09 19:14:11 -070081 ASSERT_EQ(ENOMEM, errno);
82}
83
Christopher Ferris885f3b92013-05-21 17:48:01 -070084TEST(malloc, calloc_std) {
85 // Simple calloc test.
86 size_t alloc_len = 100;
87 char *ptr = (char *)calloc(1, alloc_len);
Yi Kong32bc0fc2018-08-02 17:31:13 -070088 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -070089 ASSERT_LE(alloc_len, malloc_usable_size(ptr));
90 for (size_t i = 0; i < alloc_len; i++) {
91 ASSERT_EQ(0, ptr[i]);
92 }
Christopher Ferris885f3b92013-05-21 17:48:01 -070093 free(ptr);
94}
95
Peter Collingbourne978eb162020-09-21 15:26:02 -070096TEST(malloc, calloc_mem_init_disabled) {
97#if defined(__BIONIC__)
98 // calloc should still zero memory if mem-init is disabled.
99 // With jemalloc the mallopts will fail but that shouldn't affect the
100 // execution of the test.
101 mallopt(M_THREAD_DISABLE_MEM_INIT, 1);
102 size_t alloc_len = 100;
103 char *ptr = reinterpret_cast<char*>(calloc(1, alloc_len));
104 for (size_t i = 0; i < alloc_len; i++) {
105 ASSERT_EQ(0, ptr[i]);
106 }
107 free(ptr);
108 mallopt(M_THREAD_DISABLE_MEM_INIT, 0);
109#else
110 GTEST_SKIP() << "bionic-only test";
111#endif
112}
113
Christopher Ferrisa4037802014-06-09 19:14:11 -0700114TEST(malloc, calloc_illegal) {
Evgenii Stepanovacd6f4f2018-11-06 16:48:27 -0800115 SKIP_WITH_HWASAN;
Christopher Ferrisa4037802014-06-09 19:14:11 -0700116 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -0700117 ASSERT_EQ(nullptr, calloc(-1, 100));
Christopher Ferrisa4037802014-06-09 19:14:11 -0700118 ASSERT_EQ(ENOMEM, errno);
119}
120
121TEST(malloc, calloc_overflow) {
Evgenii Stepanovacd6f4f2018-11-06 16:48:27 -0800122 SKIP_WITH_HWASAN;
Christopher Ferrisa4037802014-06-09 19:14:11 -0700123 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -0700124 ASSERT_EQ(nullptr, calloc(1, SIZE_MAX));
Christopher Ferrisa4037802014-06-09 19:14:11 -0700125 ASSERT_EQ(ENOMEM, errno);
126 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -0700127 ASSERT_EQ(nullptr, calloc(SIZE_MAX, SIZE_MAX));
Christopher Ferrisa4037802014-06-09 19:14:11 -0700128 ASSERT_EQ(ENOMEM, errno);
129 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -0700130 ASSERT_EQ(nullptr, calloc(2, SIZE_MAX));
Christopher Ferrisa4037802014-06-09 19:14:11 -0700131 ASSERT_EQ(ENOMEM, errno);
132 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -0700133 ASSERT_EQ(nullptr, calloc(SIZE_MAX, 2));
Christopher Ferrisa4037802014-06-09 19:14:11 -0700134 ASSERT_EQ(ENOMEM, errno);
135}
136
Christopher Ferris885f3b92013-05-21 17:48:01 -0700137TEST(malloc, memalign_multiple) {
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800138 SKIP_WITH_HWASAN << "hwasan requires power of 2 alignment";
Christopher Ferris885f3b92013-05-21 17:48:01 -0700139 // Memalign test where the alignment is any value.
140 for (size_t i = 0; i <= 12; i++) {
141 for (size_t alignment = 1 << i; alignment < (1U << (i+1)); alignment++) {
Christopher Ferrisa4037802014-06-09 19:14:11 -0700142 char *ptr = reinterpret_cast<char*>(memalign(alignment, 100));
Yi Kong32bc0fc2018-08-02 17:31:13 -0700143 ASSERT_TRUE(ptr != nullptr) << "Failed at alignment " << alignment;
Christopher Ferrisa4037802014-06-09 19:14:11 -0700144 ASSERT_LE(100U, malloc_usable_size(ptr)) << "Failed at alignment " << alignment;
145 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(ptr) % ((1U << i)))
146 << "Failed at alignment " << alignment;
Christopher Ferris885f3b92013-05-21 17:48:01 -0700147 free(ptr);
148 }
149 }
150}
151
Christopher Ferrisa4037802014-06-09 19:14:11 -0700152TEST(malloc, memalign_overflow) {
Evgenii Stepanovacd6f4f2018-11-06 16:48:27 -0800153 SKIP_WITH_HWASAN;
Yi Kong32bc0fc2018-08-02 17:31:13 -0700154 ASSERT_EQ(nullptr, memalign(4096, SIZE_MAX));
Christopher Ferrisa4037802014-06-09 19:14:11 -0700155}
156
157TEST(malloc, memalign_non_power2) {
Evgenii Stepanovacd6f4f2018-11-06 16:48:27 -0800158 SKIP_WITH_HWASAN;
Christopher Ferrisa4037802014-06-09 19:14:11 -0700159 void* ptr;
160 for (size_t align = 0; align <= 256; align++) {
161 ptr = memalign(align, 1024);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700162 ASSERT_TRUE(ptr != nullptr) << "Failed at align " << align;
Christopher Ferrisa4037802014-06-09 19:14:11 -0700163 free(ptr);
164 }
165}
166
Christopher Ferris885f3b92013-05-21 17:48:01 -0700167TEST(malloc, memalign_realloc) {
168 // Memalign and then realloc the pointer a couple of times.
169 for (size_t alignment = 1; alignment <= 4096; alignment <<= 1) {
170 char *ptr = (char*)memalign(alignment, 100);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700171 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700172 ASSERT_LE(100U, malloc_usable_size(ptr));
173 ASSERT_EQ(0U, (intptr_t)ptr % alignment);
174 memset(ptr, 0x23, 100);
175
176 ptr = (char*)realloc(ptr, 200);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700177 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700178 ASSERT_LE(200U, malloc_usable_size(ptr));
Yi Kong32bc0fc2018-08-02 17:31:13 -0700179 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700180 for (size_t i = 0; i < 100; i++) {
181 ASSERT_EQ(0x23, ptr[i]);
182 }
183 memset(ptr, 0x45, 200);
184
185 ptr = (char*)realloc(ptr, 300);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700186 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700187 ASSERT_LE(300U, malloc_usable_size(ptr));
188 for (size_t i = 0; i < 200; i++) {
189 ASSERT_EQ(0x45, ptr[i]);
190 }
191 memset(ptr, 0x67, 300);
192
193 ptr = (char*)realloc(ptr, 250);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700194 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700195 ASSERT_LE(250U, malloc_usable_size(ptr));
196 for (size_t i = 0; i < 250; i++) {
197 ASSERT_EQ(0x67, ptr[i]);
198 }
Christopher Ferris885f3b92013-05-21 17:48:01 -0700199 free(ptr);
200 }
201}
202
203TEST(malloc, malloc_realloc_larger) {
204 // Realloc to a larger size, malloc is used for the original allocation.
205 char *ptr = (char *)malloc(100);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700206 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700207 ASSERT_LE(100U, malloc_usable_size(ptr));
208 memset(ptr, 67, 100);
209
210 ptr = (char *)realloc(ptr, 200);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700211 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700212 ASSERT_LE(200U, malloc_usable_size(ptr));
213 for (size_t i = 0; i < 100; i++) {
214 ASSERT_EQ(67, ptr[i]);
215 }
Christopher Ferris885f3b92013-05-21 17:48:01 -0700216 free(ptr);
217}
218
219TEST(malloc, malloc_realloc_smaller) {
220 // Realloc to a smaller size, malloc is used for the original allocation.
221 char *ptr = (char *)malloc(200);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700222 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700223 ASSERT_LE(200U, malloc_usable_size(ptr));
224 memset(ptr, 67, 200);
225
226 ptr = (char *)realloc(ptr, 100);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700227 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700228 ASSERT_LE(100U, malloc_usable_size(ptr));
229 for (size_t i = 0; i < 100; i++) {
230 ASSERT_EQ(67, ptr[i]);
231 }
Christopher Ferris885f3b92013-05-21 17:48:01 -0700232 free(ptr);
233}
234
235TEST(malloc, malloc_multiple_realloc) {
236 // Multiple reallocs, malloc is used for the original allocation.
237 char *ptr = (char *)malloc(200);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700238 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700239 ASSERT_LE(200U, malloc_usable_size(ptr));
240 memset(ptr, 0x23, 200);
241
242 ptr = (char *)realloc(ptr, 100);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700243 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700244 ASSERT_LE(100U, malloc_usable_size(ptr));
245 for (size_t i = 0; i < 100; i++) {
246 ASSERT_EQ(0x23, ptr[i]);
247 }
248
249 ptr = (char*)realloc(ptr, 50);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700250 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700251 ASSERT_LE(50U, malloc_usable_size(ptr));
252 for (size_t i = 0; i < 50; i++) {
253 ASSERT_EQ(0x23, ptr[i]);
254 }
255
256 ptr = (char*)realloc(ptr, 150);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700257 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700258 ASSERT_LE(150U, malloc_usable_size(ptr));
259 for (size_t i = 0; i < 50; i++) {
260 ASSERT_EQ(0x23, ptr[i]);
261 }
262 memset(ptr, 0x23, 150);
263
264 ptr = (char*)realloc(ptr, 425);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700265 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700266 ASSERT_LE(425U, malloc_usable_size(ptr));
267 for (size_t i = 0; i < 150; i++) {
268 ASSERT_EQ(0x23, ptr[i]);
269 }
Christopher Ferris885f3b92013-05-21 17:48:01 -0700270 free(ptr);
271}
Christopher Ferrisa4037802014-06-09 19:14:11 -0700272
Christopher Ferris885f3b92013-05-21 17:48:01 -0700273TEST(malloc, calloc_realloc_larger) {
274 // Realloc to a larger size, calloc is used for the original allocation.
275 char *ptr = (char *)calloc(1, 100);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700276 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700277 ASSERT_LE(100U, malloc_usable_size(ptr));
278
279 ptr = (char *)realloc(ptr, 200);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700280 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700281 ASSERT_LE(200U, malloc_usable_size(ptr));
282 for (size_t i = 0; i < 100; i++) {
283 ASSERT_EQ(0, ptr[i]);
284 }
Christopher Ferris885f3b92013-05-21 17:48:01 -0700285 free(ptr);
286}
287
288TEST(malloc, calloc_realloc_smaller) {
289 // Realloc to a smaller size, calloc is used for the original allocation.
290 char *ptr = (char *)calloc(1, 200);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700291 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700292 ASSERT_LE(200U, malloc_usable_size(ptr));
293
294 ptr = (char *)realloc(ptr, 100);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700295 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700296 ASSERT_LE(100U, malloc_usable_size(ptr));
297 for (size_t i = 0; i < 100; i++) {
298 ASSERT_EQ(0, ptr[i]);
299 }
Christopher Ferris885f3b92013-05-21 17:48:01 -0700300 free(ptr);
301}
302
303TEST(malloc, calloc_multiple_realloc) {
304 // Multiple reallocs, calloc is used for the original allocation.
305 char *ptr = (char *)calloc(1, 200);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700306 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700307 ASSERT_LE(200U, malloc_usable_size(ptr));
308
309 ptr = (char *)realloc(ptr, 100);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700310 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700311 ASSERT_LE(100U, malloc_usable_size(ptr));
312 for (size_t i = 0; i < 100; i++) {
313 ASSERT_EQ(0, ptr[i]);
314 }
315
316 ptr = (char*)realloc(ptr, 50);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700317 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700318 ASSERT_LE(50U, malloc_usable_size(ptr));
319 for (size_t i = 0; i < 50; i++) {
320 ASSERT_EQ(0, ptr[i]);
321 }
322
323 ptr = (char*)realloc(ptr, 150);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700324 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700325 ASSERT_LE(150U, malloc_usable_size(ptr));
326 for (size_t i = 0; i < 50; i++) {
327 ASSERT_EQ(0, ptr[i]);
328 }
329 memset(ptr, 0, 150);
330
331 ptr = (char*)realloc(ptr, 425);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700332 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700333 ASSERT_LE(425U, malloc_usable_size(ptr));
334 for (size_t i = 0; i < 150; i++) {
335 ASSERT_EQ(0, ptr[i]);
336 }
Christopher Ferris885f3b92013-05-21 17:48:01 -0700337 free(ptr);
338}
Christopher Ferris72bbd422014-05-08 11:14:03 -0700339
Christopher Ferrisa4037802014-06-09 19:14:11 -0700340TEST(malloc, realloc_overflow) {
Evgenii Stepanovacd6f4f2018-11-06 16:48:27 -0800341 SKIP_WITH_HWASAN;
Christopher Ferrisa4037802014-06-09 19:14:11 -0700342 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -0700343 ASSERT_EQ(nullptr, realloc(nullptr, SIZE_MAX));
Christopher Ferrisa4037802014-06-09 19:14:11 -0700344 ASSERT_EQ(ENOMEM, errno);
345 void* ptr = malloc(100);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700346 ASSERT_TRUE(ptr != nullptr);
Christopher Ferrisa4037802014-06-09 19:14:11 -0700347 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -0700348 ASSERT_EQ(nullptr, realloc(ptr, SIZE_MAX));
Christopher Ferrisa4037802014-06-09 19:14:11 -0700349 ASSERT_EQ(ENOMEM, errno);
350 free(ptr);
Christopher Ferris72bbd422014-05-08 11:14:03 -0700351}
352
Dan Alberte5fdaa42014-06-14 01:04:31 +0000353#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
354extern "C" void* pvalloc(size_t);
355extern "C" void* valloc(size_t);
Christopher Ferris804cebe2019-06-20 08:50:23 -0700356#endif
Dan Alberte5fdaa42014-06-14 01:04:31 +0000357
Christopher Ferrisa4037802014-06-09 19:14:11 -0700358TEST(malloc, pvalloc_std) {
Christopher Ferris804cebe2019-06-20 08:50:23 -0700359#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
Christopher Ferrisa4037802014-06-09 19:14:11 -0700360 size_t pagesize = sysconf(_SC_PAGESIZE);
361 void* ptr = pvalloc(100);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700362 ASSERT_TRUE(ptr != nullptr);
Christopher Ferrisa4037802014-06-09 19:14:11 -0700363 ASSERT_TRUE((reinterpret_cast<uintptr_t>(ptr) & (pagesize-1)) == 0);
364 ASSERT_LE(pagesize, malloc_usable_size(ptr));
365 free(ptr);
Christopher Ferris804cebe2019-06-20 08:50:23 -0700366#else
367 GTEST_SKIP() << "pvalloc not supported.";
368#endif
Christopher Ferrisa4037802014-06-09 19:14:11 -0700369}
370
371TEST(malloc, pvalloc_overflow) {
Christopher Ferris804cebe2019-06-20 08:50:23 -0700372#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
Yi Kong32bc0fc2018-08-02 17:31:13 -0700373 ASSERT_EQ(nullptr, pvalloc(SIZE_MAX));
Christopher Ferris804cebe2019-06-20 08:50:23 -0700374#else
375 GTEST_SKIP() << "pvalloc not supported.";
376#endif
Christopher Ferrisa4037802014-06-09 19:14:11 -0700377}
378
379TEST(malloc, valloc_std) {
Christopher Ferris804cebe2019-06-20 08:50:23 -0700380#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
Christopher Ferrisa4037802014-06-09 19:14:11 -0700381 size_t pagesize = sysconf(_SC_PAGESIZE);
Christopher Ferrisd5ab0a52019-06-19 12:03:57 -0700382 void* ptr = valloc(100);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700383 ASSERT_TRUE(ptr != nullptr);
Christopher Ferrisa4037802014-06-09 19:14:11 -0700384 ASSERT_TRUE((reinterpret_cast<uintptr_t>(ptr) & (pagesize-1)) == 0);
385 free(ptr);
Christopher Ferris804cebe2019-06-20 08:50:23 -0700386#else
387 GTEST_SKIP() << "valloc not supported.";
388#endif
Christopher Ferrisa4037802014-06-09 19:14:11 -0700389}
390
391TEST(malloc, valloc_overflow) {
Christopher Ferris804cebe2019-06-20 08:50:23 -0700392#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
Yi Kong32bc0fc2018-08-02 17:31:13 -0700393 ASSERT_EQ(nullptr, valloc(SIZE_MAX));
Christopher Ferris804cebe2019-06-20 08:50:23 -0700394#else
395 GTEST_SKIP() << "valloc not supported.";
Dan Alberte5fdaa42014-06-14 01:04:31 +0000396#endif
Christopher Ferris804cebe2019-06-20 08:50:23 -0700397}
Dan Albert4caa1f02014-08-20 09:16:57 -0700398
399TEST(malloc, malloc_info) {
400#ifdef __BIONIC__
Evgenii Stepanov8de6b462019-03-22 13:22:28 -0700401 SKIP_WITH_HWASAN; // hwasan does not implement malloc_info
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800402
403 TemporaryFile tf;
404 ASSERT_TRUE(tf.fd != -1);
405 FILE* fp = fdopen(tf.fd, "w+");
406 tf.release();
407 ASSERT_TRUE(fp != nullptr);
408 ASSERT_EQ(0, malloc_info(0, fp));
409 ASSERT_EQ(0, fclose(fp));
410
411 std::string contents;
412 ASSERT_TRUE(android::base::ReadFileToString(tf.path, &contents));
Dan Albert4caa1f02014-08-20 09:16:57 -0700413
414 tinyxml2::XMLDocument doc;
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800415 ASSERT_EQ(tinyxml2::XML_SUCCESS, doc.Parse(contents.c_str()));
Dan Albert4caa1f02014-08-20 09:16:57 -0700416
417 auto root = doc.FirstChildElement();
418 ASSERT_NE(nullptr, root);
419 ASSERT_STREQ("malloc", root->Name());
Christopher Ferris85169652019-10-09 18:41:55 -0700420 std::string version(root->Attribute("version"));
421 if (version == "jemalloc-1") {
Christopher Ferris6c619a02019-03-01 17:59:51 -0800422 auto arena = root->FirstChildElement();
423 for (; arena != nullptr; arena = arena->NextSiblingElement()) {
424 int val;
Dan Albert4caa1f02014-08-20 09:16:57 -0700425
Christopher Ferris6c619a02019-03-01 17:59:51 -0800426 ASSERT_STREQ("heap", arena->Name());
427 ASSERT_EQ(tinyxml2::XML_SUCCESS, arena->QueryIntAttribute("nr", &val));
428 ASSERT_EQ(tinyxml2::XML_SUCCESS,
429 arena->FirstChildElement("allocated-large")->QueryIntText(&val));
430 ASSERT_EQ(tinyxml2::XML_SUCCESS,
431 arena->FirstChildElement("allocated-huge")->QueryIntText(&val));
432 ASSERT_EQ(tinyxml2::XML_SUCCESS,
433 arena->FirstChildElement("allocated-bins")->QueryIntText(&val));
434 ASSERT_EQ(tinyxml2::XML_SUCCESS,
435 arena->FirstChildElement("bins-total")->QueryIntText(&val));
Dan Albert4caa1f02014-08-20 09:16:57 -0700436
Christopher Ferris6c619a02019-03-01 17:59:51 -0800437 auto bin = arena->FirstChildElement("bin");
438 for (; bin != nullptr; bin = bin ->NextSiblingElement()) {
439 if (strcmp(bin->Name(), "bin") == 0) {
440 ASSERT_EQ(tinyxml2::XML_SUCCESS, bin->QueryIntAttribute("nr", &val));
441 ASSERT_EQ(tinyxml2::XML_SUCCESS,
442 bin->FirstChildElement("allocated")->QueryIntText(&val));
443 ASSERT_EQ(tinyxml2::XML_SUCCESS,
444 bin->FirstChildElement("nmalloc")->QueryIntText(&val));
445 ASSERT_EQ(tinyxml2::XML_SUCCESS,
446 bin->FirstChildElement("ndalloc")->QueryIntText(&val));
447 }
Dan Albert4caa1f02014-08-20 09:16:57 -0700448 }
449 }
Christopher Ferriscce88c02020-02-12 17:41:01 -0800450 } else if (version == "scudo-1") {
451 auto element = root->FirstChildElement();
452 for (; element != nullptr; element = element->NextSiblingElement()) {
453 int val;
454
455 ASSERT_STREQ("alloc", element->Name());
456 ASSERT_EQ(tinyxml2::XML_SUCCESS, element->QueryIntAttribute("size", &val));
457 ASSERT_EQ(tinyxml2::XML_SUCCESS, element->QueryIntAttribute("count", &val));
458 }
Christopher Ferris6c619a02019-03-01 17:59:51 -0800459 } else {
Christopher Ferriscce88c02020-02-12 17:41:01 -0800460 // Do not verify output for debug malloc.
461 ASSERT_TRUE(version == "debug-malloc-1") << "Unknown version: " << version;
Dan Albert4caa1f02014-08-20 09:16:57 -0700462 }
463#endif
464}
Christopher Ferrisad33ebe2015-12-16 12:07:25 -0800465
Christopher Ferrisdb9706a2019-05-02 18:33:11 -0700466TEST(malloc, malloc_info_matches_mallinfo) {
467#ifdef __BIONIC__
468 SKIP_WITH_HWASAN; // hwasan does not implement malloc_info
469
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800470 TemporaryFile tf;
471 ASSERT_TRUE(tf.fd != -1);
472 FILE* fp = fdopen(tf.fd, "w+");
473 tf.release();
474 ASSERT_TRUE(fp != nullptr);
Christopher Ferrisdb9706a2019-05-02 18:33:11 -0700475 size_t mallinfo_before_allocated_bytes = mallinfo().uordblks;
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800476 ASSERT_EQ(0, malloc_info(0, fp));
Christopher Ferrisdb9706a2019-05-02 18:33:11 -0700477 size_t mallinfo_after_allocated_bytes = mallinfo().uordblks;
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800478 ASSERT_EQ(0, fclose(fp));
479
480 std::string contents;
481 ASSERT_TRUE(android::base::ReadFileToString(tf.path, &contents));
Christopher Ferrisdb9706a2019-05-02 18:33:11 -0700482
483 tinyxml2::XMLDocument doc;
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800484 ASSERT_EQ(tinyxml2::XML_SUCCESS, doc.Parse(contents.c_str()));
Christopher Ferrisdb9706a2019-05-02 18:33:11 -0700485
486 size_t total_allocated_bytes = 0;
487 auto root = doc.FirstChildElement();
488 ASSERT_NE(nullptr, root);
489 ASSERT_STREQ("malloc", root->Name());
Christopher Ferris85169652019-10-09 18:41:55 -0700490 std::string version(root->Attribute("version"));
491 if (version == "jemalloc-1") {
Christopher Ferrisdb9706a2019-05-02 18:33:11 -0700492 auto arena = root->FirstChildElement();
493 for (; arena != nullptr; arena = arena->NextSiblingElement()) {
494 int val;
495
496 ASSERT_STREQ("heap", arena->Name());
497 ASSERT_EQ(tinyxml2::XML_SUCCESS, arena->QueryIntAttribute("nr", &val));
498 ASSERT_EQ(tinyxml2::XML_SUCCESS,
499 arena->FirstChildElement("allocated-large")->QueryIntText(&val));
500 total_allocated_bytes += val;
501 ASSERT_EQ(tinyxml2::XML_SUCCESS,
502 arena->FirstChildElement("allocated-huge")->QueryIntText(&val));
503 total_allocated_bytes += val;
504 ASSERT_EQ(tinyxml2::XML_SUCCESS,
505 arena->FirstChildElement("allocated-bins")->QueryIntText(&val));
506 total_allocated_bytes += val;
507 ASSERT_EQ(tinyxml2::XML_SUCCESS,
508 arena->FirstChildElement("bins-total")->QueryIntText(&val));
509 }
510 // The total needs to be between the mallinfo call before and after
511 // since malloc_info allocates some memory.
512 EXPECT_LE(mallinfo_before_allocated_bytes, total_allocated_bytes);
513 EXPECT_GE(mallinfo_after_allocated_bytes, total_allocated_bytes);
Christopher Ferriscce88c02020-02-12 17:41:01 -0800514 } else if (version == "scudo-1") {
515 auto element = root->FirstChildElement();
516 for (; element != nullptr; element = element->NextSiblingElement()) {
517 ASSERT_STREQ("alloc", element->Name());
518 int size;
519 ASSERT_EQ(tinyxml2::XML_SUCCESS, element->QueryIntAttribute("size", &size));
520 int count;
521 ASSERT_EQ(tinyxml2::XML_SUCCESS, element->QueryIntAttribute("count", &count));
522 total_allocated_bytes += size * count;
523 }
524 // Scudo only gives the information on the primary, so simply make
525 // sure that the value is non-zero.
526 EXPECT_NE(0U, total_allocated_bytes);
Christopher Ferrisdb9706a2019-05-02 18:33:11 -0700527 } else {
Christopher Ferriscce88c02020-02-12 17:41:01 -0800528 // Do not verify output for debug malloc.
529 ASSERT_TRUE(version == "debug-malloc-1") << "Unknown version: " << version;
Christopher Ferrisdb9706a2019-05-02 18:33:11 -0700530 }
531#endif
532}
533
Christopher Ferrisad33ebe2015-12-16 12:07:25 -0800534TEST(malloc, calloc_usable_size) {
535 for (size_t size = 1; size <= 2048; size++) {
536 void* pointer = malloc(size);
537 ASSERT_TRUE(pointer != nullptr);
538 memset(pointer, 0xeb, malloc_usable_size(pointer));
539 free(pointer);
540
541 // We should get a previous pointer that has been set to non-zero.
542 // If calloc does not zero out all of the data, this will fail.
543 uint8_t* zero_mem = reinterpret_cast<uint8_t*>(calloc(1, size));
544 ASSERT_TRUE(pointer != nullptr);
545 size_t usable_size = malloc_usable_size(zero_mem);
546 for (size_t i = 0; i < usable_size; i++) {
547 ASSERT_EQ(0, zero_mem[i]) << "Failed at allocation size " << size << " at byte " << i;
548 }
549 free(zero_mem);
550 }
551}
Elliott Hughes884f76e2016-02-10 20:43:22 -0800552
553TEST(malloc, malloc_0) {
554 void* p = malloc(0);
555 ASSERT_TRUE(p != nullptr);
556 free(p);
557}
558
559TEST(malloc, calloc_0_0) {
560 void* p = calloc(0, 0);
561 ASSERT_TRUE(p != nullptr);
562 free(p);
563}
564
565TEST(malloc, calloc_0_1) {
566 void* p = calloc(0, 1);
567 ASSERT_TRUE(p != nullptr);
568 free(p);
569}
570
571TEST(malloc, calloc_1_0) {
572 void* p = calloc(1, 0);
573 ASSERT_TRUE(p != nullptr);
574 free(p);
575}
576
577TEST(malloc, realloc_nullptr_0) {
578 // realloc(nullptr, size) is actually malloc(size).
579 void* p = realloc(nullptr, 0);
580 ASSERT_TRUE(p != nullptr);
581 free(p);
582}
583
584TEST(malloc, realloc_0) {
585 void* p = malloc(1024);
586 ASSERT_TRUE(p != nullptr);
587 // realloc(p, 0) is actually free(p).
588 void* p2 = realloc(p, 0);
589 ASSERT_TRUE(p2 == nullptr);
590}
Christopher Ferris72df6702016-02-11 15:51:31 -0800591
592constexpr size_t MAX_LOOPS = 200;
593
594// Make sure that memory returned by malloc is aligned to allow these data types.
595TEST(malloc, verify_alignment) {
596 uint32_t** values_32 = new uint32_t*[MAX_LOOPS];
597 uint64_t** values_64 = new uint64_t*[MAX_LOOPS];
598 long double** values_ldouble = new long double*[MAX_LOOPS];
599 // Use filler to attempt to force the allocator to get potentially bad alignments.
600 void** filler = new void*[MAX_LOOPS];
601
602 for (size_t i = 0; i < MAX_LOOPS; i++) {
603 // Check uint32_t pointers.
604 filler[i] = malloc(1);
605 ASSERT_TRUE(filler[i] != nullptr);
606
607 values_32[i] = reinterpret_cast<uint32_t*>(malloc(sizeof(uint32_t)));
608 ASSERT_TRUE(values_32[i] != nullptr);
609 *values_32[i] = i;
610 ASSERT_EQ(*values_32[i], i);
611 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(values_32[i]) & (sizeof(uint32_t) - 1));
612
613 free(filler[i]);
614 }
615
616 for (size_t i = 0; i < MAX_LOOPS; i++) {
617 // Check uint64_t pointers.
618 filler[i] = malloc(1);
619 ASSERT_TRUE(filler[i] != nullptr);
620
621 values_64[i] = reinterpret_cast<uint64_t*>(malloc(sizeof(uint64_t)));
622 ASSERT_TRUE(values_64[i] != nullptr);
623 *values_64[i] = 0x1000 + i;
624 ASSERT_EQ(*values_64[i], 0x1000 + i);
625 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(values_64[i]) & (sizeof(uint64_t) - 1));
626
627 free(filler[i]);
628 }
629
630 for (size_t i = 0; i < MAX_LOOPS; i++) {
631 // Check long double pointers.
632 filler[i] = malloc(1);
633 ASSERT_TRUE(filler[i] != nullptr);
634
635 values_ldouble[i] = reinterpret_cast<long double*>(malloc(sizeof(long double)));
636 ASSERT_TRUE(values_ldouble[i] != nullptr);
637 *values_ldouble[i] = 5.5 + i;
638 ASSERT_DOUBLE_EQ(*values_ldouble[i], 5.5 + i);
639 // 32 bit glibc has a long double size of 12 bytes, so hardcode the
640 // required alignment to 0x7.
641#if !defined(__BIONIC__) && !defined(__LP64__)
642 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(values_ldouble[i]) & 0x7);
643#else
644 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(values_ldouble[i]) & (sizeof(long double) - 1));
645#endif
646
647 free(filler[i]);
648 }
649
650 for (size_t i = 0; i < MAX_LOOPS; i++) {
651 free(values_32[i]);
652 free(values_64[i]);
653 free(values_ldouble[i]);
654 }
655
656 delete[] filler;
657 delete[] values_32;
658 delete[] values_64;
659 delete[] values_ldouble;
660}
Christopher Ferrisa1c0d2f2017-05-15 15:50:19 -0700661
662TEST(malloc, mallopt_smoke) {
Colin Cross4c5595c2021-08-16 15:51:59 -0700663#if !defined(ANDROID_HOST_MUSL)
Christopher Ferrisa1c0d2f2017-05-15 15:50:19 -0700664 errno = 0;
665 ASSERT_EQ(0, mallopt(-1000, 1));
666 // mallopt doesn't set errno.
667 ASSERT_EQ(0, errno);
Colin Cross7da20342021-07-28 11:18:11 -0700668#else
669 GTEST_SKIP() << "musl doesn't have mallopt";
670#endif
Christopher Ferrisa1c0d2f2017-05-15 15:50:19 -0700671}
Elliott Hughesb1770852018-09-18 12:52:42 -0700672
Christopher Ferrisaf1b8dd2018-11-07 15:28:16 -0800673TEST(malloc, mallopt_decay) {
674#if defined(__BIONIC__)
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800675 SKIP_WITH_HWASAN << "hwasan does not implement mallopt";
Christopher Ferrisaf1b8dd2018-11-07 15:28:16 -0800676 errno = 0;
677 ASSERT_EQ(1, mallopt(M_DECAY_TIME, 1));
678 ASSERT_EQ(1, mallopt(M_DECAY_TIME, 0));
679 ASSERT_EQ(1, mallopt(M_DECAY_TIME, 1));
680 ASSERT_EQ(1, mallopt(M_DECAY_TIME, 0));
681#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800682 GTEST_SKIP() << "bionic-only test";
Christopher Ferrisaf1b8dd2018-11-07 15:28:16 -0800683#endif
684}
685
686TEST(malloc, mallopt_purge) {
687#if defined(__BIONIC__)
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800688 SKIP_WITH_HWASAN << "hwasan does not implement mallopt";
Christopher Ferrisaf1b8dd2018-11-07 15:28:16 -0800689 errno = 0;
690 ASSERT_EQ(1, mallopt(M_PURGE, 0));
691#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800692 GTEST_SKIP() << "bionic-only test";
Christopher Ferrisaf1b8dd2018-11-07 15:28:16 -0800693#endif
694}
695
Christopher Ferris88448792020-07-28 14:15:31 -0700696#if defined(__BIONIC__)
697static void GetAllocatorVersion(bool* allocator_scudo) {
698 TemporaryFile tf;
699 ASSERT_TRUE(tf.fd != -1);
700 FILE* fp = fdopen(tf.fd, "w+");
701 tf.release();
702 ASSERT_TRUE(fp != nullptr);
Evgenii Stepanov4edbcee2021-09-17 14:59:15 -0700703 if (malloc_info(0, fp) != 0) {
704 *allocator_scudo = false;
705 return;
706 }
Christopher Ferris88448792020-07-28 14:15:31 -0700707 ASSERT_EQ(0, fclose(fp));
708
709 std::string contents;
710 ASSERT_TRUE(android::base::ReadFileToString(tf.path, &contents));
711
712 tinyxml2::XMLDocument doc;
713 ASSERT_EQ(tinyxml2::XML_SUCCESS, doc.Parse(contents.c_str()));
714
715 auto root = doc.FirstChildElement();
716 ASSERT_NE(nullptr, root);
717 ASSERT_STREQ("malloc", root->Name());
718 std::string version(root->Attribute("version"));
719 *allocator_scudo = (version == "scudo-1");
720}
721#endif
722
723TEST(malloc, mallopt_scudo_only_options) {
724#if defined(__BIONIC__)
725 SKIP_WITH_HWASAN << "hwasan does not implement mallopt";
726 bool allocator_scudo;
727 GetAllocatorVersion(&allocator_scudo);
728 if (!allocator_scudo) {
729 GTEST_SKIP() << "scudo allocator only test";
730 }
731 ASSERT_EQ(1, mallopt(M_CACHE_COUNT_MAX, 100));
732 ASSERT_EQ(1, mallopt(M_CACHE_SIZE_MAX, 1024 * 1024 * 2));
733 ASSERT_EQ(1, mallopt(M_TSDS_COUNT_MAX, 8));
734#else
735 GTEST_SKIP() << "bionic-only test";
736#endif
737}
738
Elliott Hughesb1770852018-09-18 12:52:42 -0700739TEST(malloc, reallocarray_overflow) {
740#if HAVE_REALLOCARRAY
741 // Values that cause overflow to a result small enough (8 on LP64) that malloc would "succeed".
742 size_t a = static_cast<size_t>(INTPTR_MIN + 4);
743 size_t b = 2;
744
745 errno = 0;
746 ASSERT_TRUE(reallocarray(nullptr, a, b) == nullptr);
747 ASSERT_EQ(ENOMEM, errno);
748
749 errno = 0;
750 ASSERT_TRUE(reallocarray(nullptr, b, a) == nullptr);
751 ASSERT_EQ(ENOMEM, errno);
752#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800753 GTEST_SKIP() << "reallocarray not available";
Elliott Hughesb1770852018-09-18 12:52:42 -0700754#endif
755}
756
757TEST(malloc, reallocarray) {
758#if HAVE_REALLOCARRAY
759 void* p = reallocarray(nullptr, 2, 32);
760 ASSERT_TRUE(p != nullptr);
761 ASSERT_GE(malloc_usable_size(p), 64U);
762#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800763 GTEST_SKIP() << "reallocarray not available";
Elliott Hughesb1770852018-09-18 12:52:42 -0700764#endif
765}
Christopher Ferris09a19aa2018-11-16 13:28:56 -0800766
767TEST(malloc, mallinfo) {
768#if defined(__BIONIC__)
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800769 SKIP_WITH_HWASAN << "hwasan does not implement mallinfo";
Christopher Ferris09a19aa2018-11-16 13:28:56 -0800770 static size_t sizes[] = {
771 8, 32, 128, 4096, 32768, 131072, 1024000, 10240000, 20480000, 300000000
772 };
773
774 constexpr static size_t kMaxAllocs = 50;
775
776 for (size_t size : sizes) {
777 // If some of these allocations are stuck in a thread cache, then keep
778 // looping until we make an allocation that changes the total size of the
779 // memory allocated.
780 // jemalloc implementations counts the thread cache allocations against
781 // total memory allocated.
782 void* ptrs[kMaxAllocs] = {};
783 bool pass = false;
784 for (size_t i = 0; i < kMaxAllocs; i++) {
785 size_t allocated = mallinfo().uordblks;
786 ptrs[i] = malloc(size);
787 ASSERT_TRUE(ptrs[i] != nullptr);
788 size_t new_allocated = mallinfo().uordblks;
789 if (allocated != new_allocated) {
790 size_t usable_size = malloc_usable_size(ptrs[i]);
Christopher Ferris4e562282019-02-07 14:20:03 -0800791 // Only check if the total got bigger by at least allocation size.
792 // Sometimes the mallinfo numbers can go backwards due to compaction
793 // and/or freeing of cached data.
794 if (new_allocated >= allocated + usable_size) {
795 pass = true;
796 break;
797 }
Christopher Ferris09a19aa2018-11-16 13:28:56 -0800798 }
799 }
800 for (void* ptr : ptrs) {
801 free(ptr);
802 }
803 ASSERT_TRUE(pass)
804 << "For size " << size << " allocated bytes did not increase after "
805 << kMaxAllocs << " allocations.";
806 }
807#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800808 GTEST_SKIP() << "glibc is broken";
Christopher Ferris09a19aa2018-11-16 13:28:56 -0800809#endif
810}
Ryan Savitskiecc37e32018-12-14 15:57:21 +0000811
Christopher Ferris8248e622021-12-03 13:55:57 -0800812TEST(malloc, mallinfo2) {
813#if defined(__BIONIC__)
814 SKIP_WITH_HWASAN << "hwasan does not implement mallinfo2";
815 static size_t sizes[] = {8, 32, 128, 4096, 32768, 131072, 1024000, 10240000, 20480000, 300000000};
816
817 constexpr static size_t kMaxAllocs = 50;
818
819 for (size_t size : sizes) {
820 // If some of these allocations are stuck in a thread cache, then keep
821 // looping until we make an allocation that changes the total size of the
822 // memory allocated.
823 // jemalloc implementations counts the thread cache allocations against
824 // total memory allocated.
825 void* ptrs[kMaxAllocs] = {};
826 bool pass = false;
827 for (size_t i = 0; i < kMaxAllocs; i++) {
828 struct mallinfo info = mallinfo();
829 struct mallinfo2 info2 = mallinfo2();
830 // Verify that mallinfo and mallinfo2 are exactly the same.
831 ASSERT_EQ(info.arena, info2.arena);
832 ASSERT_EQ(info.ordblks, info2.ordblks);
833 ASSERT_EQ(info.smblks, info2.smblks);
834 ASSERT_EQ(info.hblks, info2.hblks);
835 ASSERT_EQ(info.hblkhd, info2.hblkhd);
836 ASSERT_EQ(info.usmblks, info2.usmblks);
837 ASSERT_EQ(info.fsmblks, info2.fsmblks);
838 ASSERT_EQ(info.uordblks, info2.uordblks);
839 ASSERT_EQ(info.fordblks, info2.fordblks);
840 ASSERT_EQ(info.keepcost, info2.keepcost);
841
842 size_t allocated = info2.uordblks;
843 ptrs[i] = malloc(size);
844 ASSERT_TRUE(ptrs[i] != nullptr);
845
846 info = mallinfo();
847 info2 = mallinfo2();
848 // Verify that mallinfo and mallinfo2 are exactly the same.
849 ASSERT_EQ(info.arena, info2.arena);
850 ASSERT_EQ(info.ordblks, info2.ordblks);
851 ASSERT_EQ(info.smblks, info2.smblks);
852 ASSERT_EQ(info.hblks, info2.hblks);
853 ASSERT_EQ(info.hblkhd, info2.hblkhd);
854 ASSERT_EQ(info.usmblks, info2.usmblks);
855 ASSERT_EQ(info.fsmblks, info2.fsmblks);
856 ASSERT_EQ(info.uordblks, info2.uordblks);
857 ASSERT_EQ(info.fordblks, info2.fordblks);
858 ASSERT_EQ(info.keepcost, info2.keepcost);
859
860 size_t new_allocated = info2.uordblks;
861 if (allocated != new_allocated) {
862 size_t usable_size = malloc_usable_size(ptrs[i]);
863 // Only check if the total got bigger by at least allocation size.
864 // Sometimes the mallinfo2 numbers can go backwards due to compaction
865 // and/or freeing of cached data.
866 if (new_allocated >= allocated + usable_size) {
867 pass = true;
868 break;
869 }
870 }
871 }
872 for (void* ptr : ptrs) {
873 free(ptr);
874 }
875 ASSERT_TRUE(pass) << "For size " << size << " allocated bytes did not increase after "
876 << kMaxAllocs << " allocations.";
877 }
878#else
879 GTEST_SKIP() << "glibc is broken";
880#endif
881}
882
Christopher Ferrisf32494c2020-01-08 14:19:10 -0800883template <typename Type>
884void __attribute__((optnone)) VerifyAlignment(Type* floating) {
885 size_t expected_alignment = alignof(Type);
886 if (expected_alignment != 0) {
887 ASSERT_EQ(0U, (expected_alignment - 1) & reinterpret_cast<uintptr_t>(floating))
888 << "Expected alignment " << expected_alignment << " ptr value " << floating;
889 }
890}
891
892template <typename Type>
893void __attribute__((optnone)) TestAllocateType() {
894 // The number of allocations to do in a row. This is to attempt to
895 // expose the worst case alignment for native allocators that use
896 // bins.
897 static constexpr size_t kMaxConsecutiveAllocs = 100;
898
899 // Verify using new directly.
900 Type* types[kMaxConsecutiveAllocs];
901 for (size_t i = 0; i < kMaxConsecutiveAllocs; i++) {
902 types[i] = new Type;
903 VerifyAlignment(types[i]);
904 if (::testing::Test::HasFatalFailure()) {
905 return;
906 }
907 }
908 for (size_t i = 0; i < kMaxConsecutiveAllocs; i++) {
909 delete types[i];
910 }
911
912 // Verify using malloc.
913 for (size_t i = 0; i < kMaxConsecutiveAllocs; i++) {
914 types[i] = reinterpret_cast<Type*>(malloc(sizeof(Type)));
915 ASSERT_TRUE(types[i] != nullptr);
916 VerifyAlignment(types[i]);
917 if (::testing::Test::HasFatalFailure()) {
918 return;
919 }
920 }
921 for (size_t i = 0; i < kMaxConsecutiveAllocs; i++) {
922 free(types[i]);
923 }
924
925 // Verify using a vector.
926 std::vector<Type> type_vector(kMaxConsecutiveAllocs);
927 for (size_t i = 0; i < type_vector.size(); i++) {
928 VerifyAlignment(&type_vector[i]);
929 if (::testing::Test::HasFatalFailure()) {
930 return;
931 }
932 }
933}
934
935#if defined(__ANDROID__)
936static void __attribute__((optnone)) AndroidVerifyAlignment(size_t alloc_size, size_t aligned_bytes) {
937 void* ptrs[100];
938 uintptr_t mask = aligned_bytes - 1;
939 for (size_t i = 0; i < sizeof(ptrs) / sizeof(void*); i++) {
940 ptrs[i] = malloc(alloc_size);
941 ASSERT_TRUE(ptrs[i] != nullptr);
942 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(ptrs[i]) & mask)
943 << "Expected at least " << aligned_bytes << " byte alignment: size "
944 << alloc_size << " actual ptr " << ptrs[i];
945 }
946}
947#endif
948
Christopher Ferrisb3cac0f2021-09-21 10:32:40 -0700949void AlignCheck() {
Christopher Ferrisf32494c2020-01-08 14:19:10 -0800950 // See http://www.open-std.org/jtc1/sc22/wg14/www/docs/summary.htm#dr_445
951 // for a discussion of type alignment.
952 ASSERT_NO_FATAL_FAILURE(TestAllocateType<float>());
953 ASSERT_NO_FATAL_FAILURE(TestAllocateType<double>());
954 ASSERT_NO_FATAL_FAILURE(TestAllocateType<long double>());
955
956 ASSERT_NO_FATAL_FAILURE(TestAllocateType<char>());
957 ASSERT_NO_FATAL_FAILURE(TestAllocateType<char16_t>());
958 ASSERT_NO_FATAL_FAILURE(TestAllocateType<char32_t>());
959 ASSERT_NO_FATAL_FAILURE(TestAllocateType<wchar_t>());
960 ASSERT_NO_FATAL_FAILURE(TestAllocateType<signed char>());
961 ASSERT_NO_FATAL_FAILURE(TestAllocateType<short int>());
962 ASSERT_NO_FATAL_FAILURE(TestAllocateType<int>());
963 ASSERT_NO_FATAL_FAILURE(TestAllocateType<long int>());
964 ASSERT_NO_FATAL_FAILURE(TestAllocateType<long long int>());
965 ASSERT_NO_FATAL_FAILURE(TestAllocateType<unsigned char>());
966 ASSERT_NO_FATAL_FAILURE(TestAllocateType<unsigned short int>());
967 ASSERT_NO_FATAL_FAILURE(TestAllocateType<unsigned int>());
968 ASSERT_NO_FATAL_FAILURE(TestAllocateType<unsigned long int>());
969 ASSERT_NO_FATAL_FAILURE(TestAllocateType<unsigned long long int>());
970
971#if defined(__ANDROID__)
972 // On Android, there is a lot of code that expects certain alignments:
Christopher Ferrisb3cac0f2021-09-21 10:32:40 -0700973 // 1. Allocations of a size that rounds up to a multiple of 16 bytes
974 // must have at least 16 byte alignment.
975 // 2. Allocations of a size that rounds up to a multiple of 8 bytes and
976 // not 16 bytes, are only required to have at least 8 byte alignment.
977 // In addition, on Android clang has been configured for 64 bit such that:
978 // 3. Allocations <= 8 bytes must be aligned to at least 8 bytes.
979 // 4. Allocations > 8 bytes must be aligned to at least 16 bytes.
980 // For 32 bit environments, only the first two requirements must be met.
Christopher Ferrisf32494c2020-01-08 14:19:10 -0800981
982 // See http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2293.htm for
983 // a discussion of this alignment mess. The code below is enforcing
984 // strong-alignment, since who knows what code depends on this behavior now.
Christopher Ferrisb3cac0f2021-09-21 10:32:40 -0700985 // As mentioned before, for 64 bit this will enforce the higher
986 // requirement since clang expects this behavior on Android now.
Christopher Ferrisf32494c2020-01-08 14:19:10 -0800987 for (size_t i = 1; i <= 128; i++) {
Christopher Ferrisb3cac0f2021-09-21 10:32:40 -0700988#if defined(__LP64__)
989 if (i <= 8) {
990 AndroidVerifyAlignment(i, 8);
991 } else {
992 AndroidVerifyAlignment(i, 16);
993 }
994#else
Christopher Ferrisf32494c2020-01-08 14:19:10 -0800995 size_t rounded = (i + 7) & ~7;
996 if ((rounded % 16) == 0) {
997 AndroidVerifyAlignment(i, 16);
998 } else {
999 AndroidVerifyAlignment(i, 8);
1000 }
Christopher Ferrisb3cac0f2021-09-21 10:32:40 -07001001#endif
Christopher Ferrisf32494c2020-01-08 14:19:10 -08001002 if (::testing::Test::HasFatalFailure()) {
1003 return;
1004 }
1005 }
1006#endif
1007}
1008
Christopher Ferrisb3cac0f2021-09-21 10:32:40 -07001009TEST(malloc, align_check) {
1010 AlignCheck();
1011}
1012
1013// Force GWP-ASan on and verify all alignment checks still pass.
1014TEST(malloc, align_check_gwp_asan) {
1015#if defined(__BIONIC__)
1016 bool force_init = true;
1017 ASSERT_TRUE(android_mallopt(M_INITIALIZE_GWP_ASAN, &force_init, sizeof(force_init)));
1018
1019 AlignCheck();
1020#else
1021 GTEST_SKIP() << "bionic-only test";
1022#endif
1023}
1024
Christopher Ferris201dcf42020-01-29 13:09:31 -08001025// Jemalloc doesn't pass this test right now, so leave it as disabled.
1026TEST(malloc, DISABLED_alloc_after_fork) {
1027 // Both of these need to be a power of 2.
1028 static constexpr size_t kMinAllocationSize = 8;
1029 static constexpr size_t kMaxAllocationSize = 2097152;
1030
1031 static constexpr size_t kNumAllocatingThreads = 5;
1032 static constexpr size_t kNumForkLoops = 100;
1033
1034 std::atomic_bool stop;
1035
1036 // Create threads that simply allocate and free different sizes.
1037 std::vector<std::thread*> threads;
1038 for (size_t i = 0; i < kNumAllocatingThreads; i++) {
1039 std::thread* t = new std::thread([&stop] {
1040 while (!stop) {
1041 for (size_t size = kMinAllocationSize; size <= kMaxAllocationSize; size <<= 1) {
Elliott Hughes7cda75f2020-10-22 13:22:35 -07001042 void* ptr;
1043 DoNotOptimize(ptr = malloc(size));
Christopher Ferris201dcf42020-01-29 13:09:31 -08001044 free(ptr);
1045 }
1046 }
1047 });
1048 threads.push_back(t);
1049 }
1050
1051 // Create a thread to fork and allocate.
1052 for (size_t i = 0; i < kNumForkLoops; i++) {
1053 pid_t pid;
1054 if ((pid = fork()) == 0) {
1055 for (size_t size = kMinAllocationSize; size <= kMaxAllocationSize; size <<= 1) {
Elliott Hughes7cda75f2020-10-22 13:22:35 -07001056 void* ptr;
1057 DoNotOptimize(ptr = malloc(size));
Christopher Ferris201dcf42020-01-29 13:09:31 -08001058 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris201dcf42020-01-29 13:09:31 -08001059 // Make sure we can touch all of the allocation.
1060 memset(ptr, 0x1, size);
1061 ASSERT_LE(size, malloc_usable_size(ptr));
1062 free(ptr);
1063 }
1064 _exit(10);
1065 }
1066 ASSERT_NE(-1, pid);
1067 AssertChildExited(pid, 10);
1068 }
1069
1070 stop = true;
1071 for (auto thread : threads) {
1072 thread->join();
1073 delete thread;
1074 }
1075}
1076
Ryan Savitskiecc37e32018-12-14 15:57:21 +00001077TEST(android_mallopt, error_on_unexpected_option) {
1078#if defined(__BIONIC__)
1079 const int unrecognized_option = -1;
1080 errno = 0;
1081 EXPECT_EQ(false, android_mallopt(unrecognized_option, nullptr, 0));
1082 EXPECT_EQ(ENOTSUP, errno);
1083#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -08001084 GTEST_SKIP() << "bionic-only test";
Ryan Savitskiecc37e32018-12-14 15:57:21 +00001085#endif
1086}
1087
Christopher Ferrise4cdbc42019-02-08 17:30:58 -08001088bool IsDynamic() {
1089#if defined(__LP64__)
1090 Elf64_Ehdr ehdr;
1091#else
1092 Elf32_Ehdr ehdr;
1093#endif
1094 std::string path(android::base::GetExecutablePath());
1095
1096 int fd = open(path.c_str(), O_RDONLY | O_CLOEXEC);
1097 if (fd == -1) {
1098 // Assume dynamic on error.
1099 return true;
1100 }
1101 bool read_completed = android::base::ReadFully(fd, &ehdr, sizeof(ehdr));
1102 close(fd);
1103 // Assume dynamic in error cases.
1104 return !read_completed || ehdr.e_type == ET_DYN;
1105}
1106
Ryan Savitskiecc37e32018-12-14 15:57:21 +00001107TEST(android_mallopt, init_zygote_child_profiling) {
1108#if defined(__BIONIC__)
1109 // Successful call.
1110 errno = 0;
Christopher Ferrise4cdbc42019-02-08 17:30:58 -08001111 if (IsDynamic()) {
1112 EXPECT_EQ(true, android_mallopt(M_INIT_ZYGOTE_CHILD_PROFILING, nullptr, 0));
1113 EXPECT_EQ(0, errno);
1114 } else {
1115 // Not supported in static executables.
1116 EXPECT_EQ(false, android_mallopt(M_INIT_ZYGOTE_CHILD_PROFILING, nullptr, 0));
1117 EXPECT_EQ(ENOTSUP, errno);
1118 }
Ryan Savitskiecc37e32018-12-14 15:57:21 +00001119
1120 // Unexpected arguments rejected.
1121 errno = 0;
1122 char unexpected = 0;
1123 EXPECT_EQ(false, android_mallopt(M_INIT_ZYGOTE_CHILD_PROFILING, &unexpected, 1));
Christopher Ferrise4cdbc42019-02-08 17:30:58 -08001124 if (IsDynamic()) {
1125 EXPECT_EQ(EINVAL, errno);
1126 } else {
1127 EXPECT_EQ(ENOTSUP, errno);
1128 }
Ryan Savitskiecc37e32018-12-14 15:57:21 +00001129#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -08001130 GTEST_SKIP() << "bionic-only test";
Ryan Savitskiecc37e32018-12-14 15:57:21 +00001131#endif
1132}
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -08001133
1134#if defined(__BIONIC__)
1135template <typename FuncType>
1136void CheckAllocationFunction(FuncType func) {
1137 // Assumes that no more than 108MB of memory is allocated before this.
1138 size_t limit = 128 * 1024 * 1024;
1139 ASSERT_TRUE(android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit)));
1140 if (!func(20 * 1024 * 1024))
1141 exit(1);
1142 if (func(128 * 1024 * 1024))
1143 exit(1);
1144 exit(0);
1145}
1146#endif
1147
1148TEST(android_mallopt, set_allocation_limit) {
1149#if defined(__BIONIC__)
1150 EXPECT_EXIT(CheckAllocationFunction([](size_t bytes) { return calloc(bytes, 1) != nullptr; }),
1151 testing::ExitedWithCode(0), "");
1152 EXPECT_EXIT(CheckAllocationFunction([](size_t bytes) { return calloc(1, bytes) != nullptr; }),
1153 testing::ExitedWithCode(0), "");
1154 EXPECT_EXIT(CheckAllocationFunction([](size_t bytes) { return malloc(bytes) != nullptr; }),
1155 testing::ExitedWithCode(0), "");
1156 EXPECT_EXIT(CheckAllocationFunction(
1157 [](size_t bytes) { return memalign(sizeof(void*), bytes) != nullptr; }),
1158 testing::ExitedWithCode(0), "");
1159 EXPECT_EXIT(CheckAllocationFunction([](size_t bytes) {
1160 void* ptr;
1161 return posix_memalign(&ptr, sizeof(void *), bytes) == 0;
1162 }),
1163 testing::ExitedWithCode(0), "");
1164 EXPECT_EXIT(CheckAllocationFunction(
1165 [](size_t bytes) { return aligned_alloc(sizeof(void*), bytes) != nullptr; }),
1166 testing::ExitedWithCode(0), "");
1167 EXPECT_EXIT(CheckAllocationFunction([](size_t bytes) {
1168 void* p = malloc(1024 * 1024);
1169 return realloc(p, bytes) != nullptr;
1170 }),
1171 testing::ExitedWithCode(0), "");
1172#if !defined(__LP64__)
1173 EXPECT_EXIT(CheckAllocationFunction([](size_t bytes) { return pvalloc(bytes) != nullptr; }),
1174 testing::ExitedWithCode(0), "");
1175 EXPECT_EXIT(CheckAllocationFunction([](size_t bytes) { return valloc(bytes) != nullptr; }),
1176 testing::ExitedWithCode(0), "");
1177#endif
1178#else
Elliott Hughes10907202019-03-27 08:51:02 -07001179 GTEST_SKIP() << "bionic extension";
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -08001180#endif
1181}
1182
1183TEST(android_mallopt, set_allocation_limit_multiple) {
1184#if defined(__BIONIC__)
1185 // Only the first set should work.
1186 size_t limit = 256 * 1024 * 1024;
1187 ASSERT_TRUE(android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit)));
1188 limit = 32 * 1024 * 1024;
1189 ASSERT_FALSE(android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit)));
1190#else
Elliott Hughes10907202019-03-27 08:51:02 -07001191 GTEST_SKIP() << "bionic extension";
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -08001192#endif
1193}
1194
1195#if defined(__BIONIC__)
1196static constexpr size_t kAllocationSize = 8 * 1024 * 1024;
1197
1198static size_t GetMaxAllocations() {
1199 size_t max_pointers = 0;
1200 void* ptrs[20];
1201 for (size_t i = 0; i < sizeof(ptrs) / sizeof(void*); i++) {
1202 ptrs[i] = malloc(kAllocationSize);
1203 if (ptrs[i] == nullptr) {
1204 max_pointers = i;
1205 break;
1206 }
1207 }
1208 for (size_t i = 0; i < max_pointers; i++) {
1209 free(ptrs[i]);
1210 }
1211 return max_pointers;
1212}
1213
1214static void VerifyMaxPointers(size_t max_pointers) {
1215 // Now verify that we can allocate the same number as before.
1216 void* ptrs[20];
1217 for (size_t i = 0; i < max_pointers; i++) {
1218 ptrs[i] = malloc(kAllocationSize);
1219 ASSERT_TRUE(ptrs[i] != nullptr) << "Failed to allocate on iteration " << i;
1220 }
1221
1222 // Make sure the next allocation still fails.
1223 ASSERT_TRUE(malloc(kAllocationSize) == nullptr);
1224 for (size_t i = 0; i < max_pointers; i++) {
1225 free(ptrs[i]);
1226 }
1227}
1228#endif
1229
1230TEST(android_mallopt, set_allocation_limit_realloc_increase) {
1231#if defined(__BIONIC__)
1232 size_t limit = 128 * 1024 * 1024;
1233 ASSERT_TRUE(android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit)));
1234
1235 size_t max_pointers = GetMaxAllocations();
1236 ASSERT_TRUE(max_pointers != 0) << "Limit never reached.";
1237
1238 void* memory = malloc(10 * 1024 * 1024);
1239 ASSERT_TRUE(memory != nullptr);
1240
1241 // Increase size.
1242 memory = realloc(memory, 20 * 1024 * 1024);
1243 ASSERT_TRUE(memory != nullptr);
1244 memory = realloc(memory, 40 * 1024 * 1024);
1245 ASSERT_TRUE(memory != nullptr);
1246 memory = realloc(memory, 60 * 1024 * 1024);
1247 ASSERT_TRUE(memory != nullptr);
1248 memory = realloc(memory, 80 * 1024 * 1024);
1249 ASSERT_TRUE(memory != nullptr);
1250 // Now push past limit.
1251 memory = realloc(memory, 130 * 1024 * 1024);
1252 ASSERT_TRUE(memory == nullptr);
1253
1254 VerifyMaxPointers(max_pointers);
1255#else
Elliott Hughes10907202019-03-27 08:51:02 -07001256 GTEST_SKIP() << "bionic extension";
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -08001257#endif
1258}
1259
1260TEST(android_mallopt, set_allocation_limit_realloc_decrease) {
1261#if defined(__BIONIC__)
1262 size_t limit = 100 * 1024 * 1024;
1263 ASSERT_TRUE(android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit)));
1264
1265 size_t max_pointers = GetMaxAllocations();
1266 ASSERT_TRUE(max_pointers != 0) << "Limit never reached.";
1267
1268 void* memory = malloc(80 * 1024 * 1024);
1269 ASSERT_TRUE(memory != nullptr);
1270
1271 // Decrease size.
1272 memory = realloc(memory, 60 * 1024 * 1024);
1273 ASSERT_TRUE(memory != nullptr);
1274 memory = realloc(memory, 40 * 1024 * 1024);
1275 ASSERT_TRUE(memory != nullptr);
1276 memory = realloc(memory, 20 * 1024 * 1024);
1277 ASSERT_TRUE(memory != nullptr);
1278 memory = realloc(memory, 10 * 1024 * 1024);
1279 ASSERT_TRUE(memory != nullptr);
1280 free(memory);
1281
1282 VerifyMaxPointers(max_pointers);
1283#else
Elliott Hughes10907202019-03-27 08:51:02 -07001284 GTEST_SKIP() << "bionic extension";
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -08001285#endif
1286}
1287
1288TEST(android_mallopt, set_allocation_limit_realloc_free) {
1289#if defined(__BIONIC__)
1290 size_t limit = 100 * 1024 * 1024;
1291 ASSERT_TRUE(android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit)));
1292
1293 size_t max_pointers = GetMaxAllocations();
1294 ASSERT_TRUE(max_pointers != 0) << "Limit never reached.";
1295
1296 void* memory = malloc(60 * 1024 * 1024);
1297 ASSERT_TRUE(memory != nullptr);
1298
1299 memory = realloc(memory, 0);
1300 ASSERT_TRUE(memory == nullptr);
1301
1302 VerifyMaxPointers(max_pointers);
1303#else
Elliott Hughes10907202019-03-27 08:51:02 -07001304 GTEST_SKIP() << "bionic extension";
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -08001305#endif
1306}
1307
1308#if defined(__BIONIC__)
1309static void* SetAllocationLimit(void* data) {
1310 std::atomic_bool* go = reinterpret_cast<std::atomic_bool*>(data);
1311 while (!go->load()) {
1312 }
1313 size_t limit = 500 * 1024 * 1024;
1314 if (android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit))) {
1315 return reinterpret_cast<void*>(-1);
1316 }
1317 return nullptr;
1318}
1319
1320static void SetAllocationLimitMultipleThreads() {
1321 std::atomic_bool go;
1322 go = false;
1323
1324 static constexpr size_t kNumThreads = 4;
1325 pthread_t threads[kNumThreads];
1326 for (size_t i = 0; i < kNumThreads; i++) {
1327 ASSERT_EQ(0, pthread_create(&threads[i], nullptr, SetAllocationLimit, &go));
1328 }
1329
1330 // Let them go all at once.
1331 go = true;
Ryan Savitski175c8862020-01-02 19:54:57 +00001332 // Send hardcoded signal (BIONIC_SIGNAL_PROFILER with value 0) to trigger
1333 // heapprofd handler.
1334 union sigval signal_value;
1335 signal_value.sival_int = 0;
Christopher Ferrisb874c332020-01-21 16:39:05 -08001336 ASSERT_EQ(0, sigqueue(getpid(), BIONIC_SIGNAL_PROFILER, signal_value));
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -08001337
1338 size_t num_successful = 0;
1339 for (size_t i = 0; i < kNumThreads; i++) {
1340 void* result;
1341 ASSERT_EQ(0, pthread_join(threads[i], &result));
1342 if (result != nullptr) {
1343 num_successful++;
1344 }
1345 }
1346 ASSERT_EQ(1U, num_successful);
1347 exit(0);
1348}
1349#endif
1350
1351TEST(android_mallopt, set_allocation_limit_multiple_threads) {
1352#if defined(__BIONIC__)
1353 if (IsDynamic()) {
1354 ASSERT_TRUE(android_mallopt(M_INIT_ZYGOTE_CHILD_PROFILING, nullptr, 0));
1355 }
1356
1357 // Run this a number of times as a stress test.
1358 for (size_t i = 0; i < 100; i++) {
1359 // Not using ASSERT_EXIT because errors messages are not displayed.
1360 pid_t pid;
1361 if ((pid = fork()) == 0) {
1362 ASSERT_NO_FATAL_FAILURE(SetAllocationLimitMultipleThreads());
1363 }
1364 ASSERT_NE(-1, pid);
1365 int status;
1366 ASSERT_EQ(pid, wait(&status));
1367 ASSERT_EQ(0, WEXITSTATUS(status));
1368 }
1369#else
Elliott Hughes10907202019-03-27 08:51:02 -07001370 GTEST_SKIP() << "bionic extension";
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -08001371#endif
1372}
Peter Collingbourne5d3aa862020-09-11 15:05:17 -07001373
Christopher Ferris8f9713e2021-09-20 17:25:46 -07001374TEST(android_mallopt, force_init_gwp_asan) {
1375#if defined(__BIONIC__)
1376 bool force_init = true;
1377 ASSERT_TRUE(android_mallopt(M_INITIALIZE_GWP_ASAN, &force_init, sizeof(force_init)));
1378
1379 // Verify that trying to do the call again also passes no matter the
1380 // value of force_init.
1381 force_init = false;
1382 ASSERT_TRUE(android_mallopt(M_INITIALIZE_GWP_ASAN, &force_init, sizeof(force_init)));
1383 force_init = true;
1384 ASSERT_TRUE(android_mallopt(M_INITIALIZE_GWP_ASAN, &force_init, sizeof(force_init)));
1385#else
1386 GTEST_SKIP() << "bionic extension";
1387#endif
1388}
1389
Mitch Phillips9cad8422021-01-20 16:03:27 -08001390void TestHeapZeroing(int num_iterations, int (*get_alloc_size)(int iteration)) {
1391 std::vector<void*> allocs;
1392 constexpr int kMaxBytesToCheckZero = 64;
1393 const char kBlankMemory[kMaxBytesToCheckZero] = {};
1394
1395 for (int i = 0; i < num_iterations; ++i) {
1396 int size = get_alloc_size(i);
1397 allocs.push_back(malloc(size));
1398 memset(allocs.back(), 'X', std::min(size, kMaxBytesToCheckZero));
1399 }
1400
1401 for (void* alloc : allocs) {
1402 free(alloc);
1403 }
1404 allocs.clear();
1405
1406 for (int i = 0; i < num_iterations; ++i) {
1407 int size = get_alloc_size(i);
1408 allocs.push_back(malloc(size));
1409 ASSERT_EQ(0, memcmp(allocs.back(), kBlankMemory, std::min(size, kMaxBytesToCheckZero)));
1410 }
1411
1412 for (void* alloc : allocs) {
1413 free(alloc);
1414 }
1415}
1416
1417TEST(malloc, zero_init) {
1418#if defined(__BIONIC__)
1419 SKIP_WITH_HWASAN << "hwasan does not implement mallopt";
1420 bool allocator_scudo;
1421 GetAllocatorVersion(&allocator_scudo);
1422 if (!allocator_scudo) {
1423 GTEST_SKIP() << "scudo allocator only test";
1424 }
1425
1426 mallopt(M_BIONIC_ZERO_INIT, 1);
1427
1428 // Test using a block of 4K small (1-32 byte) allocations.
1429 TestHeapZeroing(/* num_iterations */ 0x1000, [](int iteration) -> int {
1430 return 1 + iteration % 32;
1431 });
1432
1433 // Also test large allocations that land in the scudo secondary, as this is
1434 // the only part of Scudo that's changed by enabling zero initialization with
1435 // MTE. Uses 32 allocations, totalling 60MiB memory. Decay time (time to
1436 // release secondary allocations back to the OS) was modified to 0ms/1ms by
1437 // mallopt_decay. Ensure that we delay for at least a second before releasing
1438 // pages to the OS in order to avoid implicit zeroing by the kernel.
1439 mallopt(M_DECAY_TIME, 1000);
1440 TestHeapZeroing(/* num_iterations */ 32, [](int iteration) -> int {
1441 return 1 << (19 + iteration % 4);
1442 });
1443
1444#else
1445 GTEST_SKIP() << "bionic-only test";
1446#endif
1447}
1448
1449// Note that MTE is enabled on cc_tests on devices that support MTE.
1450TEST(malloc, disable_mte) {
Peter Collingbourne5d3aa862020-09-11 15:05:17 -07001451#if defined(__BIONIC__)
1452 if (!mte_supported()) {
1453 GTEST_SKIP() << "This function can only be tested with MTE";
1454 }
1455
Peter Collingbourne5d3aa862020-09-11 15:05:17 -07001456 sem_t sem;
1457 ASSERT_EQ(0, sem_init(&sem, 0, 0));
1458
1459 pthread_t thread;
1460 ASSERT_EQ(0, pthread_create(
1461 &thread, nullptr,
1462 [](void* ptr) -> void* {
1463 auto* sem = reinterpret_cast<sem_t*>(ptr);
1464 sem_wait(sem);
1465 return reinterpret_cast<void*>(prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0));
1466 },
1467 &sem));
1468
Mitch Phillips9cad8422021-01-20 16:03:27 -08001469 ASSERT_EQ(1, mallopt(M_BIONIC_SET_HEAP_TAGGING_LEVEL, M_HEAP_TAGGING_LEVEL_NONE));
Peter Collingbourne5d3aa862020-09-11 15:05:17 -07001470 ASSERT_EQ(0, sem_post(&sem));
1471
1472 int my_tagged_addr_ctrl = prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0);
Christopher Ferris2abfa9e2021-11-01 16:26:06 -07001473 ASSERT_EQ(static_cast<unsigned long>(PR_MTE_TCF_NONE), my_tagged_addr_ctrl & PR_MTE_TCF_MASK);
Peter Collingbourne5d3aa862020-09-11 15:05:17 -07001474
1475 void* retval;
1476 ASSERT_EQ(0, pthread_join(thread, &retval));
1477 int thread_tagged_addr_ctrl = reinterpret_cast<uintptr_t>(retval);
1478 ASSERT_EQ(my_tagged_addr_ctrl, thread_tagged_addr_ctrl);
Peter Collingbourne5d3aa862020-09-11 15:05:17 -07001479#else
1480 GTEST_SKIP() << "bionic extension";
1481#endif
1482}
Peter Collingbourne2659d7b2021-03-05 13:31:41 -08001483
1484TEST(malloc, allocation_slack) {
1485#if defined(__BIONIC__)
Christopher Ferris7c0ce862021-06-08 15:33:22 -07001486 SKIP_WITH_NATIVE_BRIDGE; // http://b/189606147
1487
Peter Collingbourne2659d7b2021-03-05 13:31:41 -08001488 bool allocator_scudo;
1489 GetAllocatorVersion(&allocator_scudo);
1490 if (!allocator_scudo) {
1491 GTEST_SKIP() << "scudo allocator only test";
1492 }
1493
1494 // Test that older target SDK levels let you access a few bytes off the end of
1495 // a large allocation.
1496 android_set_application_target_sdk_version(29);
1497 auto p = std::make_unique<char[]>(131072);
1498 volatile char *vp = p.get();
1499 volatile char oob ATTRIBUTE_UNUSED = vp[131072];
1500#else
1501 GTEST_SKIP() << "bionic extension";
1502#endif
1503}
Evgenii Stepanovf0d7a342021-11-16 17:34:39 -08001504
1505// Regression test for b/206701345 -- scudo bug, MTE only.
1506// Fix: https://reviews.llvm.org/D105261
1507// Fix: https://android-review.googlesource.com/c/platform/external/scudo/+/1763655
1508TEST(malloc, realloc_mte_crash_b206701345) {
1509 // We want to hit in-place realloc at the very end of an mmap-ed region. Not
1510 // all size classes allow such placement - mmap size has to be divisible by
1511 // the block size. At the time of writing this could only be reproduced with
1512 // 64 byte size class (i.e. 48 byte allocations), but that may change in the
1513 // future. Try several different classes at the lower end.
1514 std::vector<void*> ptrs(10000);
1515 for (int i = 1; i < 32; ++i) {
1516 size_t sz = 16 * i - 1;
1517 for (void*& p : ptrs) {
1518 p = realloc(malloc(sz), sz + 1);
1519 }
1520
1521 for (void* p : ptrs) {
1522 free(p);
1523 }
1524 }
1525}