blob: 837c4408bebfc5ac2198980714c13deb1c84de8d [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 Ferris02b6bbc2022-06-02 15:20:23 -070038#include <functional>
Christopher Ferrisd86eb862023-02-28 12:45:54 -080039#include <string>
Christopher Ferrisf32494c2020-01-08 14:19:10 -080040#include <thread>
Christopher Ferrisd86eb862023-02-28 12:45:54 -080041#include <unordered_map>
42#include <utility>
Mitch Phillips9cad8422021-01-20 16:03:27 -080043#include <vector>
Christopher Ferrisf32494c2020-01-08 14:19:10 -080044
Dan Albert4caa1f02014-08-20 09:16:57 -070045#include <tinyxml2.h>
46
Christopher Ferrise4cdbc42019-02-08 17:30:58 -080047#include <android-base/file.h>
Florian Mayer750dcd32022-04-15 15:54:47 -070048#include <android-base/test_utils.h>
Christopher Ferrise4cdbc42019-02-08 17:30:58 -080049
Christopher Ferrisdc9b0fd2024-09-30 20:05:18 +000050#include "DoNotOptimize.h"
Evgenii Stepanovacd6f4f2018-11-06 16:48:27 -080051#include "utils.h"
Dan Alberte5fdaa42014-06-14 01:04:31 +000052
Elliott Hughesb1770852018-09-18 12:52:42 -070053#if defined(__BIONIC__)
Christopher Ferrisb874c332020-01-21 16:39:05 -080054
Peter Collingbourne45819dd2020-01-09 11:00:43 -080055#include "SignalUtils.h"
56
Elliott Hughes87fcb212025-05-01 08:24:17 -070057#include "platform/bionic/dlext_namespaces.h"
Christopher Ferrisb874c332020-01-21 16:39:05 -080058#include "platform/bionic/malloc.h"
Peter Collingbourne5d3aa862020-09-11 15:05:17 -070059#include "platform/bionic/mte.h"
Christopher Ferrisb874c332020-01-21 16:39:05 -080060#include "platform/bionic/reserved_signals.h"
61#include "private/bionic_config.h"
62
Elliott Hughesb1770852018-09-18 12:52:42 -070063#define HAVE_REALLOCARRAY 1
Christopher Ferrisb874c332020-01-21 16:39:05 -080064
Colin Cross7da20342021-07-28 11:18:11 -070065#elif defined(__GLIBC__)
Christopher Ferrisb874c332020-01-21 16:39:05 -080066
Elliott Hughesb1770852018-09-18 12:52:42 -070067#define HAVE_REALLOCARRAY __GLIBC_PREREQ(2, 26)
Christopher Ferrisb874c332020-01-21 16:39:05 -080068
Colin Cross4c5595c2021-08-16 15:51:59 -070069#elif defined(ANDROID_HOST_MUSL)
Colin Cross7da20342021-07-28 11:18:11 -070070
71#define HAVE_REALLOCARRAY 1
72
Elliott Hughesb1770852018-09-18 12:52:42 -070073#endif
74
Christopher Ferrisa4037802014-06-09 19:14:11 -070075TEST(malloc, malloc_overflow) {
Evgenii Stepanovacd6f4f2018-11-06 16:48:27 -080076 SKIP_WITH_HWASAN;
Christopher Ferrisa4037802014-06-09 19:14:11 -070077 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -070078 ASSERT_EQ(nullptr, malloc(SIZE_MAX));
Elliott Hughes95646e62023-09-21 14:11:19 -070079 ASSERT_ERRNO(ENOMEM);
Christopher Ferrisa4037802014-06-09 19:14:11 -070080}
81
Peter Collingbourne978eb162020-09-21 15:26:02 -070082TEST(malloc, calloc_mem_init_disabled) {
83#if defined(__BIONIC__)
84 // calloc should still zero memory if mem-init is disabled.
85 // With jemalloc the mallopts will fail but that shouldn't affect the
86 // execution of the test.
87 mallopt(M_THREAD_DISABLE_MEM_INIT, 1);
88 size_t alloc_len = 100;
89 char *ptr = reinterpret_cast<char*>(calloc(1, alloc_len));
90 for (size_t i = 0; i < alloc_len; i++) {
91 ASSERT_EQ(0, ptr[i]);
92 }
93 free(ptr);
94 mallopt(M_THREAD_DISABLE_MEM_INIT, 0);
95#else
96 GTEST_SKIP() << "bionic-only test";
97#endif
98}
99
Christopher Ferrisa4037802014-06-09 19:14:11 -0700100TEST(malloc, calloc_illegal) {
Evgenii Stepanovacd6f4f2018-11-06 16:48:27 -0800101 SKIP_WITH_HWASAN;
Christopher Ferrisa4037802014-06-09 19:14:11 -0700102 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -0700103 ASSERT_EQ(nullptr, calloc(-1, 100));
Elliott Hughes95646e62023-09-21 14:11:19 -0700104 ASSERT_ERRNO(ENOMEM);
Christopher Ferrisa4037802014-06-09 19:14:11 -0700105}
106
107TEST(malloc, calloc_overflow) {
Evgenii Stepanovacd6f4f2018-11-06 16:48:27 -0800108 SKIP_WITH_HWASAN;
Christopher Ferrisa4037802014-06-09 19:14:11 -0700109 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -0700110 ASSERT_EQ(nullptr, calloc(1, SIZE_MAX));
Elliott Hughes95646e62023-09-21 14:11:19 -0700111 ASSERT_ERRNO(ENOMEM);
Christopher Ferrisa4037802014-06-09 19:14:11 -0700112 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -0700113 ASSERT_EQ(nullptr, calloc(SIZE_MAX, SIZE_MAX));
Elliott Hughes95646e62023-09-21 14:11:19 -0700114 ASSERT_ERRNO(ENOMEM);
Christopher Ferrisa4037802014-06-09 19:14:11 -0700115 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -0700116 ASSERT_EQ(nullptr, calloc(2, SIZE_MAX));
Elliott Hughes95646e62023-09-21 14:11:19 -0700117 ASSERT_ERRNO(ENOMEM);
Christopher Ferrisa4037802014-06-09 19:14:11 -0700118 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -0700119 ASSERT_EQ(nullptr, calloc(SIZE_MAX, 2));
Elliott Hughes95646e62023-09-21 14:11:19 -0700120 ASSERT_ERRNO(ENOMEM);
Christopher Ferrisa4037802014-06-09 19:14:11 -0700121}
122
Christopher Ferrisa4037802014-06-09 19:14:11 -0700123TEST(malloc, memalign_overflow) {
Evgenii Stepanovacd6f4f2018-11-06 16:48:27 -0800124 SKIP_WITH_HWASAN;
Yi Kong32bc0fc2018-08-02 17:31:13 -0700125 ASSERT_EQ(nullptr, memalign(4096, SIZE_MAX));
Christopher Ferrisa4037802014-06-09 19:14:11 -0700126}
127
128TEST(malloc, memalign_non_power2) {
Evgenii Stepanovacd6f4f2018-11-06 16:48:27 -0800129 SKIP_WITH_HWASAN;
Christopher Ferrisa4037802014-06-09 19:14:11 -0700130 void* ptr;
131 for (size_t align = 0; align <= 256; align++) {
132 ptr = memalign(align, 1024);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700133 ASSERT_TRUE(ptr != nullptr) << "Failed at align " << align;
Christopher Ferrisa4037802014-06-09 19:14:11 -0700134 free(ptr);
135 }
136}
137
Christopher Ferrisa4037802014-06-09 19:14:11 -0700138TEST(malloc, realloc_overflow) {
Evgenii Stepanovacd6f4f2018-11-06 16:48:27 -0800139 SKIP_WITH_HWASAN;
Christopher Ferrisa4037802014-06-09 19:14:11 -0700140 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -0700141 ASSERT_EQ(nullptr, realloc(nullptr, SIZE_MAX));
Elliott Hughes95646e62023-09-21 14:11:19 -0700142 ASSERT_ERRNO(ENOMEM);
Christopher Ferrisa4037802014-06-09 19:14:11 -0700143 void* ptr = malloc(100);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700144 ASSERT_TRUE(ptr != nullptr);
Christopher Ferrisa4037802014-06-09 19:14:11 -0700145 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -0700146 ASSERT_EQ(nullptr, realloc(ptr, SIZE_MAX));
Elliott Hughes95646e62023-09-21 14:11:19 -0700147 ASSERT_ERRNO(ENOMEM);
Christopher Ferrisa4037802014-06-09 19:14:11 -0700148 free(ptr);
Christopher Ferris72bbd422014-05-08 11:14:03 -0700149}
150
Dan Alberte5fdaa42014-06-14 01:04:31 +0000151#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
152extern "C" void* pvalloc(size_t);
153extern "C" void* valloc(size_t);
Christopher Ferris804cebe2019-06-20 08:50:23 -0700154#endif
Dan Alberte5fdaa42014-06-14 01:04:31 +0000155
Christopher Ferrisa4037802014-06-09 19:14:11 -0700156TEST(malloc, pvalloc_overflow) {
Christopher Ferris804cebe2019-06-20 08:50:23 -0700157#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
Yi Kong32bc0fc2018-08-02 17:31:13 -0700158 ASSERT_EQ(nullptr, pvalloc(SIZE_MAX));
Christopher Ferris804cebe2019-06-20 08:50:23 -0700159#else
160 GTEST_SKIP() << "pvalloc not supported.";
161#endif
Christopher Ferrisa4037802014-06-09 19:14:11 -0700162}
163
164TEST(malloc, valloc_std) {
Christopher Ferris804cebe2019-06-20 08:50:23 -0700165#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
Christopher Ferrisa4037802014-06-09 19:14:11 -0700166 size_t pagesize = sysconf(_SC_PAGESIZE);
Christopher Ferrisd5ab0a52019-06-19 12:03:57 -0700167 void* ptr = valloc(100);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700168 ASSERT_TRUE(ptr != nullptr);
Christopher Ferrisa4037802014-06-09 19:14:11 -0700169 ASSERT_TRUE((reinterpret_cast<uintptr_t>(ptr) & (pagesize-1)) == 0);
170 free(ptr);
Christopher Ferris804cebe2019-06-20 08:50:23 -0700171#else
172 GTEST_SKIP() << "valloc not supported.";
173#endif
Christopher Ferrisa4037802014-06-09 19:14:11 -0700174}
175
176TEST(malloc, valloc_overflow) {
Christopher Ferris804cebe2019-06-20 08:50:23 -0700177#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
Yi Kong32bc0fc2018-08-02 17:31:13 -0700178 ASSERT_EQ(nullptr, valloc(SIZE_MAX));
Christopher Ferris804cebe2019-06-20 08:50:23 -0700179#else
180 GTEST_SKIP() << "valloc not supported.";
Dan Alberte5fdaa42014-06-14 01:04:31 +0000181#endif
Christopher Ferris804cebe2019-06-20 08:50:23 -0700182}
Dan Albert4caa1f02014-08-20 09:16:57 -0700183
184TEST(malloc, malloc_info) {
185#ifdef __BIONIC__
Evgenii Stepanov8de6b462019-03-22 13:22:28 -0700186 SKIP_WITH_HWASAN; // hwasan does not implement malloc_info
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800187
188 TemporaryFile tf;
189 ASSERT_TRUE(tf.fd != -1);
190 FILE* fp = fdopen(tf.fd, "w+");
191 tf.release();
192 ASSERT_TRUE(fp != nullptr);
193 ASSERT_EQ(0, malloc_info(0, fp));
194 ASSERT_EQ(0, fclose(fp));
195
196 std::string contents;
197 ASSERT_TRUE(android::base::ReadFileToString(tf.path, &contents));
Dan Albert4caa1f02014-08-20 09:16:57 -0700198
199 tinyxml2::XMLDocument doc;
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800200 ASSERT_EQ(tinyxml2::XML_SUCCESS, doc.Parse(contents.c_str()));
Dan Albert4caa1f02014-08-20 09:16:57 -0700201
202 auto root = doc.FirstChildElement();
203 ASSERT_NE(nullptr, root);
204 ASSERT_STREQ("malloc", root->Name());
Christopher Ferris85169652019-10-09 18:41:55 -0700205 std::string version(root->Attribute("version"));
206 if (version == "jemalloc-1") {
Christopher Ferris6c619a02019-03-01 17:59:51 -0800207 auto arena = root->FirstChildElement();
208 for (; arena != nullptr; arena = arena->NextSiblingElement()) {
209 int val;
Dan Albert4caa1f02014-08-20 09:16:57 -0700210
Christopher Ferris6c619a02019-03-01 17:59:51 -0800211 ASSERT_STREQ("heap", arena->Name());
212 ASSERT_EQ(tinyxml2::XML_SUCCESS, arena->QueryIntAttribute("nr", &val));
213 ASSERT_EQ(tinyxml2::XML_SUCCESS,
214 arena->FirstChildElement("allocated-large")->QueryIntText(&val));
215 ASSERT_EQ(tinyxml2::XML_SUCCESS,
216 arena->FirstChildElement("allocated-huge")->QueryIntText(&val));
217 ASSERT_EQ(tinyxml2::XML_SUCCESS,
218 arena->FirstChildElement("allocated-bins")->QueryIntText(&val));
219 ASSERT_EQ(tinyxml2::XML_SUCCESS,
220 arena->FirstChildElement("bins-total")->QueryIntText(&val));
Dan Albert4caa1f02014-08-20 09:16:57 -0700221
Christopher Ferris6c619a02019-03-01 17:59:51 -0800222 auto bin = arena->FirstChildElement("bin");
223 for (; bin != nullptr; bin = bin ->NextSiblingElement()) {
224 if (strcmp(bin->Name(), "bin") == 0) {
225 ASSERT_EQ(tinyxml2::XML_SUCCESS, bin->QueryIntAttribute("nr", &val));
226 ASSERT_EQ(tinyxml2::XML_SUCCESS,
227 bin->FirstChildElement("allocated")->QueryIntText(&val));
228 ASSERT_EQ(tinyxml2::XML_SUCCESS,
229 bin->FirstChildElement("nmalloc")->QueryIntText(&val));
230 ASSERT_EQ(tinyxml2::XML_SUCCESS,
231 bin->FirstChildElement("ndalloc")->QueryIntText(&val));
232 }
Dan Albert4caa1f02014-08-20 09:16:57 -0700233 }
234 }
Christopher Ferriscce88c02020-02-12 17:41:01 -0800235 } else if (version == "scudo-1") {
236 auto element = root->FirstChildElement();
237 for (; element != nullptr; element = element->NextSiblingElement()) {
238 int val;
239
240 ASSERT_STREQ("alloc", element->Name());
241 ASSERT_EQ(tinyxml2::XML_SUCCESS, element->QueryIntAttribute("size", &val));
242 ASSERT_EQ(tinyxml2::XML_SUCCESS, element->QueryIntAttribute("count", &val));
243 }
Christopher Ferris6c619a02019-03-01 17:59:51 -0800244 } else {
Christopher Ferriscce88c02020-02-12 17:41:01 -0800245 // Do not verify output for debug malloc.
246 ASSERT_TRUE(version == "debug-malloc-1") << "Unknown version: " << version;
Dan Albert4caa1f02014-08-20 09:16:57 -0700247 }
Christopher Ferris9eb3f1f2024-12-09 23:07:14 +0000248 printf("Allocator version: %s\n", version.c_str());
Dan Albert4caa1f02014-08-20 09:16:57 -0700249#endif
250}
Christopher Ferrisad33ebe2015-12-16 12:07:25 -0800251
Christopher Ferrisdb9706a2019-05-02 18:33:11 -0700252TEST(malloc, malloc_info_matches_mallinfo) {
253#ifdef __BIONIC__
254 SKIP_WITH_HWASAN; // hwasan does not implement malloc_info
255
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800256 TemporaryFile tf;
257 ASSERT_TRUE(tf.fd != -1);
258 FILE* fp = fdopen(tf.fd, "w+");
259 tf.release();
260 ASSERT_TRUE(fp != nullptr);
Christopher Ferrisdb9706a2019-05-02 18:33:11 -0700261 size_t mallinfo_before_allocated_bytes = mallinfo().uordblks;
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800262 ASSERT_EQ(0, malloc_info(0, fp));
Christopher Ferrisdb9706a2019-05-02 18:33:11 -0700263 size_t mallinfo_after_allocated_bytes = mallinfo().uordblks;
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800264 ASSERT_EQ(0, fclose(fp));
265
266 std::string contents;
267 ASSERT_TRUE(android::base::ReadFileToString(tf.path, &contents));
Christopher Ferrisdb9706a2019-05-02 18:33:11 -0700268
269 tinyxml2::XMLDocument doc;
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800270 ASSERT_EQ(tinyxml2::XML_SUCCESS, doc.Parse(contents.c_str()));
Christopher Ferrisdb9706a2019-05-02 18:33:11 -0700271
272 size_t total_allocated_bytes = 0;
273 auto root = doc.FirstChildElement();
274 ASSERT_NE(nullptr, root);
275 ASSERT_STREQ("malloc", root->Name());
Christopher Ferris85169652019-10-09 18:41:55 -0700276 std::string version(root->Attribute("version"));
277 if (version == "jemalloc-1") {
Christopher Ferrisdb9706a2019-05-02 18:33:11 -0700278 auto arena = root->FirstChildElement();
279 for (; arena != nullptr; arena = arena->NextSiblingElement()) {
280 int val;
281
282 ASSERT_STREQ("heap", arena->Name());
283 ASSERT_EQ(tinyxml2::XML_SUCCESS, arena->QueryIntAttribute("nr", &val));
284 ASSERT_EQ(tinyxml2::XML_SUCCESS,
285 arena->FirstChildElement("allocated-large")->QueryIntText(&val));
286 total_allocated_bytes += val;
287 ASSERT_EQ(tinyxml2::XML_SUCCESS,
288 arena->FirstChildElement("allocated-huge")->QueryIntText(&val));
289 total_allocated_bytes += val;
290 ASSERT_EQ(tinyxml2::XML_SUCCESS,
291 arena->FirstChildElement("allocated-bins")->QueryIntText(&val));
292 total_allocated_bytes += val;
293 ASSERT_EQ(tinyxml2::XML_SUCCESS,
294 arena->FirstChildElement("bins-total")->QueryIntText(&val));
295 }
296 // The total needs to be between the mallinfo call before and after
297 // since malloc_info allocates some memory.
298 EXPECT_LE(mallinfo_before_allocated_bytes, total_allocated_bytes);
299 EXPECT_GE(mallinfo_after_allocated_bytes, total_allocated_bytes);
Christopher Ferriscce88c02020-02-12 17:41:01 -0800300 } else if (version == "scudo-1") {
301 auto element = root->FirstChildElement();
302 for (; element != nullptr; element = element->NextSiblingElement()) {
303 ASSERT_STREQ("alloc", element->Name());
304 int size;
305 ASSERT_EQ(tinyxml2::XML_SUCCESS, element->QueryIntAttribute("size", &size));
306 int count;
307 ASSERT_EQ(tinyxml2::XML_SUCCESS, element->QueryIntAttribute("count", &count));
308 total_allocated_bytes += size * count;
309 }
310 // Scudo only gives the information on the primary, so simply make
311 // sure that the value is non-zero.
312 EXPECT_NE(0U, total_allocated_bytes);
Christopher Ferrisdb9706a2019-05-02 18:33:11 -0700313 } else {
Christopher Ferriscce88c02020-02-12 17:41:01 -0800314 // Do not verify output for debug malloc.
315 ASSERT_TRUE(version == "debug-malloc-1") << "Unknown version: " << version;
Christopher Ferrisdb9706a2019-05-02 18:33:11 -0700316 }
317#endif
318}
319
Elliott Hughes884f76e2016-02-10 20:43:22 -0800320TEST(malloc, malloc_0) {
321 void* p = malloc(0);
322 ASSERT_TRUE(p != nullptr);
323 free(p);
324}
325
326TEST(malloc, calloc_0_0) {
327 void* p = calloc(0, 0);
328 ASSERT_TRUE(p != nullptr);
329 free(p);
330}
331
332TEST(malloc, calloc_0_1) {
333 void* p = calloc(0, 1);
334 ASSERT_TRUE(p != nullptr);
335 free(p);
336}
337
338TEST(malloc, calloc_1_0) {
339 void* p = calloc(1, 0);
340 ASSERT_TRUE(p != nullptr);
341 free(p);
342}
343
344TEST(malloc, realloc_nullptr_0) {
345 // realloc(nullptr, size) is actually malloc(size).
346 void* p = realloc(nullptr, 0);
347 ASSERT_TRUE(p != nullptr);
348 free(p);
349}
350
351TEST(malloc, realloc_0) {
352 void* p = malloc(1024);
353 ASSERT_TRUE(p != nullptr);
354 // realloc(p, 0) is actually free(p).
355 void* p2 = realloc(p, 0);
356 ASSERT_TRUE(p2 == nullptr);
357}
Christopher Ferris72df6702016-02-11 15:51:31 -0800358
359constexpr size_t MAX_LOOPS = 200;
360
361// Make sure that memory returned by malloc is aligned to allow these data types.
362TEST(malloc, verify_alignment) {
363 uint32_t** values_32 = new uint32_t*[MAX_LOOPS];
364 uint64_t** values_64 = new uint64_t*[MAX_LOOPS];
365 long double** values_ldouble = new long double*[MAX_LOOPS];
366 // Use filler to attempt to force the allocator to get potentially bad alignments.
367 void** filler = new void*[MAX_LOOPS];
368
369 for (size_t i = 0; i < MAX_LOOPS; i++) {
370 // Check uint32_t pointers.
371 filler[i] = malloc(1);
372 ASSERT_TRUE(filler[i] != nullptr);
373
374 values_32[i] = reinterpret_cast<uint32_t*>(malloc(sizeof(uint32_t)));
375 ASSERT_TRUE(values_32[i] != nullptr);
376 *values_32[i] = i;
377 ASSERT_EQ(*values_32[i], i);
378 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(values_32[i]) & (sizeof(uint32_t) - 1));
379
380 free(filler[i]);
381 }
382
383 for (size_t i = 0; i < MAX_LOOPS; i++) {
384 // Check uint64_t pointers.
385 filler[i] = malloc(1);
386 ASSERT_TRUE(filler[i] != nullptr);
387
388 values_64[i] = reinterpret_cast<uint64_t*>(malloc(sizeof(uint64_t)));
389 ASSERT_TRUE(values_64[i] != nullptr);
390 *values_64[i] = 0x1000 + i;
391 ASSERT_EQ(*values_64[i], 0x1000 + i);
392 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(values_64[i]) & (sizeof(uint64_t) - 1));
393
394 free(filler[i]);
395 }
396
397 for (size_t i = 0; i < MAX_LOOPS; i++) {
398 // Check long double pointers.
399 filler[i] = malloc(1);
400 ASSERT_TRUE(filler[i] != nullptr);
401
402 values_ldouble[i] = reinterpret_cast<long double*>(malloc(sizeof(long double)));
403 ASSERT_TRUE(values_ldouble[i] != nullptr);
404 *values_ldouble[i] = 5.5 + i;
405 ASSERT_DOUBLE_EQ(*values_ldouble[i], 5.5 + i);
406 // 32 bit glibc has a long double size of 12 bytes, so hardcode the
407 // required alignment to 0x7.
408#if !defined(__BIONIC__) && !defined(__LP64__)
409 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(values_ldouble[i]) & 0x7);
410#else
411 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(values_ldouble[i]) & (sizeof(long double) - 1));
412#endif
413
414 free(filler[i]);
415 }
416
417 for (size_t i = 0; i < MAX_LOOPS; i++) {
418 free(values_32[i]);
419 free(values_64[i]);
420 free(values_ldouble[i]);
421 }
422
423 delete[] filler;
424 delete[] values_32;
425 delete[] values_64;
426 delete[] values_ldouble;
427}
Christopher Ferrisa1c0d2f2017-05-15 15:50:19 -0700428
429TEST(malloc, mallopt_smoke) {
Christopher Ferris2ef59372023-01-18 15:08:37 -0800430#if defined(__BIONIC__)
Christopher Ferrisa1c0d2f2017-05-15 15:50:19 -0700431 errno = 0;
432 ASSERT_EQ(0, mallopt(-1000, 1));
433 // mallopt doesn't set errno.
Elliott Hughes95646e62023-09-21 14:11:19 -0700434 ASSERT_ERRNO(0);
Colin Cross7da20342021-07-28 11:18:11 -0700435#else
Christopher Ferris2ef59372023-01-18 15:08:37 -0800436 GTEST_SKIP() << "bionic-only test";
Colin Cross7da20342021-07-28 11:18:11 -0700437#endif
Christopher Ferrisa1c0d2f2017-05-15 15:50:19 -0700438}
Elliott Hughesb1770852018-09-18 12:52:42 -0700439
Christopher Ferrisaf1b8dd2018-11-07 15:28:16 -0800440TEST(malloc, mallopt_decay) {
441#if defined(__BIONIC__)
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800442 SKIP_WITH_HWASAN << "hwasan does not implement mallopt";
Chia-hung Duan6abb4062024-04-17 19:08:48 -0700443 ASSERT_EQ(1, mallopt(M_DECAY_TIME, -1));
Christopher Ferrisaf1b8dd2018-11-07 15:28:16 -0800444 ASSERT_EQ(1, mallopt(M_DECAY_TIME, 1));
445 ASSERT_EQ(1, mallopt(M_DECAY_TIME, 0));
446 ASSERT_EQ(1, mallopt(M_DECAY_TIME, 1));
447 ASSERT_EQ(1, mallopt(M_DECAY_TIME, 0));
Chia-hung Duan6abb4062024-04-17 19:08:48 -0700448 ASSERT_EQ(1, mallopt(M_DECAY_TIME, -1));
Christopher Ferrisaf1b8dd2018-11-07 15:28:16 -0800449#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800450 GTEST_SKIP() << "bionic-only test";
Christopher Ferrisaf1b8dd2018-11-07 15:28:16 -0800451#endif
452}
453
454TEST(malloc, mallopt_purge) {
455#if defined(__BIONIC__)
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800456 SKIP_WITH_HWASAN << "hwasan does not implement mallopt";
Christopher Ferrisaf1b8dd2018-11-07 15:28:16 -0800457 ASSERT_EQ(1, mallopt(M_PURGE, 0));
458#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800459 GTEST_SKIP() << "bionic-only test";
Christopher Ferrisaf1b8dd2018-11-07 15:28:16 -0800460#endif
461}
462
Christopher Ferrisd86eb862023-02-28 12:45:54 -0800463TEST(malloc, mallopt_purge_all) {
464#if defined(__BIONIC__)
465 SKIP_WITH_HWASAN << "hwasan does not implement mallopt";
Christopher Ferrisd86eb862023-02-28 12:45:54 -0800466 ASSERT_EQ(1, mallopt(M_PURGE_ALL, 0));
467#else
468 GTEST_SKIP() << "bionic-only test";
469#endif
470}
471
Christopher Ferrise9a7b812023-05-11 15:36:27 -0700472TEST(malloc, mallopt_log_stats) {
473#if defined(__BIONIC__)
474 SKIP_WITH_HWASAN << "hwasan does not implement mallopt";
475 ASSERT_EQ(1, mallopt(M_LOG_STATS, 0));
476#else
477 GTEST_SKIP() << "bionic-only test";
478#endif
479}
480
Christopher Ferrisd86eb862023-02-28 12:45:54 -0800481// Verify that all of the mallopt values are unique.
482TEST(malloc, mallopt_unique_params) {
483#if defined(__BIONIC__)
484 std::vector<std::pair<int, std::string>> params{
485 std::make_pair(M_DECAY_TIME, "M_DECAY_TIME"),
486 std::make_pair(M_PURGE, "M_PURGE"),
487 std::make_pair(M_PURGE_ALL, "M_PURGE_ALL"),
488 std::make_pair(M_MEMTAG_TUNING, "M_MEMTAG_TUNING"),
489 std::make_pair(M_THREAD_DISABLE_MEM_INIT, "M_THREAD_DISABLE_MEM_INIT"),
490 std::make_pair(M_CACHE_COUNT_MAX, "M_CACHE_COUNT_MAX"),
491 std::make_pair(M_CACHE_SIZE_MAX, "M_CACHE_SIZE_MAX"),
492 std::make_pair(M_TSDS_COUNT_MAX, "M_TSDS_COUNT_MAX"),
493 std::make_pair(M_BIONIC_ZERO_INIT, "M_BIONIC_ZERO_INIT"),
494 std::make_pair(M_BIONIC_SET_HEAP_TAGGING_LEVEL, "M_BIONIC_SET_HEAP_TAGGING_LEVEL"),
Christopher Ferrise9a7b812023-05-11 15:36:27 -0700495 std::make_pair(M_LOG_STATS, "M_LOG_STATS"),
Christopher Ferrisd86eb862023-02-28 12:45:54 -0800496 };
497
498 std::unordered_map<int, std::string> all_params;
499 for (const auto& param : params) {
500 EXPECT_TRUE(all_params.count(param.first) == 0)
501 << "mallopt params " << all_params[param.first] << " and " << param.second
502 << " have the same value " << param.first;
503 all_params.insert(param);
504 }
505#else
506 GTEST_SKIP() << "bionic-only test";
507#endif
508}
509
Christopher Ferris88448792020-07-28 14:15:31 -0700510#if defined(__BIONIC__)
511static void GetAllocatorVersion(bool* allocator_scudo) {
512 TemporaryFile tf;
513 ASSERT_TRUE(tf.fd != -1);
514 FILE* fp = fdopen(tf.fd, "w+");
515 tf.release();
516 ASSERT_TRUE(fp != nullptr);
Evgenii Stepanov4edbcee2021-09-17 14:59:15 -0700517 if (malloc_info(0, fp) != 0) {
518 *allocator_scudo = false;
519 return;
520 }
Christopher Ferris88448792020-07-28 14:15:31 -0700521 ASSERT_EQ(0, fclose(fp));
522
523 std::string contents;
524 ASSERT_TRUE(android::base::ReadFileToString(tf.path, &contents));
525
526 tinyxml2::XMLDocument doc;
527 ASSERT_EQ(tinyxml2::XML_SUCCESS, doc.Parse(contents.c_str()));
528
529 auto root = doc.FirstChildElement();
530 ASSERT_NE(nullptr, root);
531 ASSERT_STREQ("malloc", root->Name());
532 std::string version(root->Attribute("version"));
533 *allocator_scudo = (version == "scudo-1");
534}
535#endif
536
537TEST(malloc, mallopt_scudo_only_options) {
538#if defined(__BIONIC__)
539 SKIP_WITH_HWASAN << "hwasan does not implement mallopt";
540 bool allocator_scudo;
541 GetAllocatorVersion(&allocator_scudo);
542 if (!allocator_scudo) {
543 GTEST_SKIP() << "scudo allocator only test";
544 }
545 ASSERT_EQ(1, mallopt(M_CACHE_COUNT_MAX, 100));
546 ASSERT_EQ(1, mallopt(M_CACHE_SIZE_MAX, 1024 * 1024 * 2));
547 ASSERT_EQ(1, mallopt(M_TSDS_COUNT_MAX, 8));
548#else
549 GTEST_SKIP() << "bionic-only test";
550#endif
551}
552
Elliott Hughesb1770852018-09-18 12:52:42 -0700553TEST(malloc, reallocarray_overflow) {
554#if HAVE_REALLOCARRAY
555 // Values that cause overflow to a result small enough (8 on LP64) that malloc would "succeed".
556 size_t a = static_cast<size_t>(INTPTR_MIN + 4);
557 size_t b = 2;
558
559 errno = 0;
560 ASSERT_TRUE(reallocarray(nullptr, a, b) == nullptr);
Elliott Hughes95646e62023-09-21 14:11:19 -0700561 ASSERT_ERRNO(ENOMEM);
Elliott Hughesb1770852018-09-18 12:52:42 -0700562
563 errno = 0;
564 ASSERT_TRUE(reallocarray(nullptr, b, a) == nullptr);
Elliott Hughes95646e62023-09-21 14:11:19 -0700565 ASSERT_ERRNO(ENOMEM);
Elliott Hughesb1770852018-09-18 12:52:42 -0700566#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800567 GTEST_SKIP() << "reallocarray not available";
Elliott Hughesb1770852018-09-18 12:52:42 -0700568#endif
569}
570
Christopher Ferrisf32494c2020-01-08 14:19:10 -0800571template <typename Type>
572void __attribute__((optnone)) VerifyAlignment(Type* floating) {
573 size_t expected_alignment = alignof(Type);
574 if (expected_alignment != 0) {
575 ASSERT_EQ(0U, (expected_alignment - 1) & reinterpret_cast<uintptr_t>(floating))
Ryan Prichardf40f2582024-01-09 16:29:20 -0800576 << "Expected alignment " << expected_alignment << " ptr value "
577 << static_cast<void*>(floating);
Christopher Ferrisf32494c2020-01-08 14:19:10 -0800578 }
579}
580
581template <typename Type>
582void __attribute__((optnone)) TestAllocateType() {
583 // The number of allocations to do in a row. This is to attempt to
584 // expose the worst case alignment for native allocators that use
585 // bins.
586 static constexpr size_t kMaxConsecutiveAllocs = 100;
587
588 // Verify using new directly.
589 Type* types[kMaxConsecutiveAllocs];
590 for (size_t i = 0; i < kMaxConsecutiveAllocs; i++) {
591 types[i] = new Type;
592 VerifyAlignment(types[i]);
593 if (::testing::Test::HasFatalFailure()) {
594 return;
595 }
596 }
597 for (size_t i = 0; i < kMaxConsecutiveAllocs; i++) {
598 delete types[i];
599 }
600
601 // Verify using malloc.
602 for (size_t i = 0; i < kMaxConsecutiveAllocs; i++) {
603 types[i] = reinterpret_cast<Type*>(malloc(sizeof(Type)));
604 ASSERT_TRUE(types[i] != nullptr);
605 VerifyAlignment(types[i]);
606 if (::testing::Test::HasFatalFailure()) {
607 return;
608 }
609 }
610 for (size_t i = 0; i < kMaxConsecutiveAllocs; i++) {
611 free(types[i]);
612 }
613
614 // Verify using a vector.
615 std::vector<Type> type_vector(kMaxConsecutiveAllocs);
616 for (size_t i = 0; i < type_vector.size(); i++) {
617 VerifyAlignment(&type_vector[i]);
618 if (::testing::Test::HasFatalFailure()) {
619 return;
620 }
621 }
622}
623
624#if defined(__ANDROID__)
625static void __attribute__((optnone)) AndroidVerifyAlignment(size_t alloc_size, size_t aligned_bytes) {
626 void* ptrs[100];
627 uintptr_t mask = aligned_bytes - 1;
628 for (size_t i = 0; i < sizeof(ptrs) / sizeof(void*); i++) {
629 ptrs[i] = malloc(alloc_size);
630 ASSERT_TRUE(ptrs[i] != nullptr);
631 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(ptrs[i]) & mask)
632 << "Expected at least " << aligned_bytes << " byte alignment: size "
633 << alloc_size << " actual ptr " << ptrs[i];
634 }
635}
636#endif
637
Christopher Ferrisb3cac0f2021-09-21 10:32:40 -0700638void AlignCheck() {
Christopher Ferrisf32494c2020-01-08 14:19:10 -0800639 // See http://www.open-std.org/jtc1/sc22/wg14/www/docs/summary.htm#dr_445
640 // for a discussion of type alignment.
641 ASSERT_NO_FATAL_FAILURE(TestAllocateType<float>());
642 ASSERT_NO_FATAL_FAILURE(TestAllocateType<double>());
643 ASSERT_NO_FATAL_FAILURE(TestAllocateType<long double>());
644
645 ASSERT_NO_FATAL_FAILURE(TestAllocateType<char>());
646 ASSERT_NO_FATAL_FAILURE(TestAllocateType<char16_t>());
647 ASSERT_NO_FATAL_FAILURE(TestAllocateType<char32_t>());
648 ASSERT_NO_FATAL_FAILURE(TestAllocateType<wchar_t>());
649 ASSERT_NO_FATAL_FAILURE(TestAllocateType<signed char>());
650 ASSERT_NO_FATAL_FAILURE(TestAllocateType<short int>());
651 ASSERT_NO_FATAL_FAILURE(TestAllocateType<int>());
652 ASSERT_NO_FATAL_FAILURE(TestAllocateType<long int>());
653 ASSERT_NO_FATAL_FAILURE(TestAllocateType<long long int>());
654 ASSERT_NO_FATAL_FAILURE(TestAllocateType<unsigned char>());
655 ASSERT_NO_FATAL_FAILURE(TestAllocateType<unsigned short int>());
656 ASSERT_NO_FATAL_FAILURE(TestAllocateType<unsigned int>());
657 ASSERT_NO_FATAL_FAILURE(TestAllocateType<unsigned long int>());
658 ASSERT_NO_FATAL_FAILURE(TestAllocateType<unsigned long long int>());
659
660#if defined(__ANDROID__)
661 // On Android, there is a lot of code that expects certain alignments:
Christopher Ferrisb3cac0f2021-09-21 10:32:40 -0700662 // 1. Allocations of a size that rounds up to a multiple of 16 bytes
663 // must have at least 16 byte alignment.
664 // 2. Allocations of a size that rounds up to a multiple of 8 bytes and
665 // not 16 bytes, are only required to have at least 8 byte alignment.
666 // In addition, on Android clang has been configured for 64 bit such that:
667 // 3. Allocations <= 8 bytes must be aligned to at least 8 bytes.
668 // 4. Allocations > 8 bytes must be aligned to at least 16 bytes.
669 // For 32 bit environments, only the first two requirements must be met.
Christopher Ferrisf32494c2020-01-08 14:19:10 -0800670
671 // See http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2293.htm for
672 // a discussion of this alignment mess. The code below is enforcing
673 // strong-alignment, since who knows what code depends on this behavior now.
Christopher Ferrisb3cac0f2021-09-21 10:32:40 -0700674 // As mentioned before, for 64 bit this will enforce the higher
675 // requirement since clang expects this behavior on Android now.
Christopher Ferrisf32494c2020-01-08 14:19:10 -0800676 for (size_t i = 1; i <= 128; i++) {
Christopher Ferrisb3cac0f2021-09-21 10:32:40 -0700677#if defined(__LP64__)
678 if (i <= 8) {
679 AndroidVerifyAlignment(i, 8);
680 } else {
681 AndroidVerifyAlignment(i, 16);
682 }
683#else
Christopher Ferrisf32494c2020-01-08 14:19:10 -0800684 size_t rounded = (i + 7) & ~7;
685 if ((rounded % 16) == 0) {
686 AndroidVerifyAlignment(i, 16);
687 } else {
688 AndroidVerifyAlignment(i, 8);
689 }
Christopher Ferrisb3cac0f2021-09-21 10:32:40 -0700690#endif
Christopher Ferrisf32494c2020-01-08 14:19:10 -0800691 if (::testing::Test::HasFatalFailure()) {
692 return;
693 }
694 }
695#endif
696}
697
Christopher Ferrisb3cac0f2021-09-21 10:32:40 -0700698TEST(malloc, align_check) {
699 AlignCheck();
700}
701
Christopher Ferrise4cdbc42019-02-08 17:30:58 -0800702bool IsDynamic() {
703#if defined(__LP64__)
704 Elf64_Ehdr ehdr;
705#else
706 Elf32_Ehdr ehdr;
707#endif
708 std::string path(android::base::GetExecutablePath());
709
710 int fd = open(path.c_str(), O_RDONLY | O_CLOEXEC);
711 if (fd == -1) {
712 // Assume dynamic on error.
713 return true;
714 }
715 bool read_completed = android::base::ReadFully(fd, &ehdr, sizeof(ehdr));
716 close(fd);
717 // Assume dynamic in error cases.
718 return !read_completed || ehdr.e_type == ET_DYN;
719}
720
Ryan Savitskiecc37e32018-12-14 15:57:21 +0000721TEST(android_mallopt, init_zygote_child_profiling) {
722#if defined(__BIONIC__)
723 // Successful call.
724 errno = 0;
Christopher Ferrise4cdbc42019-02-08 17:30:58 -0800725 if (IsDynamic()) {
726 EXPECT_EQ(true, android_mallopt(M_INIT_ZYGOTE_CHILD_PROFILING, nullptr, 0));
Elliott Hughes95646e62023-09-21 14:11:19 -0700727 EXPECT_ERRNO(0);
Christopher Ferrise4cdbc42019-02-08 17:30:58 -0800728 } else {
729 // Not supported in static executables.
730 EXPECT_EQ(false, android_mallopt(M_INIT_ZYGOTE_CHILD_PROFILING, nullptr, 0));
Elliott Hughes95646e62023-09-21 14:11:19 -0700731 EXPECT_ERRNO(ENOTSUP);
Christopher Ferrise4cdbc42019-02-08 17:30:58 -0800732 }
Ryan Savitskiecc37e32018-12-14 15:57:21 +0000733
734 // Unexpected arguments rejected.
735 errno = 0;
736 char unexpected = 0;
737 EXPECT_EQ(false, android_mallopt(M_INIT_ZYGOTE_CHILD_PROFILING, &unexpected, 1));
Christopher Ferrise4cdbc42019-02-08 17:30:58 -0800738 if (IsDynamic()) {
Elliott Hughes95646e62023-09-21 14:11:19 -0700739 EXPECT_ERRNO(EINVAL);
Christopher Ferrise4cdbc42019-02-08 17:30:58 -0800740 } else {
Elliott Hughes95646e62023-09-21 14:11:19 -0700741 EXPECT_ERRNO(ENOTSUP);
Christopher Ferrise4cdbc42019-02-08 17:30:58 -0800742 }
Ryan Savitskiecc37e32018-12-14 15:57:21 +0000743#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800744 GTEST_SKIP() << "bionic-only test";
Ryan Savitskiecc37e32018-12-14 15:57:21 +0000745#endif
746}
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -0800747
748#if defined(__BIONIC__)
749template <typename FuncType>
750void CheckAllocationFunction(FuncType func) {
751 // Assumes that no more than 108MB of memory is allocated before this.
752 size_t limit = 128 * 1024 * 1024;
753 ASSERT_TRUE(android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit)));
754 if (!func(20 * 1024 * 1024))
755 exit(1);
756 if (func(128 * 1024 * 1024))
757 exit(1);
758 exit(0);
759}
760#endif
761
762TEST(android_mallopt, set_allocation_limit) {
763#if defined(__BIONIC__)
764 EXPECT_EXIT(CheckAllocationFunction([](size_t bytes) { return calloc(bytes, 1) != nullptr; }),
765 testing::ExitedWithCode(0), "");
766 EXPECT_EXIT(CheckAllocationFunction([](size_t bytes) { return calloc(1, bytes) != nullptr; }),
767 testing::ExitedWithCode(0), "");
768 EXPECT_EXIT(CheckAllocationFunction([](size_t bytes) { return malloc(bytes) != nullptr; }),
769 testing::ExitedWithCode(0), "");
770 EXPECT_EXIT(CheckAllocationFunction(
771 [](size_t bytes) { return memalign(sizeof(void*), bytes) != nullptr; }),
772 testing::ExitedWithCode(0), "");
773 EXPECT_EXIT(CheckAllocationFunction([](size_t bytes) {
774 void* ptr;
775 return posix_memalign(&ptr, sizeof(void *), bytes) == 0;
776 }),
777 testing::ExitedWithCode(0), "");
778 EXPECT_EXIT(CheckAllocationFunction(
779 [](size_t bytes) { return aligned_alloc(sizeof(void*), bytes) != nullptr; }),
780 testing::ExitedWithCode(0), "");
781 EXPECT_EXIT(CheckAllocationFunction([](size_t bytes) {
782 void* p = malloc(1024 * 1024);
783 return realloc(p, bytes) != nullptr;
784 }),
785 testing::ExitedWithCode(0), "");
786#if !defined(__LP64__)
787 EXPECT_EXIT(CheckAllocationFunction([](size_t bytes) { return pvalloc(bytes) != nullptr; }),
788 testing::ExitedWithCode(0), "");
789 EXPECT_EXIT(CheckAllocationFunction([](size_t bytes) { return valloc(bytes) != nullptr; }),
790 testing::ExitedWithCode(0), "");
791#endif
792#else
Elliott Hughes10907202019-03-27 08:51:02 -0700793 GTEST_SKIP() << "bionic extension";
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -0800794#endif
795}
796
797TEST(android_mallopt, set_allocation_limit_multiple) {
798#if defined(__BIONIC__)
799 // Only the first set should work.
800 size_t limit = 256 * 1024 * 1024;
801 ASSERT_TRUE(android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit)));
802 limit = 32 * 1024 * 1024;
803 ASSERT_FALSE(android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit)));
804#else
Elliott Hughes10907202019-03-27 08:51:02 -0700805 GTEST_SKIP() << "bionic extension";
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -0800806#endif
807}
808
809#if defined(__BIONIC__)
810static constexpr size_t kAllocationSize = 8 * 1024 * 1024;
811
812static size_t GetMaxAllocations() {
813 size_t max_pointers = 0;
814 void* ptrs[20];
815 for (size_t i = 0; i < sizeof(ptrs) / sizeof(void*); i++) {
816 ptrs[i] = malloc(kAllocationSize);
817 if (ptrs[i] == nullptr) {
818 max_pointers = i;
819 break;
820 }
821 }
822 for (size_t i = 0; i < max_pointers; i++) {
823 free(ptrs[i]);
824 }
825 return max_pointers;
826}
827
828static void VerifyMaxPointers(size_t max_pointers) {
829 // Now verify that we can allocate the same number as before.
830 void* ptrs[20];
831 for (size_t i = 0; i < max_pointers; i++) {
832 ptrs[i] = malloc(kAllocationSize);
833 ASSERT_TRUE(ptrs[i] != nullptr) << "Failed to allocate on iteration " << i;
834 }
835
836 // Make sure the next allocation still fails.
837 ASSERT_TRUE(malloc(kAllocationSize) == nullptr);
838 for (size_t i = 0; i < max_pointers; i++) {
839 free(ptrs[i]);
840 }
841}
842#endif
843
844TEST(android_mallopt, set_allocation_limit_realloc_increase) {
845#if defined(__BIONIC__)
846 size_t limit = 128 * 1024 * 1024;
847 ASSERT_TRUE(android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit)));
848
849 size_t max_pointers = GetMaxAllocations();
850 ASSERT_TRUE(max_pointers != 0) << "Limit never reached.";
851
852 void* memory = malloc(10 * 1024 * 1024);
853 ASSERT_TRUE(memory != nullptr);
854
855 // Increase size.
856 memory = realloc(memory, 20 * 1024 * 1024);
857 ASSERT_TRUE(memory != nullptr);
858 memory = realloc(memory, 40 * 1024 * 1024);
859 ASSERT_TRUE(memory != nullptr);
860 memory = realloc(memory, 60 * 1024 * 1024);
861 ASSERT_TRUE(memory != nullptr);
862 memory = realloc(memory, 80 * 1024 * 1024);
863 ASSERT_TRUE(memory != nullptr);
864 // Now push past limit.
865 memory = realloc(memory, 130 * 1024 * 1024);
866 ASSERT_TRUE(memory == nullptr);
867
868 VerifyMaxPointers(max_pointers);
869#else
Elliott Hughes10907202019-03-27 08:51:02 -0700870 GTEST_SKIP() << "bionic extension";
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -0800871#endif
872}
873
874TEST(android_mallopt, set_allocation_limit_realloc_decrease) {
875#if defined(__BIONIC__)
876 size_t limit = 100 * 1024 * 1024;
877 ASSERT_TRUE(android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit)));
878
879 size_t max_pointers = GetMaxAllocations();
880 ASSERT_TRUE(max_pointers != 0) << "Limit never reached.";
881
882 void* memory = malloc(80 * 1024 * 1024);
883 ASSERT_TRUE(memory != nullptr);
884
885 // Decrease size.
886 memory = realloc(memory, 60 * 1024 * 1024);
887 ASSERT_TRUE(memory != nullptr);
888 memory = realloc(memory, 40 * 1024 * 1024);
889 ASSERT_TRUE(memory != nullptr);
890 memory = realloc(memory, 20 * 1024 * 1024);
891 ASSERT_TRUE(memory != nullptr);
892 memory = realloc(memory, 10 * 1024 * 1024);
893 ASSERT_TRUE(memory != nullptr);
894 free(memory);
895
896 VerifyMaxPointers(max_pointers);
897#else
Elliott Hughes10907202019-03-27 08:51:02 -0700898 GTEST_SKIP() << "bionic extension";
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -0800899#endif
900}
901
902TEST(android_mallopt, set_allocation_limit_realloc_free) {
903#if defined(__BIONIC__)
904 size_t limit = 100 * 1024 * 1024;
905 ASSERT_TRUE(android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit)));
906
907 size_t max_pointers = GetMaxAllocations();
908 ASSERT_TRUE(max_pointers != 0) << "Limit never reached.";
909
910 void* memory = malloc(60 * 1024 * 1024);
911 ASSERT_TRUE(memory != nullptr);
912
913 memory = realloc(memory, 0);
914 ASSERT_TRUE(memory == nullptr);
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
922#if defined(__BIONIC__)
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -0800923static void SetAllocationLimitMultipleThreads() {
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -0800924 static constexpr size_t kNumThreads = 4;
Christopher Ferrisfe130412023-07-20 16:37:43 -0700925 std::atomic_bool start_running = false;
926 std::atomic<size_t> num_running;
927 std::atomic<size_t> num_successful;
928 std::unique_ptr<std::thread> threads[kNumThreads];
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -0800929 for (size_t i = 0; i < kNumThreads; i++) {
Christopher Ferrisfe130412023-07-20 16:37:43 -0700930 threads[i].reset(new std::thread([&num_running, &start_running, &num_successful] {
931 ++num_running;
932 while (!start_running) {
933 }
934 size_t limit = 500 * 1024 * 1024;
935 if (android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit))) {
936 ++num_successful;
937 }
938 }));
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -0800939 }
940
Christopher Ferrisfe130412023-07-20 16:37:43 -0700941 // Wait until all of the threads have started.
942 while (num_running != kNumThreads)
943 ;
944
945 // Now start all of the threads setting the mallopt at once.
946 start_running = true;
947
Ryan Savitski175c8862020-01-02 19:54:57 +0000948 // Send hardcoded signal (BIONIC_SIGNAL_PROFILER with value 0) to trigger
Christopher Ferrisfe130412023-07-20 16:37:43 -0700949 // heapprofd handler. This will verify that changing the limit while
950 // the allocation handlers are being changed at the same time works,
951 // or that the limit handler is changed first and this also works properly.
952 union sigval signal_value {};
Christopher Ferrisb874c332020-01-21 16:39:05 -0800953 ASSERT_EQ(0, sigqueue(getpid(), BIONIC_SIGNAL_PROFILER, signal_value));
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -0800954
Christopher Ferrisfe130412023-07-20 16:37:43 -0700955 // Wait for all of the threads to finish.
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -0800956 for (size_t i = 0; i < kNumThreads; i++) {
Christopher Ferrisfe130412023-07-20 16:37:43 -0700957 threads[i]->join();
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -0800958 }
Christopher Ferrisfe130412023-07-20 16:37:43 -0700959 ASSERT_EQ(1U, num_successful) << "Only one thread should be able to set the limit.";
Christopher Ferrise9ffc522023-08-03 17:34:05 -0700960 _exit(0);
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -0800961}
962#endif
963
964TEST(android_mallopt, set_allocation_limit_multiple_threads) {
965#if defined(__BIONIC__)
966 if (IsDynamic()) {
967 ASSERT_TRUE(android_mallopt(M_INIT_ZYGOTE_CHILD_PROFILING, nullptr, 0));
968 }
969
970 // Run this a number of times as a stress test.
971 for (size_t i = 0; i < 100; i++) {
972 // Not using ASSERT_EXIT because errors messages are not displayed.
973 pid_t pid;
974 if ((pid = fork()) == 0) {
975 ASSERT_NO_FATAL_FAILURE(SetAllocationLimitMultipleThreads());
976 }
977 ASSERT_NE(-1, pid);
978 int status;
979 ASSERT_EQ(pid, wait(&status));
980 ASSERT_EQ(0, WEXITSTATUS(status));
981 }
982#else
Elliott Hughes10907202019-03-27 08:51:02 -0700983 GTEST_SKIP() << "bionic extension";
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -0800984#endif
985}
Peter Collingbourne5d3aa862020-09-11 15:05:17 -0700986
Christopher Ferris8f9713e2021-09-20 17:25:46 -0700987#if defined(__BIONIC__)
Mitch Phillipsebc2ac92024-05-02 13:25:46 +0200988using Mode = android_mallopt_gwp_asan_options_t::Mode;
Mitch Phillipse6997d52020-11-30 15:04:14 -0800989TEST(android_mallopt, DISABLED_multiple_enable_gwp_asan) {
990 android_mallopt_gwp_asan_options_t options;
991 options.program_name = ""; // Don't infer GWP-ASan options from sysprops.
Mitch Phillipsebc2ac92024-05-02 13:25:46 +0200992 options.mode = Mode::APP_MANIFEST_NEVER;
Mitch Phillipse6997d52020-11-30 15:04:14 -0800993 // GWP-ASan should already be enabled. Trying to enable or disable it should
994 // always pass.
995 ASSERT_TRUE(android_mallopt(M_INITIALIZE_GWP_ASAN, &options, sizeof(options)));
Mitch Phillipsebc2ac92024-05-02 13:25:46 +0200996 options.mode = Mode::APP_MANIFEST_DEFAULT;
Mitch Phillipse6997d52020-11-30 15:04:14 -0800997 ASSERT_TRUE(android_mallopt(M_INITIALIZE_GWP_ASAN, &options, sizeof(options)));
998}
999#endif // defined(__BIONIC__)
Christopher Ferris8f9713e2021-09-20 17:25:46 -07001000
Mitch Phillipse6997d52020-11-30 15:04:14 -08001001TEST(android_mallopt, multiple_enable_gwp_asan) {
1002#if defined(__BIONIC__)
1003 // Always enable GWP-Asan, with default options.
1004 RunGwpAsanTest("*.DISABLED_multiple_enable_gwp_asan");
Christopher Ferris8f9713e2021-09-20 17:25:46 -07001005#else
1006 GTEST_SKIP() << "bionic extension";
1007#endif
1008}
1009
Florian Mayercc61ad82022-08-31 11:43:30 -07001010TEST(android_mallopt, memtag_stack_is_on) {
1011#if defined(__BIONIC__)
1012 bool memtag_stack;
1013 EXPECT_TRUE(android_mallopt(M_MEMTAG_STACK_IS_ON, &memtag_stack, sizeof(memtag_stack)));
1014#else
1015 GTEST_SKIP() << "bionic extension";
1016#endif
1017}
1018
Mitch Phillips9cad8422021-01-20 16:03:27 -08001019void TestHeapZeroing(int num_iterations, int (*get_alloc_size)(int iteration)) {
1020 std::vector<void*> allocs;
1021 constexpr int kMaxBytesToCheckZero = 64;
1022 const char kBlankMemory[kMaxBytesToCheckZero] = {};
1023
1024 for (int i = 0; i < num_iterations; ++i) {
1025 int size = get_alloc_size(i);
1026 allocs.push_back(malloc(size));
1027 memset(allocs.back(), 'X', std::min(size, kMaxBytesToCheckZero));
1028 }
1029
1030 for (void* alloc : allocs) {
1031 free(alloc);
1032 }
1033 allocs.clear();
1034
1035 for (int i = 0; i < num_iterations; ++i) {
1036 int size = get_alloc_size(i);
1037 allocs.push_back(malloc(size));
1038 ASSERT_EQ(0, memcmp(allocs.back(), kBlankMemory, std::min(size, kMaxBytesToCheckZero)));
1039 }
1040
1041 for (void* alloc : allocs) {
1042 free(alloc);
1043 }
1044}
1045
1046TEST(malloc, zero_init) {
1047#if defined(__BIONIC__)
1048 SKIP_WITH_HWASAN << "hwasan does not implement mallopt";
1049 bool allocator_scudo;
1050 GetAllocatorVersion(&allocator_scudo);
1051 if (!allocator_scudo) {
1052 GTEST_SKIP() << "scudo allocator only test";
1053 }
1054
1055 mallopt(M_BIONIC_ZERO_INIT, 1);
1056
1057 // Test using a block of 4K small (1-32 byte) allocations.
1058 TestHeapZeroing(/* num_iterations */ 0x1000, [](int iteration) -> int {
1059 return 1 + iteration % 32;
1060 });
1061
1062 // Also test large allocations that land in the scudo secondary, as this is
1063 // the only part of Scudo that's changed by enabling zero initialization with
1064 // MTE. Uses 32 allocations, totalling 60MiB memory. Decay time (time to
1065 // release secondary allocations back to the OS) was modified to 0ms/1ms by
1066 // mallopt_decay. Ensure that we delay for at least a second before releasing
1067 // pages to the OS in order to avoid implicit zeroing by the kernel.
Chia-hung Duan6abb4062024-04-17 19:08:48 -07001068 mallopt(M_DECAY_TIME, 1);
Mitch Phillips9cad8422021-01-20 16:03:27 -08001069 TestHeapZeroing(/* num_iterations */ 32, [](int iteration) -> int {
1070 return 1 << (19 + iteration % 4);
1071 });
1072
1073#else
1074 GTEST_SKIP() << "bionic-only test";
1075#endif
1076}
1077
1078// Note that MTE is enabled on cc_tests on devices that support MTE.
1079TEST(malloc, disable_mte) {
Peter Collingbourne5d3aa862020-09-11 15:05:17 -07001080#if defined(__BIONIC__)
1081 if (!mte_supported()) {
1082 GTEST_SKIP() << "This function can only be tested with MTE";
1083 }
1084
Peter Collingbourne5d3aa862020-09-11 15:05:17 -07001085 sem_t sem;
1086 ASSERT_EQ(0, sem_init(&sem, 0, 0));
1087
1088 pthread_t thread;
1089 ASSERT_EQ(0, pthread_create(
1090 &thread, nullptr,
1091 [](void* ptr) -> void* {
1092 auto* sem = reinterpret_cast<sem_t*>(ptr);
1093 sem_wait(sem);
1094 return reinterpret_cast<void*>(prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0));
1095 },
1096 &sem));
1097
Mitch Phillips9cad8422021-01-20 16:03:27 -08001098 ASSERT_EQ(1, mallopt(M_BIONIC_SET_HEAP_TAGGING_LEVEL, M_HEAP_TAGGING_LEVEL_NONE));
Peter Collingbourne5d3aa862020-09-11 15:05:17 -07001099 ASSERT_EQ(0, sem_post(&sem));
1100
1101 int my_tagged_addr_ctrl = prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0);
Christopher Ferris2abfa9e2021-11-01 16:26:06 -07001102 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 -07001103
1104 void* retval;
1105 ASSERT_EQ(0, pthread_join(thread, &retval));
1106 int thread_tagged_addr_ctrl = reinterpret_cast<uintptr_t>(retval);
1107 ASSERT_EQ(my_tagged_addr_ctrl, thread_tagged_addr_ctrl);
Peter Collingbourne5d3aa862020-09-11 15:05:17 -07001108#else
1109 GTEST_SKIP() << "bionic extension";
1110#endif
1111}
Peter Collingbourne2659d7b2021-03-05 13:31:41 -08001112
1113TEST(malloc, allocation_slack) {
1114#if defined(__BIONIC__)
Christopher Ferris7c0ce862021-06-08 15:33:22 -07001115 SKIP_WITH_NATIVE_BRIDGE; // http://b/189606147
1116
Peter Collingbourne2659d7b2021-03-05 13:31:41 -08001117 bool allocator_scudo;
1118 GetAllocatorVersion(&allocator_scudo);
1119 if (!allocator_scudo) {
1120 GTEST_SKIP() << "scudo allocator only test";
1121 }
1122
1123 // Test that older target SDK levels let you access a few bytes off the end of
1124 // a large allocation.
1125 android_set_application_target_sdk_version(29);
1126 auto p = std::make_unique<char[]>(131072);
1127 volatile char *vp = p.get();
1128 volatile char oob ATTRIBUTE_UNUSED = vp[131072];
1129#else
1130 GTEST_SKIP() << "bionic extension";
1131#endif
1132}
Evgenii Stepanovf0d7a342021-11-16 17:34:39 -08001133
1134// Regression test for b/206701345 -- scudo bug, MTE only.
1135// Fix: https://reviews.llvm.org/D105261
1136// Fix: https://android-review.googlesource.com/c/platform/external/scudo/+/1763655
1137TEST(malloc, realloc_mte_crash_b206701345) {
1138 // We want to hit in-place realloc at the very end of an mmap-ed region. Not
1139 // all size classes allow such placement - mmap size has to be divisible by
1140 // the block size. At the time of writing this could only be reproduced with
1141 // 64 byte size class (i.e. 48 byte allocations), but that may change in the
1142 // future. Try several different classes at the lower end.
1143 std::vector<void*> ptrs(10000);
1144 for (int i = 1; i < 32; ++i) {
1145 size_t sz = 16 * i - 1;
1146 for (void*& p : ptrs) {
1147 p = realloc(malloc(sz), sz + 1);
1148 }
1149
1150 for (void* p : ptrs) {
1151 free(p);
1152 }
1153 }
1154}
Christopher Ferris02b6bbc2022-06-02 15:20:23 -07001155
Christopher Ferrisb4e560e2023-10-26 17:00:00 -07001156TEST(android_mallopt, get_decay_time_enabled_errors) {
1157#if defined(__BIONIC__)
1158 errno = 0;
1159 EXPECT_FALSE(android_mallopt(M_GET_DECAY_TIME_ENABLED, nullptr, sizeof(bool)));
1160 EXPECT_ERRNO(EINVAL);
1161
1162 errno = 0;
1163 int value;
1164 EXPECT_FALSE(android_mallopt(M_GET_DECAY_TIME_ENABLED, &value, sizeof(value)));
1165 EXPECT_ERRNO(EINVAL);
1166#else
1167 GTEST_SKIP() << "bionic-only test";
1168#endif
1169}
1170
1171TEST(android_mallopt, get_decay_time_enabled) {
1172#if defined(__BIONIC__)
1173 SKIP_WITH_HWASAN << "hwasan does not implement mallopt";
1174
1175 EXPECT_EQ(1, mallopt(M_DECAY_TIME, 0));
1176
1177 bool value;
1178 EXPECT_TRUE(android_mallopt(M_GET_DECAY_TIME_ENABLED, &value, sizeof(value)));
1179 EXPECT_FALSE(value);
1180
1181 EXPECT_EQ(1, mallopt(M_DECAY_TIME, 1));
1182 EXPECT_TRUE(android_mallopt(M_GET_DECAY_TIME_ENABLED, &value, sizeof(value)));
1183 EXPECT_TRUE(value);
Chia-hung Duan6abb4062024-04-17 19:08:48 -07001184
1185 EXPECT_EQ(1, mallopt(M_DECAY_TIME, -1));
1186 EXPECT_TRUE(android_mallopt(M_GET_DECAY_TIME_ENABLED, &value, sizeof(value)));
1187 EXPECT_FALSE(value);
Christopher Ferrisb4e560e2023-10-26 17:00:00 -07001188#else
1189 GTEST_SKIP() << "bionic-only test";
1190#endif
1191}
Christopher Ferris0b231992023-10-31 15:09:37 -07001192
1193TEST(android_mallopt, DISABLED_verify_decay_time_on) {
1194#if defined(__BIONIC__)
1195 bool value;
1196 EXPECT_TRUE(android_mallopt(M_GET_DECAY_TIME_ENABLED, &value, sizeof(value)));
1197 EXPECT_TRUE(value) << "decay time did not get enabled properly.";
1198#endif
1199}
1200
1201TEST(android_mallopt, decay_time_set_using_env_variable) {
1202#if defined(__BIONIC__)
1203 SKIP_WITH_HWASAN << "hwasan does not implement mallopt";
1204
1205 bool value;
1206 ASSERT_TRUE(android_mallopt(M_GET_DECAY_TIME_ENABLED, &value, sizeof(value)));
1207 ASSERT_FALSE(value) << "decay time did not get disabled properly.";
1208
1209 // Verify that setting the environment variable here will be carried into
1210 // fork'd and exec'd processes.
1211 ASSERT_EQ(0, setenv("MALLOC_USE_APP_DEFAULTS", "1", 1));
1212 ExecTestHelper eth;
Christopher Ferris10111be2025-03-13 17:55:39 +00001213 std::string executable(testing::internal::GetArgvs()[0]);
1214 eth.SetArgs({executable.c_str(), "--gtest_also_run_disabled_tests",
Christopher Ferris0b231992023-10-31 15:09:37 -07001215 "--gtest_filter=android_mallopt.DISABLED_verify_decay_time_on", nullptr});
Christopher Ferris10111be2025-03-13 17:55:39 +00001216 eth.Run([&]() { execv(executable.c_str(), eth.GetArgs()); }, 0, R"(\[ PASSED \] 1 test)");
Christopher Ferris0b231992023-10-31 15:09:37 -07001217#else
1218 GTEST_SKIP() << "bionic-only test";
1219#endif
1220}