blob: f6249e06c1dbac6816e41d39325ec8ba079efda1 [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
Evgenii Stepanovacd6f4f2018-11-06 16:48:27 -080050#include "utils.h"
Dan Alberte5fdaa42014-06-14 01:04:31 +000051
Elliott Hughesb1770852018-09-18 12:52:42 -070052#if defined(__BIONIC__)
Christopher Ferrisb874c332020-01-21 16:39:05 -080053
Peter Collingbourne45819dd2020-01-09 11:00:43 -080054#include "SignalUtils.h"
55
Elliott Hughes87fcb212025-05-01 08:24:17 -070056#include "platform/bionic/dlext_namespaces.h"
Christopher Ferrisb874c332020-01-21 16:39:05 -080057#include "platform/bionic/malloc.h"
Peter Collingbourne5d3aa862020-09-11 15:05:17 -070058#include "platform/bionic/mte.h"
Christopher Ferrisb874c332020-01-21 16:39:05 -080059#include "platform/bionic/reserved_signals.h"
60#include "private/bionic_config.h"
61
Elliott Hughesb1770852018-09-18 12:52:42 -070062#define HAVE_REALLOCARRAY 1
Christopher Ferrisb874c332020-01-21 16:39:05 -080063
Colin Cross7da20342021-07-28 11:18:11 -070064#elif defined(__GLIBC__)
Christopher Ferrisb874c332020-01-21 16:39:05 -080065
Elliott Hughesb1770852018-09-18 12:52:42 -070066#define HAVE_REALLOCARRAY __GLIBC_PREREQ(2, 26)
Christopher Ferrisb874c332020-01-21 16:39:05 -080067
Colin Cross4c5595c2021-08-16 15:51:59 -070068#elif defined(ANDROID_HOST_MUSL)
Colin Cross7da20342021-07-28 11:18:11 -070069
70#define HAVE_REALLOCARRAY 1
71
Elliott Hughesb1770852018-09-18 12:52:42 -070072#endif
73
Christopher Ferrisa4037802014-06-09 19:14:11 -070074TEST(malloc, malloc_overflow) {
Evgenii Stepanovacd6f4f2018-11-06 16:48:27 -080075 SKIP_WITH_HWASAN;
Christopher Ferrisa4037802014-06-09 19:14:11 -070076 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -070077 ASSERT_EQ(nullptr, malloc(SIZE_MAX));
Elliott Hughes95646e62023-09-21 14:11:19 -070078 ASSERT_ERRNO(ENOMEM);
Christopher Ferrisa4037802014-06-09 19:14:11 -070079}
80
Peter Collingbourne978eb162020-09-21 15:26:02 -070081TEST(malloc, calloc_mem_init_disabled) {
82#if defined(__BIONIC__)
83 // calloc should still zero memory if mem-init is disabled.
84 // With jemalloc the mallopts will fail but that shouldn't affect the
85 // execution of the test.
86 mallopt(M_THREAD_DISABLE_MEM_INIT, 1);
87 size_t alloc_len = 100;
88 char *ptr = reinterpret_cast<char*>(calloc(1, alloc_len));
89 for (size_t i = 0; i < alloc_len; i++) {
90 ASSERT_EQ(0, ptr[i]);
91 }
92 free(ptr);
93 mallopt(M_THREAD_DISABLE_MEM_INIT, 0);
94#else
95 GTEST_SKIP() << "bionic-only test";
96#endif
97}
98
Christopher Ferrisa4037802014-06-09 19:14:11 -070099TEST(malloc, calloc_illegal) {
Evgenii Stepanovacd6f4f2018-11-06 16:48:27 -0800100 SKIP_WITH_HWASAN;
Christopher Ferrisa4037802014-06-09 19:14:11 -0700101 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -0700102 ASSERT_EQ(nullptr, calloc(-1, 100));
Elliott Hughes95646e62023-09-21 14:11:19 -0700103 ASSERT_ERRNO(ENOMEM);
Christopher Ferrisa4037802014-06-09 19:14:11 -0700104}
105
106TEST(malloc, calloc_overflow) {
Evgenii Stepanovacd6f4f2018-11-06 16:48:27 -0800107 SKIP_WITH_HWASAN;
Christopher Ferrisa4037802014-06-09 19:14:11 -0700108 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -0700109 ASSERT_EQ(nullptr, calloc(1, SIZE_MAX));
Elliott Hughes95646e62023-09-21 14:11:19 -0700110 ASSERT_ERRNO(ENOMEM);
Christopher Ferrisa4037802014-06-09 19:14:11 -0700111 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -0700112 ASSERT_EQ(nullptr, calloc(SIZE_MAX, SIZE_MAX));
Elliott Hughes95646e62023-09-21 14:11:19 -0700113 ASSERT_ERRNO(ENOMEM);
Christopher Ferrisa4037802014-06-09 19:14:11 -0700114 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -0700115 ASSERT_EQ(nullptr, calloc(2, SIZE_MAX));
Elliott Hughes95646e62023-09-21 14:11:19 -0700116 ASSERT_ERRNO(ENOMEM);
Christopher Ferrisa4037802014-06-09 19:14:11 -0700117 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -0700118 ASSERT_EQ(nullptr, calloc(SIZE_MAX, 2));
Elliott Hughes95646e62023-09-21 14:11:19 -0700119 ASSERT_ERRNO(ENOMEM);
Christopher Ferrisa4037802014-06-09 19:14:11 -0700120}
121
Christopher Ferrisa4037802014-06-09 19:14:11 -0700122TEST(malloc, memalign_overflow) {
Evgenii Stepanovacd6f4f2018-11-06 16:48:27 -0800123 SKIP_WITH_HWASAN;
Yi Kong32bc0fc2018-08-02 17:31:13 -0700124 ASSERT_EQ(nullptr, memalign(4096, SIZE_MAX));
Christopher Ferrisa4037802014-06-09 19:14:11 -0700125}
126
127TEST(malloc, memalign_non_power2) {
Evgenii Stepanovacd6f4f2018-11-06 16:48:27 -0800128 SKIP_WITH_HWASAN;
Christopher Ferrisa4037802014-06-09 19:14:11 -0700129 void* ptr;
130 for (size_t align = 0; align <= 256; align++) {
131 ptr = memalign(align, 1024);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700132 ASSERT_TRUE(ptr != nullptr) << "Failed at align " << align;
Christopher Ferrisa4037802014-06-09 19:14:11 -0700133 free(ptr);
134 }
135}
136
Christopher Ferrisa4037802014-06-09 19:14:11 -0700137TEST(malloc, realloc_overflow) {
Evgenii Stepanovacd6f4f2018-11-06 16:48:27 -0800138 SKIP_WITH_HWASAN;
Christopher Ferrisa4037802014-06-09 19:14:11 -0700139 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -0700140 ASSERT_EQ(nullptr, realloc(nullptr, SIZE_MAX));
Elliott Hughes95646e62023-09-21 14:11:19 -0700141 ASSERT_ERRNO(ENOMEM);
Christopher Ferrisa4037802014-06-09 19:14:11 -0700142 void* ptr = malloc(100);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700143 ASSERT_TRUE(ptr != nullptr);
Christopher Ferrisa4037802014-06-09 19:14:11 -0700144 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -0700145 ASSERT_EQ(nullptr, realloc(ptr, SIZE_MAX));
Elliott Hughes95646e62023-09-21 14:11:19 -0700146 ASSERT_ERRNO(ENOMEM);
Christopher Ferrisa4037802014-06-09 19:14:11 -0700147 free(ptr);
Christopher Ferris72bbd422014-05-08 11:14:03 -0700148}
149
Dan Alberte5fdaa42014-06-14 01:04:31 +0000150#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
151extern "C" void* pvalloc(size_t);
152extern "C" void* valloc(size_t);
Christopher Ferris804cebe2019-06-20 08:50:23 -0700153#endif
Dan Alberte5fdaa42014-06-14 01:04:31 +0000154
Christopher Ferrisa4037802014-06-09 19:14:11 -0700155TEST(malloc, pvalloc_overflow) {
Christopher Ferris804cebe2019-06-20 08:50:23 -0700156#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
Yi Kong32bc0fc2018-08-02 17:31:13 -0700157 ASSERT_EQ(nullptr, pvalloc(SIZE_MAX));
Christopher Ferris804cebe2019-06-20 08:50:23 -0700158#else
159 GTEST_SKIP() << "pvalloc not supported.";
160#endif
Christopher Ferrisa4037802014-06-09 19:14:11 -0700161}
162
163TEST(malloc, valloc_std) {
Christopher Ferris804cebe2019-06-20 08:50:23 -0700164#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
Christopher Ferrisa4037802014-06-09 19:14:11 -0700165 size_t pagesize = sysconf(_SC_PAGESIZE);
Christopher Ferrisd5ab0a52019-06-19 12:03:57 -0700166 void* ptr = valloc(100);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700167 ASSERT_TRUE(ptr != nullptr);
Christopher Ferrisa4037802014-06-09 19:14:11 -0700168 ASSERT_TRUE((reinterpret_cast<uintptr_t>(ptr) & (pagesize-1)) == 0);
169 free(ptr);
Christopher Ferris804cebe2019-06-20 08:50:23 -0700170#else
171 GTEST_SKIP() << "valloc not supported.";
172#endif
Christopher Ferrisa4037802014-06-09 19:14:11 -0700173}
174
175TEST(malloc, valloc_overflow) {
Christopher Ferris804cebe2019-06-20 08:50:23 -0700176#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
Yi Kong32bc0fc2018-08-02 17:31:13 -0700177 ASSERT_EQ(nullptr, valloc(SIZE_MAX));
Christopher Ferris804cebe2019-06-20 08:50:23 -0700178#else
179 GTEST_SKIP() << "valloc not supported.";
Dan Alberte5fdaa42014-06-14 01:04:31 +0000180#endif
Christopher Ferris804cebe2019-06-20 08:50:23 -0700181}
Dan Albert4caa1f02014-08-20 09:16:57 -0700182
183TEST(malloc, malloc_info) {
184#ifdef __BIONIC__
Evgenii Stepanov8de6b462019-03-22 13:22:28 -0700185 SKIP_WITH_HWASAN; // hwasan does not implement malloc_info
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800186
187 TemporaryFile tf;
188 ASSERT_TRUE(tf.fd != -1);
189 FILE* fp = fdopen(tf.fd, "w+");
190 tf.release();
191 ASSERT_TRUE(fp != nullptr);
192 ASSERT_EQ(0, malloc_info(0, fp));
193 ASSERT_EQ(0, fclose(fp));
194
195 std::string contents;
196 ASSERT_TRUE(android::base::ReadFileToString(tf.path, &contents));
Dan Albert4caa1f02014-08-20 09:16:57 -0700197
198 tinyxml2::XMLDocument doc;
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800199 ASSERT_EQ(tinyxml2::XML_SUCCESS, doc.Parse(contents.c_str()));
Dan Albert4caa1f02014-08-20 09:16:57 -0700200
201 auto root = doc.FirstChildElement();
202 ASSERT_NE(nullptr, root);
203 ASSERT_STREQ("malloc", root->Name());
Christopher Ferris85169652019-10-09 18:41:55 -0700204 std::string version(root->Attribute("version"));
205 if (version == "jemalloc-1") {
Christopher Ferris6c619a02019-03-01 17:59:51 -0800206 auto arena = root->FirstChildElement();
207 for (; arena != nullptr; arena = arena->NextSiblingElement()) {
208 int val;
Dan Albert4caa1f02014-08-20 09:16:57 -0700209
Christopher Ferris6c619a02019-03-01 17:59:51 -0800210 ASSERT_STREQ("heap", arena->Name());
211 ASSERT_EQ(tinyxml2::XML_SUCCESS, arena->QueryIntAttribute("nr", &val));
212 ASSERT_EQ(tinyxml2::XML_SUCCESS,
213 arena->FirstChildElement("allocated-large")->QueryIntText(&val));
214 ASSERT_EQ(tinyxml2::XML_SUCCESS,
215 arena->FirstChildElement("allocated-huge")->QueryIntText(&val));
216 ASSERT_EQ(tinyxml2::XML_SUCCESS,
217 arena->FirstChildElement("allocated-bins")->QueryIntText(&val));
218 ASSERT_EQ(tinyxml2::XML_SUCCESS,
219 arena->FirstChildElement("bins-total")->QueryIntText(&val));
Dan Albert4caa1f02014-08-20 09:16:57 -0700220
Christopher Ferris6c619a02019-03-01 17:59:51 -0800221 auto bin = arena->FirstChildElement("bin");
222 for (; bin != nullptr; bin = bin ->NextSiblingElement()) {
223 if (strcmp(bin->Name(), "bin") == 0) {
224 ASSERT_EQ(tinyxml2::XML_SUCCESS, bin->QueryIntAttribute("nr", &val));
225 ASSERT_EQ(tinyxml2::XML_SUCCESS,
226 bin->FirstChildElement("allocated")->QueryIntText(&val));
227 ASSERT_EQ(tinyxml2::XML_SUCCESS,
228 bin->FirstChildElement("nmalloc")->QueryIntText(&val));
229 ASSERT_EQ(tinyxml2::XML_SUCCESS,
230 bin->FirstChildElement("ndalloc")->QueryIntText(&val));
231 }
Dan Albert4caa1f02014-08-20 09:16:57 -0700232 }
233 }
Christopher Ferriscce88c02020-02-12 17:41:01 -0800234 } else if (version == "scudo-1") {
235 auto element = root->FirstChildElement();
236 for (; element != nullptr; element = element->NextSiblingElement()) {
237 int val;
238
239 ASSERT_STREQ("alloc", element->Name());
240 ASSERT_EQ(tinyxml2::XML_SUCCESS, element->QueryIntAttribute("size", &val));
241 ASSERT_EQ(tinyxml2::XML_SUCCESS, element->QueryIntAttribute("count", &val));
242 }
Christopher Ferris6c619a02019-03-01 17:59:51 -0800243 } else {
Christopher Ferriscce88c02020-02-12 17:41:01 -0800244 // Do not verify output for debug malloc.
245 ASSERT_TRUE(version == "debug-malloc-1") << "Unknown version: " << version;
Dan Albert4caa1f02014-08-20 09:16:57 -0700246 }
Christopher Ferris9eb3f1f2024-12-09 23:07:14 +0000247 printf("Allocator version: %s\n", version.c_str());
Dan Albert4caa1f02014-08-20 09:16:57 -0700248#endif
249}
Christopher Ferrisad33ebe2015-12-16 12:07:25 -0800250
Christopher Ferrisdb9706a2019-05-02 18:33:11 -0700251TEST(malloc, malloc_info_matches_mallinfo) {
252#ifdef __BIONIC__
253 SKIP_WITH_HWASAN; // hwasan does not implement malloc_info
254
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800255 TemporaryFile tf;
256 ASSERT_TRUE(tf.fd != -1);
257 FILE* fp = fdopen(tf.fd, "w+");
258 tf.release();
259 ASSERT_TRUE(fp != nullptr);
Christopher Ferrisdb9706a2019-05-02 18:33:11 -0700260 size_t mallinfo_before_allocated_bytes = mallinfo().uordblks;
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800261 ASSERT_EQ(0, malloc_info(0, fp));
Christopher Ferrisdb9706a2019-05-02 18:33:11 -0700262 size_t mallinfo_after_allocated_bytes = mallinfo().uordblks;
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800263 ASSERT_EQ(0, fclose(fp));
264
265 std::string contents;
266 ASSERT_TRUE(android::base::ReadFileToString(tf.path, &contents));
Christopher Ferrisdb9706a2019-05-02 18:33:11 -0700267
268 tinyxml2::XMLDocument doc;
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800269 ASSERT_EQ(tinyxml2::XML_SUCCESS, doc.Parse(contents.c_str()));
Christopher Ferrisdb9706a2019-05-02 18:33:11 -0700270
271 size_t total_allocated_bytes = 0;
272 auto root = doc.FirstChildElement();
273 ASSERT_NE(nullptr, root);
274 ASSERT_STREQ("malloc", root->Name());
Christopher Ferris85169652019-10-09 18:41:55 -0700275 std::string version(root->Attribute("version"));
276 if (version == "jemalloc-1") {
Christopher Ferrisdb9706a2019-05-02 18:33:11 -0700277 auto arena = root->FirstChildElement();
278 for (; arena != nullptr; arena = arena->NextSiblingElement()) {
279 int val;
280
281 ASSERT_STREQ("heap", arena->Name());
282 ASSERT_EQ(tinyxml2::XML_SUCCESS, arena->QueryIntAttribute("nr", &val));
283 ASSERT_EQ(tinyxml2::XML_SUCCESS,
284 arena->FirstChildElement("allocated-large")->QueryIntText(&val));
285 total_allocated_bytes += val;
286 ASSERT_EQ(tinyxml2::XML_SUCCESS,
287 arena->FirstChildElement("allocated-huge")->QueryIntText(&val));
288 total_allocated_bytes += val;
289 ASSERT_EQ(tinyxml2::XML_SUCCESS,
290 arena->FirstChildElement("allocated-bins")->QueryIntText(&val));
291 total_allocated_bytes += val;
292 ASSERT_EQ(tinyxml2::XML_SUCCESS,
293 arena->FirstChildElement("bins-total")->QueryIntText(&val));
294 }
295 // The total needs to be between the mallinfo call before and after
296 // since malloc_info allocates some memory.
297 EXPECT_LE(mallinfo_before_allocated_bytes, total_allocated_bytes);
298 EXPECT_GE(mallinfo_after_allocated_bytes, total_allocated_bytes);
Christopher Ferriscce88c02020-02-12 17:41:01 -0800299 } else if (version == "scudo-1") {
300 auto element = root->FirstChildElement();
301 for (; element != nullptr; element = element->NextSiblingElement()) {
302 ASSERT_STREQ("alloc", element->Name());
303 int size;
304 ASSERT_EQ(tinyxml2::XML_SUCCESS, element->QueryIntAttribute("size", &size));
305 int count;
306 ASSERT_EQ(tinyxml2::XML_SUCCESS, element->QueryIntAttribute("count", &count));
307 total_allocated_bytes += size * count;
308 }
309 // Scudo only gives the information on the primary, so simply make
310 // sure that the value is non-zero.
311 EXPECT_NE(0U, total_allocated_bytes);
Christopher Ferrisdb9706a2019-05-02 18:33:11 -0700312 } else {
Christopher Ferriscce88c02020-02-12 17:41:01 -0800313 // Do not verify output for debug malloc.
314 ASSERT_TRUE(version == "debug-malloc-1") << "Unknown version: " << version;
Christopher Ferrisdb9706a2019-05-02 18:33:11 -0700315 }
316#endif
317}
318
Elliott Hughes884f76e2016-02-10 20:43:22 -0800319TEST(malloc, malloc_0) {
320 void* p = malloc(0);
321 ASSERT_TRUE(p != nullptr);
322 free(p);
323}
324
325TEST(malloc, calloc_0_0) {
326 void* p = calloc(0, 0);
327 ASSERT_TRUE(p != nullptr);
328 free(p);
329}
330
331TEST(malloc, calloc_0_1) {
332 void* p = calloc(0, 1);
333 ASSERT_TRUE(p != nullptr);
334 free(p);
335}
336
337TEST(malloc, calloc_1_0) {
338 void* p = calloc(1, 0);
339 ASSERT_TRUE(p != nullptr);
340 free(p);
341}
342
343TEST(malloc, realloc_nullptr_0) {
344 // realloc(nullptr, size) is actually malloc(size).
345 void* p = realloc(nullptr, 0);
346 ASSERT_TRUE(p != nullptr);
347 free(p);
348}
349
350TEST(malloc, realloc_0) {
351 void* p = malloc(1024);
352 ASSERT_TRUE(p != nullptr);
353 // realloc(p, 0) is actually free(p).
354 void* p2 = realloc(p, 0);
355 ASSERT_TRUE(p2 == nullptr);
356}
Christopher Ferris72df6702016-02-11 15:51:31 -0800357
358constexpr size_t MAX_LOOPS = 200;
359
360// Make sure that memory returned by malloc is aligned to allow these data types.
361TEST(malloc, verify_alignment) {
362 uint32_t** values_32 = new uint32_t*[MAX_LOOPS];
363 uint64_t** values_64 = new uint64_t*[MAX_LOOPS];
364 long double** values_ldouble = new long double*[MAX_LOOPS];
365 // Use filler to attempt to force the allocator to get potentially bad alignments.
366 void** filler = new void*[MAX_LOOPS];
367
368 for (size_t i = 0; i < MAX_LOOPS; i++) {
369 // Check uint32_t pointers.
370 filler[i] = malloc(1);
371 ASSERT_TRUE(filler[i] != nullptr);
372
373 values_32[i] = reinterpret_cast<uint32_t*>(malloc(sizeof(uint32_t)));
374 ASSERT_TRUE(values_32[i] != nullptr);
375 *values_32[i] = i;
376 ASSERT_EQ(*values_32[i], i);
377 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(values_32[i]) & (sizeof(uint32_t) - 1));
378
379 free(filler[i]);
380 }
381
382 for (size_t i = 0; i < MAX_LOOPS; i++) {
383 // Check uint64_t pointers.
384 filler[i] = malloc(1);
385 ASSERT_TRUE(filler[i] != nullptr);
386
387 values_64[i] = reinterpret_cast<uint64_t*>(malloc(sizeof(uint64_t)));
388 ASSERT_TRUE(values_64[i] != nullptr);
389 *values_64[i] = 0x1000 + i;
390 ASSERT_EQ(*values_64[i], 0x1000 + i);
391 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(values_64[i]) & (sizeof(uint64_t) - 1));
392
393 free(filler[i]);
394 }
395
396 for (size_t i = 0; i < MAX_LOOPS; i++) {
397 // Check long double pointers.
398 filler[i] = malloc(1);
399 ASSERT_TRUE(filler[i] != nullptr);
400
401 values_ldouble[i] = reinterpret_cast<long double*>(malloc(sizeof(long double)));
402 ASSERT_TRUE(values_ldouble[i] != nullptr);
403 *values_ldouble[i] = 5.5 + i;
404 ASSERT_DOUBLE_EQ(*values_ldouble[i], 5.5 + i);
405 // 32 bit glibc has a long double size of 12 bytes, so hardcode the
406 // required alignment to 0x7.
407#if !defined(__BIONIC__) && !defined(__LP64__)
408 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(values_ldouble[i]) & 0x7);
409#else
410 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(values_ldouble[i]) & (sizeof(long double) - 1));
411#endif
412
413 free(filler[i]);
414 }
415
416 for (size_t i = 0; i < MAX_LOOPS; i++) {
417 free(values_32[i]);
418 free(values_64[i]);
419 free(values_ldouble[i]);
420 }
421
422 delete[] filler;
423 delete[] values_32;
424 delete[] values_64;
425 delete[] values_ldouble;
426}
Christopher Ferrisa1c0d2f2017-05-15 15:50:19 -0700427
428TEST(malloc, mallopt_smoke) {
Christopher Ferris2ef59372023-01-18 15:08:37 -0800429#if defined(__BIONIC__)
Christopher Ferrisa1c0d2f2017-05-15 15:50:19 -0700430 errno = 0;
431 ASSERT_EQ(0, mallopt(-1000, 1));
432 // mallopt doesn't set errno.
Elliott Hughes95646e62023-09-21 14:11:19 -0700433 ASSERT_ERRNO(0);
Colin Cross7da20342021-07-28 11:18:11 -0700434#else
Christopher Ferris2ef59372023-01-18 15:08:37 -0800435 GTEST_SKIP() << "bionic-only test";
Colin Cross7da20342021-07-28 11:18:11 -0700436#endif
Christopher Ferrisa1c0d2f2017-05-15 15:50:19 -0700437}
Elliott Hughesb1770852018-09-18 12:52:42 -0700438
Christopher Ferrisaf1b8dd2018-11-07 15:28:16 -0800439TEST(malloc, mallopt_decay) {
440#if defined(__BIONIC__)
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800441 SKIP_WITH_HWASAN << "hwasan does not implement mallopt";
Chia-hung Duan6abb4062024-04-17 19:08:48 -0700442 ASSERT_EQ(1, mallopt(M_DECAY_TIME, -1));
Christopher Ferrisaf1b8dd2018-11-07 15:28:16 -0800443 ASSERT_EQ(1, mallopt(M_DECAY_TIME, 1));
444 ASSERT_EQ(1, mallopt(M_DECAY_TIME, 0));
445 ASSERT_EQ(1, mallopt(M_DECAY_TIME, 1));
446 ASSERT_EQ(1, mallopt(M_DECAY_TIME, 0));
Chia-hung Duan6abb4062024-04-17 19:08:48 -0700447 ASSERT_EQ(1, mallopt(M_DECAY_TIME, -1));
Christopher Ferrisaf1b8dd2018-11-07 15:28:16 -0800448#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800449 GTEST_SKIP() << "bionic-only test";
Christopher Ferrisaf1b8dd2018-11-07 15:28:16 -0800450#endif
451}
452
453TEST(malloc, mallopt_purge) {
454#if defined(__BIONIC__)
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800455 SKIP_WITH_HWASAN << "hwasan does not implement mallopt";
Christopher Ferrisaf1b8dd2018-11-07 15:28:16 -0800456 ASSERT_EQ(1, mallopt(M_PURGE, 0));
457#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800458 GTEST_SKIP() << "bionic-only test";
Christopher Ferrisaf1b8dd2018-11-07 15:28:16 -0800459#endif
460}
461
Christopher Ferrisd86eb862023-02-28 12:45:54 -0800462TEST(malloc, mallopt_purge_all) {
463#if defined(__BIONIC__)
464 SKIP_WITH_HWASAN << "hwasan does not implement mallopt";
Christopher Ferrisd86eb862023-02-28 12:45:54 -0800465 ASSERT_EQ(1, mallopt(M_PURGE_ALL, 0));
466#else
467 GTEST_SKIP() << "bionic-only test";
468#endif
469}
470
Christopher Ferrise9a7b812023-05-11 15:36:27 -0700471TEST(malloc, mallopt_log_stats) {
472#if defined(__BIONIC__)
473 SKIP_WITH_HWASAN << "hwasan does not implement mallopt";
474 ASSERT_EQ(1, mallopt(M_LOG_STATS, 0));
475#else
476 GTEST_SKIP() << "bionic-only test";
477#endif
478}
479
Christopher Ferrisd86eb862023-02-28 12:45:54 -0800480// Verify that all of the mallopt values are unique.
481TEST(malloc, mallopt_unique_params) {
482#if defined(__BIONIC__)
483 std::vector<std::pair<int, std::string>> params{
484 std::make_pair(M_DECAY_TIME, "M_DECAY_TIME"),
485 std::make_pair(M_PURGE, "M_PURGE"),
486 std::make_pair(M_PURGE_ALL, "M_PURGE_ALL"),
487 std::make_pair(M_MEMTAG_TUNING, "M_MEMTAG_TUNING"),
488 std::make_pair(M_THREAD_DISABLE_MEM_INIT, "M_THREAD_DISABLE_MEM_INIT"),
489 std::make_pair(M_CACHE_COUNT_MAX, "M_CACHE_COUNT_MAX"),
490 std::make_pair(M_CACHE_SIZE_MAX, "M_CACHE_SIZE_MAX"),
491 std::make_pair(M_TSDS_COUNT_MAX, "M_TSDS_COUNT_MAX"),
492 std::make_pair(M_BIONIC_ZERO_INIT, "M_BIONIC_ZERO_INIT"),
493 std::make_pair(M_BIONIC_SET_HEAP_TAGGING_LEVEL, "M_BIONIC_SET_HEAP_TAGGING_LEVEL"),
Christopher Ferrise9a7b812023-05-11 15:36:27 -0700494 std::make_pair(M_LOG_STATS, "M_LOG_STATS"),
Christopher Ferrisd86eb862023-02-28 12:45:54 -0800495 };
496
497 std::unordered_map<int, std::string> all_params;
498 for (const auto& param : params) {
499 EXPECT_TRUE(all_params.count(param.first) == 0)
500 << "mallopt params " << all_params[param.first] << " and " << param.second
501 << " have the same value " << param.first;
502 all_params.insert(param);
503 }
504#else
505 GTEST_SKIP() << "bionic-only test";
506#endif
507}
508
Christopher Ferris88448792020-07-28 14:15:31 -0700509#if defined(__BIONIC__)
510static void GetAllocatorVersion(bool* allocator_scudo) {
511 TemporaryFile tf;
512 ASSERT_TRUE(tf.fd != -1);
513 FILE* fp = fdopen(tf.fd, "w+");
514 tf.release();
515 ASSERT_TRUE(fp != nullptr);
Evgenii Stepanov4edbcee2021-09-17 14:59:15 -0700516 if (malloc_info(0, fp) != 0) {
517 *allocator_scudo = false;
518 return;
519 }
Christopher Ferris88448792020-07-28 14:15:31 -0700520 ASSERT_EQ(0, fclose(fp));
521
522 std::string contents;
523 ASSERT_TRUE(android::base::ReadFileToString(tf.path, &contents));
524
525 tinyxml2::XMLDocument doc;
526 ASSERT_EQ(tinyxml2::XML_SUCCESS, doc.Parse(contents.c_str()));
527
528 auto root = doc.FirstChildElement();
529 ASSERT_NE(nullptr, root);
530 ASSERT_STREQ("malloc", root->Name());
531 std::string version(root->Attribute("version"));
532 *allocator_scudo = (version == "scudo-1");
533}
534#endif
535
536TEST(malloc, mallopt_scudo_only_options) {
537#if defined(__BIONIC__)
538 SKIP_WITH_HWASAN << "hwasan does not implement mallopt";
539 bool allocator_scudo;
540 GetAllocatorVersion(&allocator_scudo);
541 if (!allocator_scudo) {
542 GTEST_SKIP() << "scudo allocator only test";
543 }
544 ASSERT_EQ(1, mallopt(M_CACHE_COUNT_MAX, 100));
545 ASSERT_EQ(1, mallopt(M_CACHE_SIZE_MAX, 1024 * 1024 * 2));
546 ASSERT_EQ(1, mallopt(M_TSDS_COUNT_MAX, 8));
547#else
548 GTEST_SKIP() << "bionic-only test";
549#endif
550}
551
Elliott Hughesb1770852018-09-18 12:52:42 -0700552TEST(malloc, reallocarray_overflow) {
553#if HAVE_REALLOCARRAY
554 // Values that cause overflow to a result small enough (8 on LP64) that malloc would "succeed".
555 size_t a = static_cast<size_t>(INTPTR_MIN + 4);
556 size_t b = 2;
557
558 errno = 0;
559 ASSERT_TRUE(reallocarray(nullptr, a, b) == nullptr);
Elliott Hughes95646e62023-09-21 14:11:19 -0700560 ASSERT_ERRNO(ENOMEM);
Elliott Hughesb1770852018-09-18 12:52:42 -0700561
562 errno = 0;
563 ASSERT_TRUE(reallocarray(nullptr, b, a) == nullptr);
Elliott Hughes95646e62023-09-21 14:11:19 -0700564 ASSERT_ERRNO(ENOMEM);
Elliott Hughesb1770852018-09-18 12:52:42 -0700565#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800566 GTEST_SKIP() << "reallocarray not available";
Elliott Hughesb1770852018-09-18 12:52:42 -0700567#endif
568}
569
Christopher Ferrisf32494c2020-01-08 14:19:10 -0800570template <typename Type>
571void __attribute__((optnone)) VerifyAlignment(Type* floating) {
572 size_t expected_alignment = alignof(Type);
573 if (expected_alignment != 0) {
574 ASSERT_EQ(0U, (expected_alignment - 1) & reinterpret_cast<uintptr_t>(floating))
Ryan Prichardf40f2582024-01-09 16:29:20 -0800575 << "Expected alignment " << expected_alignment << " ptr value "
576 << static_cast<void*>(floating);
Christopher Ferrisf32494c2020-01-08 14:19:10 -0800577 }
578}
579
580template <typename Type>
581void __attribute__((optnone)) TestAllocateType() {
582 // The number of allocations to do in a row. This is to attempt to
583 // expose the worst case alignment for native allocators that use
584 // bins.
585 static constexpr size_t kMaxConsecutiveAllocs = 100;
586
587 // Verify using new directly.
588 Type* types[kMaxConsecutiveAllocs];
589 for (size_t i = 0; i < kMaxConsecutiveAllocs; i++) {
590 types[i] = new Type;
591 VerifyAlignment(types[i]);
592 if (::testing::Test::HasFatalFailure()) {
593 return;
594 }
595 }
596 for (size_t i = 0; i < kMaxConsecutiveAllocs; i++) {
597 delete types[i];
598 }
599
600 // Verify using malloc.
601 for (size_t i = 0; i < kMaxConsecutiveAllocs; i++) {
602 types[i] = reinterpret_cast<Type*>(malloc(sizeof(Type)));
603 ASSERT_TRUE(types[i] != nullptr);
604 VerifyAlignment(types[i]);
605 if (::testing::Test::HasFatalFailure()) {
606 return;
607 }
608 }
609 for (size_t i = 0; i < kMaxConsecutiveAllocs; i++) {
610 free(types[i]);
611 }
612
613 // Verify using a vector.
614 std::vector<Type> type_vector(kMaxConsecutiveAllocs);
615 for (size_t i = 0; i < type_vector.size(); i++) {
616 VerifyAlignment(&type_vector[i]);
617 if (::testing::Test::HasFatalFailure()) {
618 return;
619 }
620 }
621}
622
623#if defined(__ANDROID__)
624static void __attribute__((optnone)) AndroidVerifyAlignment(size_t alloc_size, size_t aligned_bytes) {
625 void* ptrs[100];
626 uintptr_t mask = aligned_bytes - 1;
627 for (size_t i = 0; i < sizeof(ptrs) / sizeof(void*); i++) {
628 ptrs[i] = malloc(alloc_size);
629 ASSERT_TRUE(ptrs[i] != nullptr);
630 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(ptrs[i]) & mask)
631 << "Expected at least " << aligned_bytes << " byte alignment: size "
632 << alloc_size << " actual ptr " << ptrs[i];
633 }
634}
635#endif
636
Christopher Ferrisb3cac0f2021-09-21 10:32:40 -0700637void AlignCheck() {
Christopher Ferrisf32494c2020-01-08 14:19:10 -0800638 // See http://www.open-std.org/jtc1/sc22/wg14/www/docs/summary.htm#dr_445
639 // for a discussion of type alignment.
640 ASSERT_NO_FATAL_FAILURE(TestAllocateType<float>());
641 ASSERT_NO_FATAL_FAILURE(TestAllocateType<double>());
642 ASSERT_NO_FATAL_FAILURE(TestAllocateType<long double>());
643
644 ASSERT_NO_FATAL_FAILURE(TestAllocateType<char>());
645 ASSERT_NO_FATAL_FAILURE(TestAllocateType<char16_t>());
646 ASSERT_NO_FATAL_FAILURE(TestAllocateType<char32_t>());
647 ASSERT_NO_FATAL_FAILURE(TestAllocateType<wchar_t>());
648 ASSERT_NO_FATAL_FAILURE(TestAllocateType<signed char>());
649 ASSERT_NO_FATAL_FAILURE(TestAllocateType<short int>());
650 ASSERT_NO_FATAL_FAILURE(TestAllocateType<int>());
651 ASSERT_NO_FATAL_FAILURE(TestAllocateType<long int>());
652 ASSERT_NO_FATAL_FAILURE(TestAllocateType<long long int>());
653 ASSERT_NO_FATAL_FAILURE(TestAllocateType<unsigned char>());
654 ASSERT_NO_FATAL_FAILURE(TestAllocateType<unsigned short int>());
655 ASSERT_NO_FATAL_FAILURE(TestAllocateType<unsigned int>());
656 ASSERT_NO_FATAL_FAILURE(TestAllocateType<unsigned long int>());
657 ASSERT_NO_FATAL_FAILURE(TestAllocateType<unsigned long long int>());
658
659#if defined(__ANDROID__)
660 // On Android, there is a lot of code that expects certain alignments:
Christopher Ferrisb3cac0f2021-09-21 10:32:40 -0700661 // 1. Allocations of a size that rounds up to a multiple of 16 bytes
662 // must have at least 16 byte alignment.
663 // 2. Allocations of a size that rounds up to a multiple of 8 bytes and
664 // not 16 bytes, are only required to have at least 8 byte alignment.
665 // In addition, on Android clang has been configured for 64 bit such that:
666 // 3. Allocations <= 8 bytes must be aligned to at least 8 bytes.
667 // 4. Allocations > 8 bytes must be aligned to at least 16 bytes.
668 // For 32 bit environments, only the first two requirements must be met.
Christopher Ferrisf32494c2020-01-08 14:19:10 -0800669
670 // See http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2293.htm for
671 // a discussion of this alignment mess. The code below is enforcing
672 // strong-alignment, since who knows what code depends on this behavior now.
Christopher Ferrisb3cac0f2021-09-21 10:32:40 -0700673 // As mentioned before, for 64 bit this will enforce the higher
674 // requirement since clang expects this behavior on Android now.
Christopher Ferrisf32494c2020-01-08 14:19:10 -0800675 for (size_t i = 1; i <= 128; i++) {
Christopher Ferrisb3cac0f2021-09-21 10:32:40 -0700676#if defined(__LP64__)
677 if (i <= 8) {
678 AndroidVerifyAlignment(i, 8);
679 } else {
680 AndroidVerifyAlignment(i, 16);
681 }
682#else
Christopher Ferrisf32494c2020-01-08 14:19:10 -0800683 size_t rounded = (i + 7) & ~7;
684 if ((rounded % 16) == 0) {
685 AndroidVerifyAlignment(i, 16);
686 } else {
687 AndroidVerifyAlignment(i, 8);
688 }
Christopher Ferrisb3cac0f2021-09-21 10:32:40 -0700689#endif
Christopher Ferrisf32494c2020-01-08 14:19:10 -0800690 if (::testing::Test::HasFatalFailure()) {
691 return;
692 }
693 }
694#endif
695}
696
Christopher Ferrisb3cac0f2021-09-21 10:32:40 -0700697TEST(malloc, align_check) {
698 AlignCheck();
699}
700
Christopher Ferrise4cdbc42019-02-08 17:30:58 -0800701bool IsDynamic() {
702#if defined(__LP64__)
703 Elf64_Ehdr ehdr;
704#else
705 Elf32_Ehdr ehdr;
706#endif
707 std::string path(android::base::GetExecutablePath());
708
709 int fd = open(path.c_str(), O_RDONLY | O_CLOEXEC);
710 if (fd == -1) {
711 // Assume dynamic on error.
712 return true;
713 }
714 bool read_completed = android::base::ReadFully(fd, &ehdr, sizeof(ehdr));
715 close(fd);
716 // Assume dynamic in error cases.
717 return !read_completed || ehdr.e_type == ET_DYN;
718}
719
Ryan Savitskiecc37e32018-12-14 15:57:21 +0000720TEST(android_mallopt, init_zygote_child_profiling) {
721#if defined(__BIONIC__)
722 // Successful call.
723 errno = 0;
Christopher Ferrise4cdbc42019-02-08 17:30:58 -0800724 if (IsDynamic()) {
725 EXPECT_EQ(true, android_mallopt(M_INIT_ZYGOTE_CHILD_PROFILING, nullptr, 0));
Elliott Hughes95646e62023-09-21 14:11:19 -0700726 EXPECT_ERRNO(0);
Christopher Ferrise4cdbc42019-02-08 17:30:58 -0800727 } else {
728 // Not supported in static executables.
729 EXPECT_EQ(false, android_mallopt(M_INIT_ZYGOTE_CHILD_PROFILING, nullptr, 0));
Elliott Hughes95646e62023-09-21 14:11:19 -0700730 EXPECT_ERRNO(ENOTSUP);
Christopher Ferrise4cdbc42019-02-08 17:30:58 -0800731 }
Ryan Savitskiecc37e32018-12-14 15:57:21 +0000732
733 // Unexpected arguments rejected.
734 errno = 0;
735 char unexpected = 0;
736 EXPECT_EQ(false, android_mallopt(M_INIT_ZYGOTE_CHILD_PROFILING, &unexpected, 1));
Christopher Ferrise4cdbc42019-02-08 17:30:58 -0800737 if (IsDynamic()) {
Elliott Hughes95646e62023-09-21 14:11:19 -0700738 EXPECT_ERRNO(EINVAL);
Christopher Ferrise4cdbc42019-02-08 17:30:58 -0800739 } else {
Elliott Hughes95646e62023-09-21 14:11:19 -0700740 EXPECT_ERRNO(ENOTSUP);
Christopher Ferrise4cdbc42019-02-08 17:30:58 -0800741 }
Ryan Savitskiecc37e32018-12-14 15:57:21 +0000742#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800743 GTEST_SKIP() << "bionic-only test";
Ryan Savitskiecc37e32018-12-14 15:57:21 +0000744#endif
745}
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -0800746
747#if defined(__BIONIC__)
748template <typename FuncType>
749void CheckAllocationFunction(FuncType func) {
750 // Assumes that no more than 108MB of memory is allocated before this.
751 size_t limit = 128 * 1024 * 1024;
752 ASSERT_TRUE(android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit)));
753 if (!func(20 * 1024 * 1024))
754 exit(1);
755 if (func(128 * 1024 * 1024))
756 exit(1);
757 exit(0);
758}
759#endif
760
761TEST(android_mallopt, set_allocation_limit) {
762#if defined(__BIONIC__)
763 EXPECT_EXIT(CheckAllocationFunction([](size_t bytes) { return calloc(bytes, 1) != nullptr; }),
764 testing::ExitedWithCode(0), "");
765 EXPECT_EXIT(CheckAllocationFunction([](size_t bytes) { return calloc(1, bytes) != nullptr; }),
766 testing::ExitedWithCode(0), "");
767 EXPECT_EXIT(CheckAllocationFunction([](size_t bytes) { return malloc(bytes) != nullptr; }),
768 testing::ExitedWithCode(0), "");
769 EXPECT_EXIT(CheckAllocationFunction(
770 [](size_t bytes) { return memalign(sizeof(void*), bytes) != nullptr; }),
771 testing::ExitedWithCode(0), "");
772 EXPECT_EXIT(CheckAllocationFunction([](size_t bytes) {
773 void* ptr;
774 return posix_memalign(&ptr, sizeof(void *), bytes) == 0;
775 }),
776 testing::ExitedWithCode(0), "");
777 EXPECT_EXIT(CheckAllocationFunction(
778 [](size_t bytes) { return aligned_alloc(sizeof(void*), bytes) != nullptr; }),
779 testing::ExitedWithCode(0), "");
780 EXPECT_EXIT(CheckAllocationFunction([](size_t bytes) {
781 void* p = malloc(1024 * 1024);
782 return realloc(p, bytes) != nullptr;
783 }),
784 testing::ExitedWithCode(0), "");
785#if !defined(__LP64__)
786 EXPECT_EXIT(CheckAllocationFunction([](size_t bytes) { return pvalloc(bytes) != nullptr; }),
787 testing::ExitedWithCode(0), "");
788 EXPECT_EXIT(CheckAllocationFunction([](size_t bytes) { return valloc(bytes) != nullptr; }),
789 testing::ExitedWithCode(0), "");
790#endif
791#else
Elliott Hughes10907202019-03-27 08:51:02 -0700792 GTEST_SKIP() << "bionic extension";
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -0800793#endif
794}
795
796TEST(android_mallopt, set_allocation_limit_multiple) {
797#if defined(__BIONIC__)
798 // Only the first set should work.
799 size_t limit = 256 * 1024 * 1024;
800 ASSERT_TRUE(android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit)));
801 limit = 32 * 1024 * 1024;
802 ASSERT_FALSE(android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit)));
803#else
Elliott Hughes10907202019-03-27 08:51:02 -0700804 GTEST_SKIP() << "bionic extension";
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -0800805#endif
806}
807
808#if defined(__BIONIC__)
809static constexpr size_t kAllocationSize = 8 * 1024 * 1024;
810
811static size_t GetMaxAllocations() {
812 size_t max_pointers = 0;
813 void* ptrs[20];
814 for (size_t i = 0; i < sizeof(ptrs) / sizeof(void*); i++) {
815 ptrs[i] = malloc(kAllocationSize);
816 if (ptrs[i] == nullptr) {
817 max_pointers = i;
818 break;
819 }
820 }
821 for (size_t i = 0; i < max_pointers; i++) {
822 free(ptrs[i]);
823 }
824 return max_pointers;
825}
826
827static void VerifyMaxPointers(size_t max_pointers) {
828 // Now verify that we can allocate the same number as before.
829 void* ptrs[20];
830 for (size_t i = 0; i < max_pointers; i++) {
831 ptrs[i] = malloc(kAllocationSize);
832 ASSERT_TRUE(ptrs[i] != nullptr) << "Failed to allocate on iteration " << i;
833 }
834
835 // Make sure the next allocation still fails.
836 ASSERT_TRUE(malloc(kAllocationSize) == nullptr);
837 for (size_t i = 0; i < max_pointers; i++) {
838 free(ptrs[i]);
839 }
840}
841#endif
842
843TEST(android_mallopt, set_allocation_limit_realloc_increase) {
844#if defined(__BIONIC__)
845 size_t limit = 128 * 1024 * 1024;
846 ASSERT_TRUE(android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit)));
847
848 size_t max_pointers = GetMaxAllocations();
849 ASSERT_TRUE(max_pointers != 0) << "Limit never reached.";
850
851 void* memory = malloc(10 * 1024 * 1024);
852 ASSERT_TRUE(memory != nullptr);
853
854 // Increase size.
855 memory = realloc(memory, 20 * 1024 * 1024);
856 ASSERT_TRUE(memory != nullptr);
857 memory = realloc(memory, 40 * 1024 * 1024);
858 ASSERT_TRUE(memory != nullptr);
859 memory = realloc(memory, 60 * 1024 * 1024);
860 ASSERT_TRUE(memory != nullptr);
861 memory = realloc(memory, 80 * 1024 * 1024);
862 ASSERT_TRUE(memory != nullptr);
863 // Now push past limit.
864 memory = realloc(memory, 130 * 1024 * 1024);
865 ASSERT_TRUE(memory == nullptr);
866
867 VerifyMaxPointers(max_pointers);
868#else
Elliott Hughes10907202019-03-27 08:51:02 -0700869 GTEST_SKIP() << "bionic extension";
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -0800870#endif
871}
872
873TEST(android_mallopt, set_allocation_limit_realloc_decrease) {
874#if defined(__BIONIC__)
875 size_t limit = 100 * 1024 * 1024;
876 ASSERT_TRUE(android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit)));
877
878 size_t max_pointers = GetMaxAllocations();
879 ASSERT_TRUE(max_pointers != 0) << "Limit never reached.";
880
881 void* memory = malloc(80 * 1024 * 1024);
882 ASSERT_TRUE(memory != nullptr);
883
884 // Decrease size.
885 memory = realloc(memory, 60 * 1024 * 1024);
886 ASSERT_TRUE(memory != nullptr);
887 memory = realloc(memory, 40 * 1024 * 1024);
888 ASSERT_TRUE(memory != nullptr);
889 memory = realloc(memory, 20 * 1024 * 1024);
890 ASSERT_TRUE(memory != nullptr);
891 memory = realloc(memory, 10 * 1024 * 1024);
892 ASSERT_TRUE(memory != nullptr);
893 free(memory);
894
895 VerifyMaxPointers(max_pointers);
896#else
Elliott Hughes10907202019-03-27 08:51:02 -0700897 GTEST_SKIP() << "bionic extension";
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -0800898#endif
899}
900
901TEST(android_mallopt, set_allocation_limit_realloc_free) {
902#if defined(__BIONIC__)
903 size_t limit = 100 * 1024 * 1024;
904 ASSERT_TRUE(android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit)));
905
906 size_t max_pointers = GetMaxAllocations();
907 ASSERT_TRUE(max_pointers != 0) << "Limit never reached.";
908
909 void* memory = malloc(60 * 1024 * 1024);
910 ASSERT_TRUE(memory != nullptr);
911
912 memory = realloc(memory, 0);
913 ASSERT_TRUE(memory == nullptr);
914
915 VerifyMaxPointers(max_pointers);
916#else
Elliott Hughes10907202019-03-27 08:51:02 -0700917 GTEST_SKIP() << "bionic extension";
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -0800918#endif
919}
920
921#if defined(__BIONIC__)
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -0800922static void SetAllocationLimitMultipleThreads() {
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -0800923 static constexpr size_t kNumThreads = 4;
Christopher Ferrisfe130412023-07-20 16:37:43 -0700924 std::atomic_bool start_running = false;
925 std::atomic<size_t> num_running;
926 std::atomic<size_t> num_successful;
927 std::unique_ptr<std::thread> threads[kNumThreads];
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -0800928 for (size_t i = 0; i < kNumThreads; i++) {
Christopher Ferrisfe130412023-07-20 16:37:43 -0700929 threads[i].reset(new std::thread([&num_running, &start_running, &num_successful] {
930 ++num_running;
931 while (!start_running) {
932 }
933 size_t limit = 500 * 1024 * 1024;
934 if (android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit))) {
935 ++num_successful;
936 }
937 }));
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -0800938 }
939
Christopher Ferrisfe130412023-07-20 16:37:43 -0700940 // Wait until all of the threads have started.
941 while (num_running != kNumThreads)
942 ;
943
944 // Now start all of the threads setting the mallopt at once.
945 start_running = true;
946
Ryan Savitski175c8862020-01-02 19:54:57 +0000947 // Send hardcoded signal (BIONIC_SIGNAL_PROFILER with value 0) to trigger
Christopher Ferrisfe130412023-07-20 16:37:43 -0700948 // heapprofd handler. This will verify that changing the limit while
949 // the allocation handlers are being changed at the same time works,
950 // or that the limit handler is changed first and this also works properly.
951 union sigval signal_value {};
Christopher Ferrisb874c332020-01-21 16:39:05 -0800952 ASSERT_EQ(0, sigqueue(getpid(), BIONIC_SIGNAL_PROFILER, signal_value));
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -0800953
Christopher Ferrisfe130412023-07-20 16:37:43 -0700954 // Wait for all of the threads to finish.
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -0800955 for (size_t i = 0; i < kNumThreads; i++) {
Christopher Ferrisfe130412023-07-20 16:37:43 -0700956 threads[i]->join();
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -0800957 }
Christopher Ferrisfe130412023-07-20 16:37:43 -0700958 ASSERT_EQ(1U, num_successful) << "Only one thread should be able to set the limit.";
Christopher Ferrise9ffc522023-08-03 17:34:05 -0700959 _exit(0);
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -0800960}
961#endif
962
963TEST(android_mallopt, set_allocation_limit_multiple_threads) {
964#if defined(__BIONIC__)
965 if (IsDynamic()) {
966 ASSERT_TRUE(android_mallopt(M_INIT_ZYGOTE_CHILD_PROFILING, nullptr, 0));
967 }
968
969 // Run this a number of times as a stress test.
970 for (size_t i = 0; i < 100; i++) {
971 // Not using ASSERT_EXIT because errors messages are not displayed.
972 pid_t pid;
973 if ((pid = fork()) == 0) {
974 ASSERT_NO_FATAL_FAILURE(SetAllocationLimitMultipleThreads());
975 }
976 ASSERT_NE(-1, pid);
977 int status;
978 ASSERT_EQ(pid, wait(&status));
979 ASSERT_EQ(0, WEXITSTATUS(status));
980 }
981#else
Elliott Hughes10907202019-03-27 08:51:02 -0700982 GTEST_SKIP() << "bionic extension";
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -0800983#endif
984}
Peter Collingbourne5d3aa862020-09-11 15:05:17 -0700985
Christopher Ferris8f9713e2021-09-20 17:25:46 -0700986#if defined(__BIONIC__)
Mitch Phillipsebc2ac92024-05-02 13:25:46 +0200987using Mode = android_mallopt_gwp_asan_options_t::Mode;
Mitch Phillipse6997d52020-11-30 15:04:14 -0800988TEST(android_mallopt, DISABLED_multiple_enable_gwp_asan) {
989 android_mallopt_gwp_asan_options_t options;
990 options.program_name = ""; // Don't infer GWP-ASan options from sysprops.
Mitch Phillipsebc2ac92024-05-02 13:25:46 +0200991 options.mode = Mode::APP_MANIFEST_NEVER;
Mitch Phillipse6997d52020-11-30 15:04:14 -0800992 // GWP-ASan should already be enabled. Trying to enable or disable it should
993 // always pass.
994 ASSERT_TRUE(android_mallopt(M_INITIALIZE_GWP_ASAN, &options, sizeof(options)));
Mitch Phillipsebc2ac92024-05-02 13:25:46 +0200995 options.mode = Mode::APP_MANIFEST_DEFAULT;
Mitch Phillipse6997d52020-11-30 15:04:14 -0800996 ASSERT_TRUE(android_mallopt(M_INITIALIZE_GWP_ASAN, &options, sizeof(options)));
997}
998#endif // defined(__BIONIC__)
Christopher Ferris8f9713e2021-09-20 17:25:46 -0700999
Mitch Phillipse6997d52020-11-30 15:04:14 -08001000TEST(android_mallopt, multiple_enable_gwp_asan) {
1001#if defined(__BIONIC__)
1002 // Always enable GWP-Asan, with default options.
1003 RunGwpAsanTest("*.DISABLED_multiple_enable_gwp_asan");
Christopher Ferris8f9713e2021-09-20 17:25:46 -07001004#else
1005 GTEST_SKIP() << "bionic extension";
1006#endif
1007}
1008
Florian Mayercc61ad82022-08-31 11:43:30 -07001009TEST(android_mallopt, memtag_stack_is_on) {
1010#if defined(__BIONIC__)
1011 bool memtag_stack;
1012 EXPECT_TRUE(android_mallopt(M_MEMTAG_STACK_IS_ON, &memtag_stack, sizeof(memtag_stack)));
1013#else
1014 GTEST_SKIP() << "bionic extension";
1015#endif
1016}
1017
Mitch Phillips9cad8422021-01-20 16:03:27 -08001018void TestHeapZeroing(int num_iterations, int (*get_alloc_size)(int iteration)) {
1019 std::vector<void*> allocs;
1020 constexpr int kMaxBytesToCheckZero = 64;
1021 const char kBlankMemory[kMaxBytesToCheckZero] = {};
1022
1023 for (int i = 0; i < num_iterations; ++i) {
1024 int size = get_alloc_size(i);
1025 allocs.push_back(malloc(size));
1026 memset(allocs.back(), 'X', std::min(size, kMaxBytesToCheckZero));
1027 }
1028
1029 for (void* alloc : allocs) {
1030 free(alloc);
1031 }
1032 allocs.clear();
1033
1034 for (int i = 0; i < num_iterations; ++i) {
1035 int size = get_alloc_size(i);
1036 allocs.push_back(malloc(size));
1037 ASSERT_EQ(0, memcmp(allocs.back(), kBlankMemory, std::min(size, kMaxBytesToCheckZero)));
1038 }
1039
1040 for (void* alloc : allocs) {
1041 free(alloc);
1042 }
1043}
1044
1045TEST(malloc, zero_init) {
1046#if defined(__BIONIC__)
1047 SKIP_WITH_HWASAN << "hwasan does not implement mallopt";
1048 bool allocator_scudo;
1049 GetAllocatorVersion(&allocator_scudo);
1050 if (!allocator_scudo) {
1051 GTEST_SKIP() << "scudo allocator only test";
1052 }
1053
1054 mallopt(M_BIONIC_ZERO_INIT, 1);
1055
1056 // Test using a block of 4K small (1-32 byte) allocations.
1057 TestHeapZeroing(/* num_iterations */ 0x1000, [](int iteration) -> int {
1058 return 1 + iteration % 32;
1059 });
1060
1061 // Also test large allocations that land in the scudo secondary, as this is
1062 // the only part of Scudo that's changed by enabling zero initialization with
1063 // MTE. Uses 32 allocations, totalling 60MiB memory. Decay time (time to
1064 // release secondary allocations back to the OS) was modified to 0ms/1ms by
1065 // mallopt_decay. Ensure that we delay for at least a second before releasing
1066 // pages to the OS in order to avoid implicit zeroing by the kernel.
Chia-hung Duan6abb4062024-04-17 19:08:48 -07001067 mallopt(M_DECAY_TIME, 1);
Mitch Phillips9cad8422021-01-20 16:03:27 -08001068 TestHeapZeroing(/* num_iterations */ 32, [](int iteration) -> int {
1069 return 1 << (19 + iteration % 4);
1070 });
1071
1072#else
1073 GTEST_SKIP() << "bionic-only test";
1074#endif
1075}
1076
1077// Note that MTE is enabled on cc_tests on devices that support MTE.
1078TEST(malloc, disable_mte) {
Peter Collingbourne5d3aa862020-09-11 15:05:17 -07001079#if defined(__BIONIC__)
1080 if (!mte_supported()) {
1081 GTEST_SKIP() << "This function can only be tested with MTE";
1082 }
1083
Peter Collingbourne5d3aa862020-09-11 15:05:17 -07001084 sem_t sem;
1085 ASSERT_EQ(0, sem_init(&sem, 0, 0));
1086
1087 pthread_t thread;
1088 ASSERT_EQ(0, pthread_create(
1089 &thread, nullptr,
1090 [](void* ptr) -> void* {
1091 auto* sem = reinterpret_cast<sem_t*>(ptr);
1092 sem_wait(sem);
1093 return reinterpret_cast<void*>(prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0));
1094 },
1095 &sem));
1096
Mitch Phillips9cad8422021-01-20 16:03:27 -08001097 ASSERT_EQ(1, mallopt(M_BIONIC_SET_HEAP_TAGGING_LEVEL, M_HEAP_TAGGING_LEVEL_NONE));
Peter Collingbourne5d3aa862020-09-11 15:05:17 -07001098 ASSERT_EQ(0, sem_post(&sem));
1099
1100 int my_tagged_addr_ctrl = prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0);
Christopher Ferris2abfa9e2021-11-01 16:26:06 -07001101 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 -07001102
1103 void* retval;
1104 ASSERT_EQ(0, pthread_join(thread, &retval));
1105 int thread_tagged_addr_ctrl = reinterpret_cast<uintptr_t>(retval);
1106 ASSERT_EQ(my_tagged_addr_ctrl, thread_tagged_addr_ctrl);
Peter Collingbourne5d3aa862020-09-11 15:05:17 -07001107#else
1108 GTEST_SKIP() << "bionic extension";
1109#endif
1110}
Peter Collingbourne2659d7b2021-03-05 13:31:41 -08001111
1112TEST(malloc, allocation_slack) {
1113#if defined(__BIONIC__)
Christopher Ferris7c0ce862021-06-08 15:33:22 -07001114 SKIP_WITH_NATIVE_BRIDGE; // http://b/189606147
1115
Peter Collingbourne2659d7b2021-03-05 13:31:41 -08001116 bool allocator_scudo;
1117 GetAllocatorVersion(&allocator_scudo);
1118 if (!allocator_scudo) {
1119 GTEST_SKIP() << "scudo allocator only test";
1120 }
1121
1122 // Test that older target SDK levels let you access a few bytes off the end of
1123 // a large allocation.
1124 android_set_application_target_sdk_version(29);
1125 auto p = std::make_unique<char[]>(131072);
1126 volatile char *vp = p.get();
1127 volatile char oob ATTRIBUTE_UNUSED = vp[131072];
1128#else
1129 GTEST_SKIP() << "bionic extension";
1130#endif
1131}
Evgenii Stepanovf0d7a342021-11-16 17:34:39 -08001132
1133// Regression test for b/206701345 -- scudo bug, MTE only.
1134// Fix: https://reviews.llvm.org/D105261
1135// Fix: https://android-review.googlesource.com/c/platform/external/scudo/+/1763655
1136TEST(malloc, realloc_mte_crash_b206701345) {
1137 // We want to hit in-place realloc at the very end of an mmap-ed region. Not
1138 // all size classes allow such placement - mmap size has to be divisible by
1139 // the block size. At the time of writing this could only be reproduced with
1140 // 64 byte size class (i.e. 48 byte allocations), but that may change in the
1141 // future. Try several different classes at the lower end.
1142 std::vector<void*> ptrs(10000);
1143 for (int i = 1; i < 32; ++i) {
1144 size_t sz = 16 * i - 1;
1145 for (void*& p : ptrs) {
1146 p = realloc(malloc(sz), sz + 1);
1147 }
1148
1149 for (void* p : ptrs) {
1150 free(p);
1151 }
1152 }
1153}
Christopher Ferris02b6bbc2022-06-02 15:20:23 -07001154
Christopher Ferrisb4e560e2023-10-26 17:00:00 -07001155TEST(android_mallopt, get_decay_time_enabled_errors) {
1156#if defined(__BIONIC__)
1157 errno = 0;
1158 EXPECT_FALSE(android_mallopt(M_GET_DECAY_TIME_ENABLED, nullptr, sizeof(bool)));
1159 EXPECT_ERRNO(EINVAL);
1160
1161 errno = 0;
1162 int value;
1163 EXPECT_FALSE(android_mallopt(M_GET_DECAY_TIME_ENABLED, &value, sizeof(value)));
1164 EXPECT_ERRNO(EINVAL);
1165#else
1166 GTEST_SKIP() << "bionic-only test";
1167#endif
1168}
1169
1170TEST(android_mallopt, get_decay_time_enabled) {
1171#if defined(__BIONIC__)
1172 SKIP_WITH_HWASAN << "hwasan does not implement mallopt";
1173
1174 EXPECT_EQ(1, mallopt(M_DECAY_TIME, 0));
1175
1176 bool value;
1177 EXPECT_TRUE(android_mallopt(M_GET_DECAY_TIME_ENABLED, &value, sizeof(value)));
1178 EXPECT_FALSE(value);
1179
1180 EXPECT_EQ(1, mallopt(M_DECAY_TIME, 1));
1181 EXPECT_TRUE(android_mallopt(M_GET_DECAY_TIME_ENABLED, &value, sizeof(value)));
1182 EXPECT_TRUE(value);
Chia-hung Duan6abb4062024-04-17 19:08:48 -07001183
1184 EXPECT_EQ(1, mallopt(M_DECAY_TIME, -1));
1185 EXPECT_TRUE(android_mallopt(M_GET_DECAY_TIME_ENABLED, &value, sizeof(value)));
1186 EXPECT_FALSE(value);
Christopher Ferrisb4e560e2023-10-26 17:00:00 -07001187#else
1188 GTEST_SKIP() << "bionic-only test";
1189#endif
1190}
Christopher Ferris0b231992023-10-31 15:09:37 -07001191
1192TEST(android_mallopt, DISABLED_verify_decay_time_on) {
1193#if defined(__BIONIC__)
1194 bool value;
1195 EXPECT_TRUE(android_mallopt(M_GET_DECAY_TIME_ENABLED, &value, sizeof(value)));
1196 EXPECT_TRUE(value) << "decay time did not get enabled properly.";
1197#endif
1198}
1199
1200TEST(android_mallopt, decay_time_set_using_env_variable) {
1201#if defined(__BIONIC__)
1202 SKIP_WITH_HWASAN << "hwasan does not implement mallopt";
1203
1204 bool value;
1205 ASSERT_TRUE(android_mallopt(M_GET_DECAY_TIME_ENABLED, &value, sizeof(value)));
1206 ASSERT_FALSE(value) << "decay time did not get disabled properly.";
1207
1208 // Verify that setting the environment variable here will be carried into
1209 // fork'd and exec'd processes.
1210 ASSERT_EQ(0, setenv("MALLOC_USE_APP_DEFAULTS", "1", 1));
1211 ExecTestHelper eth;
Christopher Ferris10111be2025-03-13 17:55:39 +00001212 std::string executable(testing::internal::GetArgvs()[0]);
1213 eth.SetArgs({executable.c_str(), "--gtest_also_run_disabled_tests",
Christopher Ferris0b231992023-10-31 15:09:37 -07001214 "--gtest_filter=android_mallopt.DISABLED_verify_decay_time_on", nullptr});
Christopher Ferris10111be2025-03-13 17:55:39 +00001215 eth.Run([&]() { execv(executable.c_str(), eth.GetArgs()); }, 0, R"(\[ PASSED \] 1 test)");
Christopher Ferris0b231992023-10-31 15:09:37 -07001216#else
1217 GTEST_SKIP() << "bionic-only test";
1218#endif
1219}