blob: 20e6f16ae75c46c24297586b1c4c7c68ac12be60 [file] [log] [blame]
Christopher Ferris885f3b92013-05-21 17:48:01 -07001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <gtest/gtest.h>
18
Christopher Ferrise4cdbc42019-02-08 17:30:58 -080019#include <elf.h>
Christopher Ferrisa4037802014-06-09 19:14:11 -070020#include <limits.h>
Ryan Savitski175c8862020-01-02 19:54:57 +000021#include <malloc.h>
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -080022#include <pthread.h>
Ryan Savitski175c8862020-01-02 19:54:57 +000023#include <signal.h>
Christopher Ferrisa4037802014-06-09 19:14:11 -070024#include <stdint.h>
Christopher Ferris6c619a02019-03-01 17:59:51 -080025#include <stdio.h>
Christopher Ferris885f3b92013-05-21 17:48:01 -070026#include <stdlib.h>
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -080027#include <string.h>
28#include <sys/types.h>
29#include <sys/wait.h>
Christopher Ferrisa4037802014-06-09 19:14:11 -070030#include <unistd.h>
Christopher Ferris885f3b92013-05-21 17:48:01 -070031
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -080032#include <atomic>
Christopher Ferrisf32494c2020-01-08 14:19:10 -080033#include <thread>
34
Dan Albert4caa1f02014-08-20 09:16:57 -070035#include <tinyxml2.h>
36
Christopher Ferrise4cdbc42019-02-08 17:30:58 -080037#include <android-base/file.h>
38
Christopher Ferris2b0638e2019-09-11 19:05:29 -070039#include "platform/bionic/malloc.h"
Christopher Ferris63619642014-06-16 23:35:53 -070040#include "private/bionic_config.h"
Evgenii Stepanovacd6f4f2018-11-06 16:48:27 -080041#include "utils.h"
Dan Alberte5fdaa42014-06-14 01:04:31 +000042
Elliott Hughesb1770852018-09-18 12:52:42 -070043#if defined(__BIONIC__)
44#define HAVE_REALLOCARRAY 1
45#else
46#define HAVE_REALLOCARRAY __GLIBC_PREREQ(2, 26)
47#endif
48
Christopher Ferris885f3b92013-05-21 17:48:01 -070049TEST(malloc, malloc_std) {
50 // Simple malloc test.
51 void *ptr = malloc(100);
Yi Kong32bc0fc2018-08-02 17:31:13 -070052 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -070053 ASSERT_LE(100U, malloc_usable_size(ptr));
Christopher Ferris885f3b92013-05-21 17:48:01 -070054 free(ptr);
55}
56
Christopher Ferrisa4037802014-06-09 19:14:11 -070057TEST(malloc, malloc_overflow) {
Evgenii Stepanovacd6f4f2018-11-06 16:48:27 -080058 SKIP_WITH_HWASAN;
Christopher Ferrisa4037802014-06-09 19:14:11 -070059 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -070060 ASSERT_EQ(nullptr, malloc(SIZE_MAX));
Christopher Ferrisa4037802014-06-09 19:14:11 -070061 ASSERT_EQ(ENOMEM, errno);
62}
63
Christopher Ferris885f3b92013-05-21 17:48:01 -070064TEST(malloc, calloc_std) {
65 // Simple calloc test.
66 size_t alloc_len = 100;
67 char *ptr = (char *)calloc(1, alloc_len);
Yi Kong32bc0fc2018-08-02 17:31:13 -070068 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -070069 ASSERT_LE(alloc_len, malloc_usable_size(ptr));
70 for (size_t i = 0; i < alloc_len; i++) {
71 ASSERT_EQ(0, ptr[i]);
72 }
Christopher Ferris885f3b92013-05-21 17:48:01 -070073 free(ptr);
74}
75
Christopher Ferrisa4037802014-06-09 19:14:11 -070076TEST(malloc, calloc_illegal) {
Evgenii Stepanovacd6f4f2018-11-06 16:48:27 -080077 SKIP_WITH_HWASAN;
Christopher Ferrisa4037802014-06-09 19:14:11 -070078 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -070079 ASSERT_EQ(nullptr, calloc(-1, 100));
Christopher Ferrisa4037802014-06-09 19:14:11 -070080 ASSERT_EQ(ENOMEM, errno);
81}
82
83TEST(malloc, calloc_overflow) {
Evgenii Stepanovacd6f4f2018-11-06 16:48:27 -080084 SKIP_WITH_HWASAN;
Christopher Ferrisa4037802014-06-09 19:14:11 -070085 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -070086 ASSERT_EQ(nullptr, calloc(1, SIZE_MAX));
Christopher Ferrisa4037802014-06-09 19:14:11 -070087 ASSERT_EQ(ENOMEM, errno);
88 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -070089 ASSERT_EQ(nullptr, calloc(SIZE_MAX, SIZE_MAX));
Christopher Ferrisa4037802014-06-09 19:14:11 -070090 ASSERT_EQ(ENOMEM, errno);
91 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -070092 ASSERT_EQ(nullptr, calloc(2, SIZE_MAX));
Christopher Ferrisa4037802014-06-09 19:14:11 -070093 ASSERT_EQ(ENOMEM, errno);
94 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -070095 ASSERT_EQ(nullptr, calloc(SIZE_MAX, 2));
Christopher Ferrisa4037802014-06-09 19:14:11 -070096 ASSERT_EQ(ENOMEM, errno);
97}
98
Christopher Ferris885f3b92013-05-21 17:48:01 -070099TEST(malloc, memalign_multiple) {
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800100 SKIP_WITH_HWASAN << "hwasan requires power of 2 alignment";
Christopher Ferris885f3b92013-05-21 17:48:01 -0700101 // Memalign test where the alignment is any value.
102 for (size_t i = 0; i <= 12; i++) {
103 for (size_t alignment = 1 << i; alignment < (1U << (i+1)); alignment++) {
Christopher Ferrisa4037802014-06-09 19:14:11 -0700104 char *ptr = reinterpret_cast<char*>(memalign(alignment, 100));
Yi Kong32bc0fc2018-08-02 17:31:13 -0700105 ASSERT_TRUE(ptr != nullptr) << "Failed at alignment " << alignment;
Christopher Ferrisa4037802014-06-09 19:14:11 -0700106 ASSERT_LE(100U, malloc_usable_size(ptr)) << "Failed at alignment " << alignment;
107 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(ptr) % ((1U << i)))
108 << "Failed at alignment " << alignment;
Christopher Ferris885f3b92013-05-21 17:48:01 -0700109 free(ptr);
110 }
111 }
112}
113
Christopher Ferrisa4037802014-06-09 19:14:11 -0700114TEST(malloc, memalign_overflow) {
Evgenii Stepanovacd6f4f2018-11-06 16:48:27 -0800115 SKIP_WITH_HWASAN;
Yi Kong32bc0fc2018-08-02 17:31:13 -0700116 ASSERT_EQ(nullptr, memalign(4096, SIZE_MAX));
Christopher Ferrisa4037802014-06-09 19:14:11 -0700117}
118
119TEST(malloc, memalign_non_power2) {
Evgenii Stepanovacd6f4f2018-11-06 16:48:27 -0800120 SKIP_WITH_HWASAN;
Christopher Ferrisa4037802014-06-09 19:14:11 -0700121 void* ptr;
122 for (size_t align = 0; align <= 256; align++) {
123 ptr = memalign(align, 1024);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700124 ASSERT_TRUE(ptr != nullptr) << "Failed at align " << align;
Christopher Ferrisa4037802014-06-09 19:14:11 -0700125 free(ptr);
126 }
127}
128
Christopher Ferris885f3b92013-05-21 17:48:01 -0700129TEST(malloc, memalign_realloc) {
130 // Memalign and then realloc the pointer a couple of times.
131 for (size_t alignment = 1; alignment <= 4096; alignment <<= 1) {
132 char *ptr = (char*)memalign(alignment, 100);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700133 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700134 ASSERT_LE(100U, malloc_usable_size(ptr));
135 ASSERT_EQ(0U, (intptr_t)ptr % alignment);
136 memset(ptr, 0x23, 100);
137
138 ptr = (char*)realloc(ptr, 200);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700139 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700140 ASSERT_LE(200U, malloc_usable_size(ptr));
Yi Kong32bc0fc2018-08-02 17:31:13 -0700141 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700142 for (size_t i = 0; i < 100; i++) {
143 ASSERT_EQ(0x23, ptr[i]);
144 }
145 memset(ptr, 0x45, 200);
146
147 ptr = (char*)realloc(ptr, 300);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700148 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700149 ASSERT_LE(300U, malloc_usable_size(ptr));
150 for (size_t i = 0; i < 200; i++) {
151 ASSERT_EQ(0x45, ptr[i]);
152 }
153 memset(ptr, 0x67, 300);
154
155 ptr = (char*)realloc(ptr, 250);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700156 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700157 ASSERT_LE(250U, malloc_usable_size(ptr));
158 for (size_t i = 0; i < 250; i++) {
159 ASSERT_EQ(0x67, ptr[i]);
160 }
Christopher Ferris885f3b92013-05-21 17:48:01 -0700161 free(ptr);
162 }
163}
164
165TEST(malloc, malloc_realloc_larger) {
166 // Realloc to a larger size, malloc is used for the original allocation.
167 char *ptr = (char *)malloc(100);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700168 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700169 ASSERT_LE(100U, malloc_usable_size(ptr));
170 memset(ptr, 67, 100);
171
172 ptr = (char *)realloc(ptr, 200);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700173 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700174 ASSERT_LE(200U, malloc_usable_size(ptr));
175 for (size_t i = 0; i < 100; i++) {
176 ASSERT_EQ(67, ptr[i]);
177 }
Christopher Ferris885f3b92013-05-21 17:48:01 -0700178 free(ptr);
179}
180
181TEST(malloc, malloc_realloc_smaller) {
182 // Realloc to a smaller size, malloc is used for the original allocation.
183 char *ptr = (char *)malloc(200);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700184 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700185 ASSERT_LE(200U, malloc_usable_size(ptr));
186 memset(ptr, 67, 200);
187
188 ptr = (char *)realloc(ptr, 100);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700189 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700190 ASSERT_LE(100U, malloc_usable_size(ptr));
191 for (size_t i = 0; i < 100; i++) {
192 ASSERT_EQ(67, ptr[i]);
193 }
Christopher Ferris885f3b92013-05-21 17:48:01 -0700194 free(ptr);
195}
196
197TEST(malloc, malloc_multiple_realloc) {
198 // Multiple reallocs, malloc is used for the original allocation.
199 char *ptr = (char *)malloc(200);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700200 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700201 ASSERT_LE(200U, malloc_usable_size(ptr));
202 memset(ptr, 0x23, 200);
203
204 ptr = (char *)realloc(ptr, 100);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700205 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700206 ASSERT_LE(100U, malloc_usable_size(ptr));
207 for (size_t i = 0; i < 100; i++) {
208 ASSERT_EQ(0x23, ptr[i]);
209 }
210
211 ptr = (char*)realloc(ptr, 50);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700212 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700213 ASSERT_LE(50U, malloc_usable_size(ptr));
214 for (size_t i = 0; i < 50; i++) {
215 ASSERT_EQ(0x23, ptr[i]);
216 }
217
218 ptr = (char*)realloc(ptr, 150);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700219 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700220 ASSERT_LE(150U, malloc_usable_size(ptr));
221 for (size_t i = 0; i < 50; i++) {
222 ASSERT_EQ(0x23, ptr[i]);
223 }
224 memset(ptr, 0x23, 150);
225
226 ptr = (char*)realloc(ptr, 425);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700227 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700228 ASSERT_LE(425U, malloc_usable_size(ptr));
229 for (size_t i = 0; i < 150; i++) {
230 ASSERT_EQ(0x23, ptr[i]);
231 }
Christopher Ferris885f3b92013-05-21 17:48:01 -0700232 free(ptr);
233}
Christopher Ferrisa4037802014-06-09 19:14:11 -0700234
Christopher Ferris885f3b92013-05-21 17:48:01 -0700235TEST(malloc, calloc_realloc_larger) {
236 // Realloc to a larger size, calloc is used for the original allocation.
237 char *ptr = (char *)calloc(1, 100);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700238 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700239 ASSERT_LE(100U, malloc_usable_size(ptr));
240
241 ptr = (char *)realloc(ptr, 200);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700242 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700243 ASSERT_LE(200U, malloc_usable_size(ptr));
244 for (size_t i = 0; i < 100; i++) {
245 ASSERT_EQ(0, ptr[i]);
246 }
Christopher Ferris885f3b92013-05-21 17:48:01 -0700247 free(ptr);
248}
249
250TEST(malloc, calloc_realloc_smaller) {
251 // Realloc to a smaller size, calloc is used for the original allocation.
252 char *ptr = (char *)calloc(1, 200);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700253 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700254 ASSERT_LE(200U, malloc_usable_size(ptr));
255
256 ptr = (char *)realloc(ptr, 100);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700257 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700258 ASSERT_LE(100U, malloc_usable_size(ptr));
259 for (size_t i = 0; i < 100; i++) {
260 ASSERT_EQ(0, ptr[i]);
261 }
Christopher Ferris885f3b92013-05-21 17:48:01 -0700262 free(ptr);
263}
264
265TEST(malloc, calloc_multiple_realloc) {
266 // Multiple reallocs, calloc is used for the original allocation.
267 char *ptr = (char *)calloc(1, 200);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700268 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700269 ASSERT_LE(200U, malloc_usable_size(ptr));
270
271 ptr = (char *)realloc(ptr, 100);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700272 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700273 ASSERT_LE(100U, malloc_usable_size(ptr));
274 for (size_t i = 0; i < 100; i++) {
275 ASSERT_EQ(0, ptr[i]);
276 }
277
278 ptr = (char*)realloc(ptr, 50);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700279 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700280 ASSERT_LE(50U, malloc_usable_size(ptr));
281 for (size_t i = 0; i < 50; i++) {
282 ASSERT_EQ(0, ptr[i]);
283 }
284
285 ptr = (char*)realloc(ptr, 150);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700286 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700287 ASSERT_LE(150U, malloc_usable_size(ptr));
288 for (size_t i = 0; i < 50; i++) {
289 ASSERT_EQ(0, ptr[i]);
290 }
291 memset(ptr, 0, 150);
292
293 ptr = (char*)realloc(ptr, 425);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700294 ASSERT_TRUE(ptr != nullptr);
Christopher Ferris885f3b92013-05-21 17:48:01 -0700295 ASSERT_LE(425U, malloc_usable_size(ptr));
296 for (size_t i = 0; i < 150; i++) {
297 ASSERT_EQ(0, ptr[i]);
298 }
Christopher Ferris885f3b92013-05-21 17:48:01 -0700299 free(ptr);
300}
Christopher Ferris72bbd422014-05-08 11:14:03 -0700301
Christopher Ferrisa4037802014-06-09 19:14:11 -0700302TEST(malloc, realloc_overflow) {
Evgenii Stepanovacd6f4f2018-11-06 16:48:27 -0800303 SKIP_WITH_HWASAN;
Christopher Ferrisa4037802014-06-09 19:14:11 -0700304 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -0700305 ASSERT_EQ(nullptr, realloc(nullptr, SIZE_MAX));
Christopher Ferrisa4037802014-06-09 19:14:11 -0700306 ASSERT_EQ(ENOMEM, errno);
307 void* ptr = malloc(100);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700308 ASSERT_TRUE(ptr != nullptr);
Christopher Ferrisa4037802014-06-09 19:14:11 -0700309 errno = 0;
Yi Kong32bc0fc2018-08-02 17:31:13 -0700310 ASSERT_EQ(nullptr, realloc(ptr, SIZE_MAX));
Christopher Ferrisa4037802014-06-09 19:14:11 -0700311 ASSERT_EQ(ENOMEM, errno);
312 free(ptr);
Christopher Ferris72bbd422014-05-08 11:14:03 -0700313}
314
Dan Alberte5fdaa42014-06-14 01:04:31 +0000315#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
316extern "C" void* pvalloc(size_t);
317extern "C" void* valloc(size_t);
Christopher Ferris804cebe2019-06-20 08:50:23 -0700318#endif
Dan Alberte5fdaa42014-06-14 01:04:31 +0000319
Christopher Ferrisa4037802014-06-09 19:14:11 -0700320TEST(malloc, pvalloc_std) {
Christopher Ferris804cebe2019-06-20 08:50:23 -0700321#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
Christopher Ferrisa4037802014-06-09 19:14:11 -0700322 size_t pagesize = sysconf(_SC_PAGESIZE);
323 void* ptr = pvalloc(100);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700324 ASSERT_TRUE(ptr != nullptr);
Christopher Ferrisa4037802014-06-09 19:14:11 -0700325 ASSERT_TRUE((reinterpret_cast<uintptr_t>(ptr) & (pagesize-1)) == 0);
326 ASSERT_LE(pagesize, malloc_usable_size(ptr));
327 free(ptr);
Christopher Ferris804cebe2019-06-20 08:50:23 -0700328#else
329 GTEST_SKIP() << "pvalloc not supported.";
330#endif
Christopher Ferrisa4037802014-06-09 19:14:11 -0700331}
332
333TEST(malloc, pvalloc_overflow) {
Christopher Ferris804cebe2019-06-20 08:50:23 -0700334#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
Yi Kong32bc0fc2018-08-02 17:31:13 -0700335 ASSERT_EQ(nullptr, pvalloc(SIZE_MAX));
Christopher Ferris804cebe2019-06-20 08:50:23 -0700336#else
337 GTEST_SKIP() << "pvalloc not supported.";
338#endif
Christopher Ferrisa4037802014-06-09 19:14:11 -0700339}
340
341TEST(malloc, valloc_std) {
Christopher Ferris804cebe2019-06-20 08:50:23 -0700342#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
Christopher Ferrisa4037802014-06-09 19:14:11 -0700343 size_t pagesize = sysconf(_SC_PAGESIZE);
Christopher Ferrisd5ab0a52019-06-19 12:03:57 -0700344 void* ptr = valloc(100);
Yi Kong32bc0fc2018-08-02 17:31:13 -0700345 ASSERT_TRUE(ptr != nullptr);
Christopher Ferrisa4037802014-06-09 19:14:11 -0700346 ASSERT_TRUE((reinterpret_cast<uintptr_t>(ptr) & (pagesize-1)) == 0);
347 free(ptr);
Christopher Ferris804cebe2019-06-20 08:50:23 -0700348#else
349 GTEST_SKIP() << "valloc not supported.";
350#endif
Christopher Ferrisa4037802014-06-09 19:14:11 -0700351}
352
353TEST(malloc, valloc_overflow) {
Christopher Ferris804cebe2019-06-20 08:50:23 -0700354#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
Yi Kong32bc0fc2018-08-02 17:31:13 -0700355 ASSERT_EQ(nullptr, valloc(SIZE_MAX));
Christopher Ferris804cebe2019-06-20 08:50:23 -0700356#else
357 GTEST_SKIP() << "valloc not supported.";
Dan Alberte5fdaa42014-06-14 01:04:31 +0000358#endif
Christopher Ferris804cebe2019-06-20 08:50:23 -0700359}
Dan Albert4caa1f02014-08-20 09:16:57 -0700360
361TEST(malloc, malloc_info) {
362#ifdef __BIONIC__
Evgenii Stepanov8de6b462019-03-22 13:22:28 -0700363 SKIP_WITH_HWASAN; // hwasan does not implement malloc_info
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800364
365 TemporaryFile tf;
366 ASSERT_TRUE(tf.fd != -1);
367 FILE* fp = fdopen(tf.fd, "w+");
368 tf.release();
369 ASSERT_TRUE(fp != nullptr);
370 ASSERT_EQ(0, malloc_info(0, fp));
371 ASSERT_EQ(0, fclose(fp));
372
373 std::string contents;
374 ASSERT_TRUE(android::base::ReadFileToString(tf.path, &contents));
Dan Albert4caa1f02014-08-20 09:16:57 -0700375
376 tinyxml2::XMLDocument doc;
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800377 ASSERT_EQ(tinyxml2::XML_SUCCESS, doc.Parse(contents.c_str()));
Dan Albert4caa1f02014-08-20 09:16:57 -0700378
379 auto root = doc.FirstChildElement();
380 ASSERT_NE(nullptr, root);
381 ASSERT_STREQ("malloc", root->Name());
Christopher Ferris85169652019-10-09 18:41:55 -0700382 std::string version(root->Attribute("version"));
383 if (version == "jemalloc-1") {
Christopher Ferris6c619a02019-03-01 17:59:51 -0800384 // Verify jemalloc version of this data.
385 ASSERT_STREQ("jemalloc-1", root->Attribute("version"));
Dan Albert4caa1f02014-08-20 09:16:57 -0700386
Christopher Ferris6c619a02019-03-01 17:59:51 -0800387 auto arena = root->FirstChildElement();
388 for (; arena != nullptr; arena = arena->NextSiblingElement()) {
389 int val;
Dan Albert4caa1f02014-08-20 09:16:57 -0700390
Christopher Ferris6c619a02019-03-01 17:59:51 -0800391 ASSERT_STREQ("heap", arena->Name());
392 ASSERT_EQ(tinyxml2::XML_SUCCESS, arena->QueryIntAttribute("nr", &val));
393 ASSERT_EQ(tinyxml2::XML_SUCCESS,
394 arena->FirstChildElement("allocated-large")->QueryIntText(&val));
395 ASSERT_EQ(tinyxml2::XML_SUCCESS,
396 arena->FirstChildElement("allocated-huge")->QueryIntText(&val));
397 ASSERT_EQ(tinyxml2::XML_SUCCESS,
398 arena->FirstChildElement("allocated-bins")->QueryIntText(&val));
399 ASSERT_EQ(tinyxml2::XML_SUCCESS,
400 arena->FirstChildElement("bins-total")->QueryIntText(&val));
Dan Albert4caa1f02014-08-20 09:16:57 -0700401
Christopher Ferris6c619a02019-03-01 17:59:51 -0800402 auto bin = arena->FirstChildElement("bin");
403 for (; bin != nullptr; bin = bin ->NextSiblingElement()) {
404 if (strcmp(bin->Name(), "bin") == 0) {
405 ASSERT_EQ(tinyxml2::XML_SUCCESS, bin->QueryIntAttribute("nr", &val));
406 ASSERT_EQ(tinyxml2::XML_SUCCESS,
407 bin->FirstChildElement("allocated")->QueryIntText(&val));
408 ASSERT_EQ(tinyxml2::XML_SUCCESS,
409 bin->FirstChildElement("nmalloc")->QueryIntText(&val));
410 ASSERT_EQ(tinyxml2::XML_SUCCESS,
411 bin->FirstChildElement("ndalloc")->QueryIntText(&val));
412 }
Dan Albert4caa1f02014-08-20 09:16:57 -0700413 }
414 }
Christopher Ferris6c619a02019-03-01 17:59:51 -0800415 } else {
Christopher Ferris85169652019-10-09 18:41:55 -0700416 // Do not verify output for scudo or debug malloc.
417 ASSERT_TRUE(version == "scudo-1" || version == "debug-malloc-1")
418 << "Unknown version: " << version;
Dan Albert4caa1f02014-08-20 09:16:57 -0700419 }
420#endif
421}
Christopher Ferrisad33ebe2015-12-16 12:07:25 -0800422
Christopher Ferrisdb9706a2019-05-02 18:33:11 -0700423TEST(malloc, malloc_info_matches_mallinfo) {
424#ifdef __BIONIC__
425 SKIP_WITH_HWASAN; // hwasan does not implement malloc_info
426
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800427 TemporaryFile tf;
428 ASSERT_TRUE(tf.fd != -1);
429 FILE* fp = fdopen(tf.fd, "w+");
430 tf.release();
431 ASSERT_TRUE(fp != nullptr);
Christopher Ferrisdb9706a2019-05-02 18:33:11 -0700432 size_t mallinfo_before_allocated_bytes = mallinfo().uordblks;
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800433 ASSERT_EQ(0, malloc_info(0, fp));
Christopher Ferrisdb9706a2019-05-02 18:33:11 -0700434 size_t mallinfo_after_allocated_bytes = mallinfo().uordblks;
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800435 ASSERT_EQ(0, fclose(fp));
436
437 std::string contents;
438 ASSERT_TRUE(android::base::ReadFileToString(tf.path, &contents));
Christopher Ferrisdb9706a2019-05-02 18:33:11 -0700439
440 tinyxml2::XMLDocument doc;
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800441 ASSERT_EQ(tinyxml2::XML_SUCCESS, doc.Parse(contents.c_str()));
Christopher Ferrisdb9706a2019-05-02 18:33:11 -0700442
443 size_t total_allocated_bytes = 0;
444 auto root = doc.FirstChildElement();
445 ASSERT_NE(nullptr, root);
446 ASSERT_STREQ("malloc", root->Name());
Christopher Ferris85169652019-10-09 18:41:55 -0700447 std::string version(root->Attribute("version"));
448 if (version == "jemalloc-1") {
Christopher Ferrisdb9706a2019-05-02 18:33:11 -0700449 // Verify jemalloc version of this data.
450 ASSERT_STREQ("jemalloc-1", root->Attribute("version"));
451
452 auto arena = root->FirstChildElement();
453 for (; arena != nullptr; arena = arena->NextSiblingElement()) {
454 int val;
455
456 ASSERT_STREQ("heap", arena->Name());
457 ASSERT_EQ(tinyxml2::XML_SUCCESS, arena->QueryIntAttribute("nr", &val));
458 ASSERT_EQ(tinyxml2::XML_SUCCESS,
459 arena->FirstChildElement("allocated-large")->QueryIntText(&val));
460 total_allocated_bytes += val;
461 ASSERT_EQ(tinyxml2::XML_SUCCESS,
462 arena->FirstChildElement("allocated-huge")->QueryIntText(&val));
463 total_allocated_bytes += val;
464 ASSERT_EQ(tinyxml2::XML_SUCCESS,
465 arena->FirstChildElement("allocated-bins")->QueryIntText(&val));
466 total_allocated_bytes += val;
467 ASSERT_EQ(tinyxml2::XML_SUCCESS,
468 arena->FirstChildElement("bins-total")->QueryIntText(&val));
469 }
470 // The total needs to be between the mallinfo call before and after
471 // since malloc_info allocates some memory.
472 EXPECT_LE(mallinfo_before_allocated_bytes, total_allocated_bytes);
473 EXPECT_GE(mallinfo_after_allocated_bytes, total_allocated_bytes);
474 } else {
Christopher Ferris85169652019-10-09 18:41:55 -0700475 // Do not verify output for scudo or debug malloc.
476 ASSERT_TRUE(version == "scudo-1" || version == "debug-malloc-1")
477 << "Unknown version: " << version;
Christopher Ferrisdb9706a2019-05-02 18:33:11 -0700478 }
479#endif
480}
481
Christopher Ferrisad33ebe2015-12-16 12:07:25 -0800482TEST(malloc, calloc_usable_size) {
483 for (size_t size = 1; size <= 2048; size++) {
484 void* pointer = malloc(size);
485 ASSERT_TRUE(pointer != nullptr);
486 memset(pointer, 0xeb, malloc_usable_size(pointer));
487 free(pointer);
488
489 // We should get a previous pointer that has been set to non-zero.
490 // If calloc does not zero out all of the data, this will fail.
491 uint8_t* zero_mem = reinterpret_cast<uint8_t*>(calloc(1, size));
492 ASSERT_TRUE(pointer != nullptr);
493 size_t usable_size = malloc_usable_size(zero_mem);
494 for (size_t i = 0; i < usable_size; i++) {
495 ASSERT_EQ(0, zero_mem[i]) << "Failed at allocation size " << size << " at byte " << i;
496 }
497 free(zero_mem);
498 }
499}
Elliott Hughes884f76e2016-02-10 20:43:22 -0800500
501TEST(malloc, malloc_0) {
502 void* p = malloc(0);
503 ASSERT_TRUE(p != nullptr);
504 free(p);
505}
506
507TEST(malloc, calloc_0_0) {
508 void* p = calloc(0, 0);
509 ASSERT_TRUE(p != nullptr);
510 free(p);
511}
512
513TEST(malloc, calloc_0_1) {
514 void* p = calloc(0, 1);
515 ASSERT_TRUE(p != nullptr);
516 free(p);
517}
518
519TEST(malloc, calloc_1_0) {
520 void* p = calloc(1, 0);
521 ASSERT_TRUE(p != nullptr);
522 free(p);
523}
524
525TEST(malloc, realloc_nullptr_0) {
526 // realloc(nullptr, size) is actually malloc(size).
527 void* p = realloc(nullptr, 0);
528 ASSERT_TRUE(p != nullptr);
529 free(p);
530}
531
532TEST(malloc, realloc_0) {
533 void* p = malloc(1024);
534 ASSERT_TRUE(p != nullptr);
535 // realloc(p, 0) is actually free(p).
536 void* p2 = realloc(p, 0);
537 ASSERT_TRUE(p2 == nullptr);
538}
Christopher Ferris72df6702016-02-11 15:51:31 -0800539
540constexpr size_t MAX_LOOPS = 200;
541
542// Make sure that memory returned by malloc is aligned to allow these data types.
543TEST(malloc, verify_alignment) {
544 uint32_t** values_32 = new uint32_t*[MAX_LOOPS];
545 uint64_t** values_64 = new uint64_t*[MAX_LOOPS];
546 long double** values_ldouble = new long double*[MAX_LOOPS];
547 // Use filler to attempt to force the allocator to get potentially bad alignments.
548 void** filler = new void*[MAX_LOOPS];
549
550 for (size_t i = 0; i < MAX_LOOPS; i++) {
551 // Check uint32_t pointers.
552 filler[i] = malloc(1);
553 ASSERT_TRUE(filler[i] != nullptr);
554
555 values_32[i] = reinterpret_cast<uint32_t*>(malloc(sizeof(uint32_t)));
556 ASSERT_TRUE(values_32[i] != nullptr);
557 *values_32[i] = i;
558 ASSERT_EQ(*values_32[i], i);
559 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(values_32[i]) & (sizeof(uint32_t) - 1));
560
561 free(filler[i]);
562 }
563
564 for (size_t i = 0; i < MAX_LOOPS; i++) {
565 // Check uint64_t pointers.
566 filler[i] = malloc(1);
567 ASSERT_TRUE(filler[i] != nullptr);
568
569 values_64[i] = reinterpret_cast<uint64_t*>(malloc(sizeof(uint64_t)));
570 ASSERT_TRUE(values_64[i] != nullptr);
571 *values_64[i] = 0x1000 + i;
572 ASSERT_EQ(*values_64[i], 0x1000 + i);
573 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(values_64[i]) & (sizeof(uint64_t) - 1));
574
575 free(filler[i]);
576 }
577
578 for (size_t i = 0; i < MAX_LOOPS; i++) {
579 // Check long double pointers.
580 filler[i] = malloc(1);
581 ASSERT_TRUE(filler[i] != nullptr);
582
583 values_ldouble[i] = reinterpret_cast<long double*>(malloc(sizeof(long double)));
584 ASSERT_TRUE(values_ldouble[i] != nullptr);
585 *values_ldouble[i] = 5.5 + i;
586 ASSERT_DOUBLE_EQ(*values_ldouble[i], 5.5 + i);
587 // 32 bit glibc has a long double size of 12 bytes, so hardcode the
588 // required alignment to 0x7.
589#if !defined(__BIONIC__) && !defined(__LP64__)
590 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(values_ldouble[i]) & 0x7);
591#else
592 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(values_ldouble[i]) & (sizeof(long double) - 1));
593#endif
594
595 free(filler[i]);
596 }
597
598 for (size_t i = 0; i < MAX_LOOPS; i++) {
599 free(values_32[i]);
600 free(values_64[i]);
601 free(values_ldouble[i]);
602 }
603
604 delete[] filler;
605 delete[] values_32;
606 delete[] values_64;
607 delete[] values_ldouble;
608}
Christopher Ferrisa1c0d2f2017-05-15 15:50:19 -0700609
610TEST(malloc, mallopt_smoke) {
611 errno = 0;
612 ASSERT_EQ(0, mallopt(-1000, 1));
613 // mallopt doesn't set errno.
614 ASSERT_EQ(0, errno);
615}
Elliott Hughesb1770852018-09-18 12:52:42 -0700616
Christopher Ferrisaf1b8dd2018-11-07 15:28:16 -0800617TEST(malloc, mallopt_decay) {
618#if defined(__BIONIC__)
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800619 SKIP_WITH_HWASAN << "hwasan does not implement mallopt";
Christopher Ferrisaf1b8dd2018-11-07 15:28:16 -0800620 errno = 0;
621 ASSERT_EQ(1, mallopt(M_DECAY_TIME, 1));
622 ASSERT_EQ(1, mallopt(M_DECAY_TIME, 0));
623 ASSERT_EQ(1, mallopt(M_DECAY_TIME, 1));
624 ASSERT_EQ(1, mallopt(M_DECAY_TIME, 0));
625#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800626 GTEST_SKIP() << "bionic-only test";
Christopher Ferrisaf1b8dd2018-11-07 15:28:16 -0800627#endif
628}
629
630TEST(malloc, mallopt_purge) {
631#if defined(__BIONIC__)
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800632 SKIP_WITH_HWASAN << "hwasan does not implement mallopt";
Christopher Ferrisaf1b8dd2018-11-07 15:28:16 -0800633 errno = 0;
634 ASSERT_EQ(1, mallopt(M_PURGE, 0));
635#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800636 GTEST_SKIP() << "bionic-only test";
Christopher Ferrisaf1b8dd2018-11-07 15:28:16 -0800637#endif
638}
639
Elliott Hughesb1770852018-09-18 12:52:42 -0700640TEST(malloc, reallocarray_overflow) {
641#if HAVE_REALLOCARRAY
642 // Values that cause overflow to a result small enough (8 on LP64) that malloc would "succeed".
643 size_t a = static_cast<size_t>(INTPTR_MIN + 4);
644 size_t b = 2;
645
646 errno = 0;
647 ASSERT_TRUE(reallocarray(nullptr, a, b) == nullptr);
648 ASSERT_EQ(ENOMEM, errno);
649
650 errno = 0;
651 ASSERT_TRUE(reallocarray(nullptr, b, a) == nullptr);
652 ASSERT_EQ(ENOMEM, errno);
653#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800654 GTEST_SKIP() << "reallocarray not available";
Elliott Hughesb1770852018-09-18 12:52:42 -0700655#endif
656}
657
658TEST(malloc, reallocarray) {
659#if HAVE_REALLOCARRAY
660 void* p = reallocarray(nullptr, 2, 32);
661 ASSERT_TRUE(p != nullptr);
662 ASSERT_GE(malloc_usable_size(p), 64U);
663#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800664 GTEST_SKIP() << "reallocarray not available";
Elliott Hughesb1770852018-09-18 12:52:42 -0700665#endif
666}
Christopher Ferris09a19aa2018-11-16 13:28:56 -0800667
668TEST(malloc, mallinfo) {
669#if defined(__BIONIC__)
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800670 SKIP_WITH_HWASAN << "hwasan does not implement mallinfo";
Christopher Ferris09a19aa2018-11-16 13:28:56 -0800671 static size_t sizes[] = {
672 8, 32, 128, 4096, 32768, 131072, 1024000, 10240000, 20480000, 300000000
673 };
674
675 constexpr static size_t kMaxAllocs = 50;
676
677 for (size_t size : sizes) {
678 // If some of these allocations are stuck in a thread cache, then keep
679 // looping until we make an allocation that changes the total size of the
680 // memory allocated.
681 // jemalloc implementations counts the thread cache allocations against
682 // total memory allocated.
683 void* ptrs[kMaxAllocs] = {};
684 bool pass = false;
685 for (size_t i = 0; i < kMaxAllocs; i++) {
686 size_t allocated = mallinfo().uordblks;
687 ptrs[i] = malloc(size);
688 ASSERT_TRUE(ptrs[i] != nullptr);
689 size_t new_allocated = mallinfo().uordblks;
690 if (allocated != new_allocated) {
691 size_t usable_size = malloc_usable_size(ptrs[i]);
Christopher Ferris4e562282019-02-07 14:20:03 -0800692 // Only check if the total got bigger by at least allocation size.
693 // Sometimes the mallinfo numbers can go backwards due to compaction
694 // and/or freeing of cached data.
695 if (new_allocated >= allocated + usable_size) {
696 pass = true;
697 break;
698 }
Christopher Ferris09a19aa2018-11-16 13:28:56 -0800699 }
700 }
701 for (void* ptr : ptrs) {
702 free(ptr);
703 }
704 ASSERT_TRUE(pass)
705 << "For size " << size << " allocated bytes did not increase after "
706 << kMaxAllocs << " allocations.";
707 }
708#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800709 GTEST_SKIP() << "glibc is broken";
Christopher Ferris09a19aa2018-11-16 13:28:56 -0800710#endif
711}
Ryan Savitskiecc37e32018-12-14 15:57:21 +0000712
Christopher Ferrisf32494c2020-01-08 14:19:10 -0800713template <typename Type>
714void __attribute__((optnone)) VerifyAlignment(Type* floating) {
715 size_t expected_alignment = alignof(Type);
716 if (expected_alignment != 0) {
717 ASSERT_EQ(0U, (expected_alignment - 1) & reinterpret_cast<uintptr_t>(floating))
718 << "Expected alignment " << expected_alignment << " ptr value " << floating;
719 }
720}
721
722template <typename Type>
723void __attribute__((optnone)) TestAllocateType() {
724 // The number of allocations to do in a row. This is to attempt to
725 // expose the worst case alignment for native allocators that use
726 // bins.
727 static constexpr size_t kMaxConsecutiveAllocs = 100;
728
729 // Verify using new directly.
730 Type* types[kMaxConsecutiveAllocs];
731 for (size_t i = 0; i < kMaxConsecutiveAllocs; i++) {
732 types[i] = new Type;
733 VerifyAlignment(types[i]);
734 if (::testing::Test::HasFatalFailure()) {
735 return;
736 }
737 }
738 for (size_t i = 0; i < kMaxConsecutiveAllocs; i++) {
739 delete types[i];
740 }
741
742 // Verify using malloc.
743 for (size_t i = 0; i < kMaxConsecutiveAllocs; i++) {
744 types[i] = reinterpret_cast<Type*>(malloc(sizeof(Type)));
745 ASSERT_TRUE(types[i] != nullptr);
746 VerifyAlignment(types[i]);
747 if (::testing::Test::HasFatalFailure()) {
748 return;
749 }
750 }
751 for (size_t i = 0; i < kMaxConsecutiveAllocs; i++) {
752 free(types[i]);
753 }
754
755 // Verify using a vector.
756 std::vector<Type> type_vector(kMaxConsecutiveAllocs);
757 for (size_t i = 0; i < type_vector.size(); i++) {
758 VerifyAlignment(&type_vector[i]);
759 if (::testing::Test::HasFatalFailure()) {
760 return;
761 }
762 }
763}
764
765#if defined(__ANDROID__)
766static void __attribute__((optnone)) AndroidVerifyAlignment(size_t alloc_size, size_t aligned_bytes) {
767 void* ptrs[100];
768 uintptr_t mask = aligned_bytes - 1;
769 for (size_t i = 0; i < sizeof(ptrs) / sizeof(void*); i++) {
770 ptrs[i] = malloc(alloc_size);
771 ASSERT_TRUE(ptrs[i] != nullptr);
772 ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(ptrs[i]) & mask)
773 << "Expected at least " << aligned_bytes << " byte alignment: size "
774 << alloc_size << " actual ptr " << ptrs[i];
775 }
776}
777#endif
778
779TEST(malloc, align_check) {
780 // See http://www.open-std.org/jtc1/sc22/wg14/www/docs/summary.htm#dr_445
781 // for a discussion of type alignment.
782 ASSERT_NO_FATAL_FAILURE(TestAllocateType<float>());
783 ASSERT_NO_FATAL_FAILURE(TestAllocateType<double>());
784 ASSERT_NO_FATAL_FAILURE(TestAllocateType<long double>());
785
786 ASSERT_NO_FATAL_FAILURE(TestAllocateType<char>());
787 ASSERT_NO_FATAL_FAILURE(TestAllocateType<char16_t>());
788 ASSERT_NO_FATAL_FAILURE(TestAllocateType<char32_t>());
789 ASSERT_NO_FATAL_FAILURE(TestAllocateType<wchar_t>());
790 ASSERT_NO_FATAL_FAILURE(TestAllocateType<signed char>());
791 ASSERT_NO_FATAL_FAILURE(TestAllocateType<short int>());
792 ASSERT_NO_FATAL_FAILURE(TestAllocateType<int>());
793 ASSERT_NO_FATAL_FAILURE(TestAllocateType<long int>());
794 ASSERT_NO_FATAL_FAILURE(TestAllocateType<long long int>());
795 ASSERT_NO_FATAL_FAILURE(TestAllocateType<unsigned char>());
796 ASSERT_NO_FATAL_FAILURE(TestAllocateType<unsigned short int>());
797 ASSERT_NO_FATAL_FAILURE(TestAllocateType<unsigned int>());
798 ASSERT_NO_FATAL_FAILURE(TestAllocateType<unsigned long int>());
799 ASSERT_NO_FATAL_FAILURE(TestAllocateType<unsigned long long int>());
800
801#if defined(__ANDROID__)
802 // On Android, there is a lot of code that expects certain alignments:
803 // - Allocations of a size that rounds up to a multiple of 16 bytes
804 // must have at least 16 byte alignment.
805 // - Allocations of a size that rounds up to a multiple of 8 bytes and
806 // not 16 bytes, are only required to have at least 8 byte alignment.
807 // This is regardless of whether it is in a 32 bit or 64 bit environment.
808
809 // See http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2293.htm for
810 // a discussion of this alignment mess. The code below is enforcing
811 // strong-alignment, since who knows what code depends on this behavior now.
812 for (size_t i = 1; i <= 128; i++) {
813 size_t rounded = (i + 7) & ~7;
814 if ((rounded % 16) == 0) {
815 AndroidVerifyAlignment(i, 16);
816 } else {
817 AndroidVerifyAlignment(i, 8);
818 }
819 if (::testing::Test::HasFatalFailure()) {
820 return;
821 }
822 }
823#endif
824}
825
Ryan Savitskiecc37e32018-12-14 15:57:21 +0000826TEST(android_mallopt, error_on_unexpected_option) {
827#if defined(__BIONIC__)
828 const int unrecognized_option = -1;
829 errno = 0;
830 EXPECT_EQ(false, android_mallopt(unrecognized_option, nullptr, 0));
831 EXPECT_EQ(ENOTSUP, errno);
832#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800833 GTEST_SKIP() << "bionic-only test";
Ryan Savitskiecc37e32018-12-14 15:57:21 +0000834#endif
835}
836
Christopher Ferrise4cdbc42019-02-08 17:30:58 -0800837bool IsDynamic() {
838#if defined(__LP64__)
839 Elf64_Ehdr ehdr;
840#else
841 Elf32_Ehdr ehdr;
842#endif
843 std::string path(android::base::GetExecutablePath());
844
845 int fd = open(path.c_str(), O_RDONLY | O_CLOEXEC);
846 if (fd == -1) {
847 // Assume dynamic on error.
848 return true;
849 }
850 bool read_completed = android::base::ReadFully(fd, &ehdr, sizeof(ehdr));
851 close(fd);
852 // Assume dynamic in error cases.
853 return !read_completed || ehdr.e_type == ET_DYN;
854}
855
Ryan Savitskiecc37e32018-12-14 15:57:21 +0000856TEST(android_mallopt, init_zygote_child_profiling) {
857#if defined(__BIONIC__)
858 // Successful call.
859 errno = 0;
Christopher Ferrise4cdbc42019-02-08 17:30:58 -0800860 if (IsDynamic()) {
861 EXPECT_EQ(true, android_mallopt(M_INIT_ZYGOTE_CHILD_PROFILING, nullptr, 0));
862 EXPECT_EQ(0, errno);
863 } else {
864 // Not supported in static executables.
865 EXPECT_EQ(false, android_mallopt(M_INIT_ZYGOTE_CHILD_PROFILING, nullptr, 0));
866 EXPECT_EQ(ENOTSUP, errno);
867 }
Ryan Savitskiecc37e32018-12-14 15:57:21 +0000868
869 // Unexpected arguments rejected.
870 errno = 0;
871 char unexpected = 0;
872 EXPECT_EQ(false, android_mallopt(M_INIT_ZYGOTE_CHILD_PROFILING, &unexpected, 1));
Christopher Ferrise4cdbc42019-02-08 17:30:58 -0800873 if (IsDynamic()) {
874 EXPECT_EQ(EINVAL, errno);
875 } else {
876 EXPECT_EQ(ENOTSUP, errno);
877 }
Ryan Savitskiecc37e32018-12-14 15:57:21 +0000878#else
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800879 GTEST_SKIP() << "bionic-only test";
Ryan Savitskiecc37e32018-12-14 15:57:21 +0000880#endif
881}
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -0800882
883#if defined(__BIONIC__)
884template <typename FuncType>
885void CheckAllocationFunction(FuncType func) {
886 // Assumes that no more than 108MB of memory is allocated before this.
887 size_t limit = 128 * 1024 * 1024;
888 ASSERT_TRUE(android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit)));
889 if (!func(20 * 1024 * 1024))
890 exit(1);
891 if (func(128 * 1024 * 1024))
892 exit(1);
893 exit(0);
894}
895#endif
896
897TEST(android_mallopt, set_allocation_limit) {
898#if defined(__BIONIC__)
899 EXPECT_EXIT(CheckAllocationFunction([](size_t bytes) { return calloc(bytes, 1) != nullptr; }),
900 testing::ExitedWithCode(0), "");
901 EXPECT_EXIT(CheckAllocationFunction([](size_t bytes) { return calloc(1, bytes) != nullptr; }),
902 testing::ExitedWithCode(0), "");
903 EXPECT_EXIT(CheckAllocationFunction([](size_t bytes) { return malloc(bytes) != nullptr; }),
904 testing::ExitedWithCode(0), "");
905 EXPECT_EXIT(CheckAllocationFunction(
906 [](size_t bytes) { return memalign(sizeof(void*), bytes) != nullptr; }),
907 testing::ExitedWithCode(0), "");
908 EXPECT_EXIT(CheckAllocationFunction([](size_t bytes) {
909 void* ptr;
910 return posix_memalign(&ptr, sizeof(void *), bytes) == 0;
911 }),
912 testing::ExitedWithCode(0), "");
913 EXPECT_EXIT(CheckAllocationFunction(
914 [](size_t bytes) { return aligned_alloc(sizeof(void*), bytes) != nullptr; }),
915 testing::ExitedWithCode(0), "");
916 EXPECT_EXIT(CheckAllocationFunction([](size_t bytes) {
917 void* p = malloc(1024 * 1024);
918 return realloc(p, bytes) != nullptr;
919 }),
920 testing::ExitedWithCode(0), "");
921#if !defined(__LP64__)
922 EXPECT_EXIT(CheckAllocationFunction([](size_t bytes) { return pvalloc(bytes) != nullptr; }),
923 testing::ExitedWithCode(0), "");
924 EXPECT_EXIT(CheckAllocationFunction([](size_t bytes) { return valloc(bytes) != nullptr; }),
925 testing::ExitedWithCode(0), "");
926#endif
927#else
Elliott Hughes10907202019-03-27 08:51:02 -0700928 GTEST_SKIP() << "bionic extension";
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -0800929#endif
930}
931
932TEST(android_mallopt, set_allocation_limit_multiple) {
933#if defined(__BIONIC__)
934 // Only the first set should work.
935 size_t limit = 256 * 1024 * 1024;
936 ASSERT_TRUE(android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit)));
937 limit = 32 * 1024 * 1024;
938 ASSERT_FALSE(android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit)));
939#else
Elliott Hughes10907202019-03-27 08:51:02 -0700940 GTEST_SKIP() << "bionic extension";
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -0800941#endif
942}
943
944#if defined(__BIONIC__)
945static constexpr size_t kAllocationSize = 8 * 1024 * 1024;
946
947static size_t GetMaxAllocations() {
948 size_t max_pointers = 0;
949 void* ptrs[20];
950 for (size_t i = 0; i < sizeof(ptrs) / sizeof(void*); i++) {
951 ptrs[i] = malloc(kAllocationSize);
952 if (ptrs[i] == nullptr) {
953 max_pointers = i;
954 break;
955 }
956 }
957 for (size_t i = 0; i < max_pointers; i++) {
958 free(ptrs[i]);
959 }
960 return max_pointers;
961}
962
963static void VerifyMaxPointers(size_t max_pointers) {
964 // Now verify that we can allocate the same number as before.
965 void* ptrs[20];
966 for (size_t i = 0; i < max_pointers; i++) {
967 ptrs[i] = malloc(kAllocationSize);
968 ASSERT_TRUE(ptrs[i] != nullptr) << "Failed to allocate on iteration " << i;
969 }
970
971 // Make sure the next allocation still fails.
972 ASSERT_TRUE(malloc(kAllocationSize) == nullptr);
973 for (size_t i = 0; i < max_pointers; i++) {
974 free(ptrs[i]);
975 }
976}
977#endif
978
979TEST(android_mallopt, set_allocation_limit_realloc_increase) {
980#if defined(__BIONIC__)
981 size_t limit = 128 * 1024 * 1024;
982 ASSERT_TRUE(android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit)));
983
984 size_t max_pointers = GetMaxAllocations();
985 ASSERT_TRUE(max_pointers != 0) << "Limit never reached.";
986
987 void* memory = malloc(10 * 1024 * 1024);
988 ASSERT_TRUE(memory != nullptr);
989
990 // Increase size.
991 memory = realloc(memory, 20 * 1024 * 1024);
992 ASSERT_TRUE(memory != nullptr);
993 memory = realloc(memory, 40 * 1024 * 1024);
994 ASSERT_TRUE(memory != nullptr);
995 memory = realloc(memory, 60 * 1024 * 1024);
996 ASSERT_TRUE(memory != nullptr);
997 memory = realloc(memory, 80 * 1024 * 1024);
998 ASSERT_TRUE(memory != nullptr);
999 // Now push past limit.
1000 memory = realloc(memory, 130 * 1024 * 1024);
1001 ASSERT_TRUE(memory == nullptr);
1002
1003 VerifyMaxPointers(max_pointers);
1004#else
Elliott Hughes10907202019-03-27 08:51:02 -07001005 GTEST_SKIP() << "bionic extension";
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -08001006#endif
1007}
1008
1009TEST(android_mallopt, set_allocation_limit_realloc_decrease) {
1010#if defined(__BIONIC__)
1011 size_t limit = 100 * 1024 * 1024;
1012 ASSERT_TRUE(android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit)));
1013
1014 size_t max_pointers = GetMaxAllocations();
1015 ASSERT_TRUE(max_pointers != 0) << "Limit never reached.";
1016
1017 void* memory = malloc(80 * 1024 * 1024);
1018 ASSERT_TRUE(memory != nullptr);
1019
1020 // Decrease size.
1021 memory = realloc(memory, 60 * 1024 * 1024);
1022 ASSERT_TRUE(memory != nullptr);
1023 memory = realloc(memory, 40 * 1024 * 1024);
1024 ASSERT_TRUE(memory != nullptr);
1025 memory = realloc(memory, 20 * 1024 * 1024);
1026 ASSERT_TRUE(memory != nullptr);
1027 memory = realloc(memory, 10 * 1024 * 1024);
1028 ASSERT_TRUE(memory != nullptr);
1029 free(memory);
1030
1031 VerifyMaxPointers(max_pointers);
1032#else
Elliott Hughes10907202019-03-27 08:51:02 -07001033 GTEST_SKIP() << "bionic extension";
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -08001034#endif
1035}
1036
1037TEST(android_mallopt, set_allocation_limit_realloc_free) {
1038#if defined(__BIONIC__)
1039 size_t limit = 100 * 1024 * 1024;
1040 ASSERT_TRUE(android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit)));
1041
1042 size_t max_pointers = GetMaxAllocations();
1043 ASSERT_TRUE(max_pointers != 0) << "Limit never reached.";
1044
1045 void* memory = malloc(60 * 1024 * 1024);
1046 ASSERT_TRUE(memory != nullptr);
1047
1048 memory = realloc(memory, 0);
1049 ASSERT_TRUE(memory == nullptr);
1050
1051 VerifyMaxPointers(max_pointers);
1052#else
Elliott Hughes10907202019-03-27 08:51:02 -07001053 GTEST_SKIP() << "bionic extension";
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -08001054#endif
1055}
1056
1057#if defined(__BIONIC__)
1058static void* SetAllocationLimit(void* data) {
1059 std::atomic_bool* go = reinterpret_cast<std::atomic_bool*>(data);
1060 while (!go->load()) {
1061 }
1062 size_t limit = 500 * 1024 * 1024;
1063 if (android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit))) {
1064 return reinterpret_cast<void*>(-1);
1065 }
1066 return nullptr;
1067}
1068
1069static void SetAllocationLimitMultipleThreads() {
1070 std::atomic_bool go;
1071 go = false;
1072
1073 static constexpr size_t kNumThreads = 4;
1074 pthread_t threads[kNumThreads];
1075 for (size_t i = 0; i < kNumThreads; i++) {
1076 ASSERT_EQ(0, pthread_create(&threads[i], nullptr, SetAllocationLimit, &go));
1077 }
1078
1079 // Let them go all at once.
1080 go = true;
Ryan Savitski175c8862020-01-02 19:54:57 +00001081 // Send hardcoded signal (BIONIC_SIGNAL_PROFILER with value 0) to trigger
1082 // heapprofd handler.
1083 union sigval signal_value;
1084 signal_value.sival_int = 0;
1085 ASSERT_EQ(0, sigqueue(getpid(), __SIGRTMIN + 4, signal_value));
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -08001086
1087 size_t num_successful = 0;
1088 for (size_t i = 0; i < kNumThreads; i++) {
1089 void* result;
1090 ASSERT_EQ(0, pthread_join(threads[i], &result));
1091 if (result != nullptr) {
1092 num_successful++;
1093 }
1094 }
1095 ASSERT_EQ(1U, num_successful);
1096 exit(0);
1097}
1098#endif
1099
1100TEST(android_mallopt, set_allocation_limit_multiple_threads) {
1101#if defined(__BIONIC__)
1102 if (IsDynamic()) {
1103 ASSERT_TRUE(android_mallopt(M_INIT_ZYGOTE_CHILD_PROFILING, nullptr, 0));
1104 }
1105
1106 // Run this a number of times as a stress test.
1107 for (size_t i = 0; i < 100; i++) {
1108 // Not using ASSERT_EXIT because errors messages are not displayed.
1109 pid_t pid;
1110 if ((pid = fork()) == 0) {
1111 ASSERT_NO_FATAL_FAILURE(SetAllocationLimitMultipleThreads());
1112 }
1113 ASSERT_NE(-1, pid);
1114 int status;
1115 ASSERT_EQ(pid, wait(&status));
1116 ASSERT_EQ(0, WEXITSTATUS(status));
1117 }
1118#else
Elliott Hughes10907202019-03-27 08:51:02 -07001119 GTEST_SKIP() << "bionic extension";
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -08001120#endif
1121}