blob: d7a7a4f126e70f4e3070430a8861aa74842b1b2a [file] [log] [blame]
Christopher Ferris97b47472018-07-10 14:45:24 -07001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
13 * distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include <errno.h>
30#include <fcntl.h>
31#include <poll.h>
Christopher Ferris4990c2d2021-07-22 13:17:34 -070032#include <setjmp.h>
Christopher Ferris97b47472018-07-10 14:45:24 -070033#include <signal.h>
Christopher Ferris33d73372021-07-02 15:46:18 -070034#include <stdint.h>
Christopher Ferris97b47472018-07-10 14:45:24 -070035#include <stdio.h>
36#include <stdlib.h>
37#include <sys/types.h>
38#include <sys/wait.h>
39#include <time.h>
40#include <unistd.h>
41
Christopher Ferrisff88fb02019-11-04 18:40:00 -080042#include <android-base/file.h>
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -080043#include <android-base/stringprintf.h>
Florian Mayer750dcd32022-04-15 15:54:47 -070044#include <android-base/test_utils.h>
Christopher Ferris97b47472018-07-10 14:45:24 -070045#include <gtest/gtest.h>
Tom Cherryad9e99d2020-04-22 19:00:42 -070046#include <log/log_read.h>
Christopher Ferris97b47472018-07-10 14:45:24 -070047
Christopher Ferris9bf78172020-05-20 15:37:30 -070048#include <atomic>
Christopher Ferris4990c2d2021-07-22 13:17:34 -070049#include <mutex>
Christopher Ferrise07b33d2021-08-05 13:26:11 -070050#include <random>
Christopher Ferris97b47472018-07-10 14:45:24 -070051#include <string>
Christopher Ferrisd269fcc2019-05-06 19:03:59 -070052#include <thread>
Christopher Ferris97b47472018-07-10 14:45:24 -070053#include <vector>
54
Christopher Ferrisdfbc59a2022-03-23 12:22:36 -070055#include <unwindstack/AndroidUnwinder.h>
Christopher Ferris9bf78172020-05-20 15:37:30 -070056
Christopher Ferris2b0638e2019-09-11 19:05:29 -070057#include <bionic/malloc.h>
Florian Mayerdca72292022-04-13 14:39:36 -070058#include <tests/utils.h>
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -080059
Christopher Ferris9bf78172020-05-20 15:37:30 -070060// All DISABLED_ tests are designed to be executed after malloc debug
61// is enabled. These tests don't run be default, and are executed
62// by wrappers that will enable various malloc debug features.
63
Christopher Ferrise4619f72019-11-11 14:17:44 -080064extern "C" bool GetInitialArgs(const char*** args, size_t* num_args) {
65 static const char* initial_args[] = {"--slow_threshold_ms=30000",
66 "--deadline_threshold_ms=1200000"};
67 *args = initial_args;
68 *num_args = 2;
69 return true;
70}
71
Christopher Ferris4990c2d2021-07-22 13:17:34 -070072class LogReader {
73 public:
74 LogReader(pid_t pid, log_id log) {
75 std::call_once(log_start_time_flag_, []() {
76 // Use this to figure out the point at which to start grabbing the log.
77 // This avoids accidentally grabbing data from a previous process with
78 // the same pid.
79 log_start_time_ = {};
Elliott Hughese1aabd22024-07-01 13:20:06 +000080 logger_list* list = android_logger_list_open(LOG_ID_MAIN, ANDROID_LOG_NONBLOCK, INT_MAX, 0);
Christopher Ferris4990c2d2021-07-22 13:17:34 -070081 if (list == nullptr) {
82 return;
Christopher Ferris97b47472018-07-10 14:45:24 -070083 }
Christopher Ferris4990c2d2021-07-22 13:17:34 -070084 log_msg log_msg;
85 int ret = android_logger_list_read(list, &log_msg);
86 android_logger_list_close(list);
87 if (ret <= 0) {
88 return;
89 }
90 log_start_time_.tv_sec = log_msg.entry.sec;
91 log_start_time_.tv_nsec = log_msg.entry.nsec;
92 });
93
94 std::call_once(jmp_data_key_flag_, []() {
95 pthread_key_create(&jmp_data_key_, [](void* ptr) { free(ptr); });
96 signal(SIGUSR1, [](int) {
97 jmp_buf* jb = reinterpret_cast<jmp_buf*>(pthread_getspecific(jmp_data_key_));
98 if (jb != nullptr) {
99 // The thread reading the log is in a blocking read call that
100 // cannot be interrupted. In order to get out of this read loop,
101 // it's necessary to call longjmp when a SIGUSR1 signal is sent
102 // to the thread.
103 longjmp(*jb, 1);
104 }
105 });
106 });
107
108 reader_.reset(new std::thread([this, pid, log] {
109 tid_.store(gettid(), std::memory_order_release);
110 logger_list* list;
111 while (true) {
112 // Do not use non-blocking mode so that the two threads
113 // are essentially asleep and not consuming any cpu.
Elliott Hughese1aabd22024-07-01 13:20:06 +0000114 list = android_logger_list_open(log, 0, INT_MAX, pid);
Christopher Ferris4990c2d2021-07-22 13:17:34 -0700115 if (list != nullptr) {
116 break;
117 }
118 // Wait for a short time for the log to become available.
119 usleep(1000);
120 }
121
122 jmp_buf* jb = reinterpret_cast<jmp_buf*>(malloc(sizeof(jmp_buf)));
123 if (jb == nullptr) {
124 printf("Failed to allocate memory for jmp_buf\n");
125 return;
126 }
127 pthread_setspecific(jmp_data_key_, jb);
128 if (setjmp(*jb) != 0) {
129 // SIGUSR1 signal hit, we need to terminate the thread.
130 android_logger_list_free(list);
131 return;
132 }
133
134 while (true) {
135 log_msg msg;
136 int actual = android_logger_list_read(list, &msg);
137 if (actual < 0) {
138 if (actual == -EINTR) {
139 // Interrupted retry.
140 continue;
141 }
142 // Unknown error.
143 break;
144 } else if (actual == 0) {
145 // Nothing left to read.
146 break;
147 }
Christopher Ferrisd9d9ee82021-07-23 17:10:58 -0700148 // Do not allow SIGUSR1 while processing the log message.
149 // This avoids a deadlock if the thread is being terminated
150 // at this moment.
151 sigset64_t mask_set;
152 sigprocmask64(SIG_SETMASK, nullptr, &mask_set);
153 sigaddset64(&mask_set, SIGUSR1);
154 sigprocmask64(SIG_SETMASK, &mask_set, nullptr);
155
156 {
157 // Lock while appending to the data.
158 std::lock_guard<std::mutex> guard(data_lock_);
159 char* msg_str = msg.msg();
160 // Make sure the message is not empty and recent.
161 if (msg_str != nullptr && (msg.entry.sec > log_start_time_.tv_sec ||
162 (msg.entry.sec == log_start_time_.tv_sec &&
163 msg.entry.nsec > log_start_time_.tv_nsec))) {
164 // Skip the tag part of the message.
165 char* tag = msg_str + 1;
166 msg_str = tag + strlen(tag) + 1;
167 log_data_ += msg_str;
168 if (log_data_.back() != '\n') {
169 log_data_ += '\n';
170 }
Christopher Ferris4990c2d2021-07-22 13:17:34 -0700171 }
172 }
Christopher Ferrisd9d9ee82021-07-23 17:10:58 -0700173
174 // Re-enable SIGUSR1
175 sigprocmask64(SIG_SETMASK, nullptr, &mask_set);
176 sigdelset64(&mask_set, SIGUSR1);
177 sigprocmask64(SIG_SETMASK, &mask_set, nullptr);
Christopher Ferris4990c2d2021-07-22 13:17:34 -0700178 }
179 android_logger_list_free(list);
180 }));
181 }
182
183 virtual ~LogReader() {
184 tgkill(getpid(), tid_.load(std::memory_order_acquire), SIGUSR1);
185 reader_->join();
186 }
187
188 std::string GetLog() {
189 std::lock_guard<std::mutex> guard(data_lock_);
190 return log_data_;
191 }
192
193 private:
194 std::unique_ptr<std::thread> reader_;
195 std::string log_data_;
196 std::mutex data_lock_;
197 std::atomic<pid_t> tid_;
198
199 static std::once_flag jmp_data_key_flag_;
200 static pthread_key_t jmp_data_key_;
201
202 static std::once_flag log_start_time_flag_;
203 static log_time log_start_time_;
204};
205
206std::once_flag LogReader::jmp_data_key_flag_;
207pthread_key_t LogReader::jmp_data_key_;
208
209std::once_flag LogReader::log_start_time_flag_;
210log_time LogReader::log_start_time_;
211
212class MallocDebugSystemTest : public ::testing::Test {
213 protected:
Christopher Ferrisd9d9ee82021-07-23 17:10:58 -0700214 void SetUp() override {
215 expected_log_strings_.clear();
216 unexpected_log_strings_.clear();
217
218 // All tests expect this message to be present.
219 expected_log_strings_.push_back("malloc debug enabled");
220 }
221
222 void Exec(const char* test_name, const char* debug_options, int expected_exit_code = 0) {
Christopher Ferrise07b33d2021-08-05 13:26:11 -0700223 std::random_device rd;
224 std::mt19937 generator(rd());
225 std::uniform_int_distribution<> rand_usleep_time(1, 10);
226 std::srand(std::time(nullptr));
227
Christopher Ferrisd9d9ee82021-07-23 17:10:58 -0700228 for (size_t i = 0; i < kMaxRetries; i++) {
229 ASSERT_NO_FATAL_FAILURE(InternalExec(test_name, debug_options, expected_exit_code));
230
231 // Due to log messages sometimes getting lost, if a log message
232 // is not present, allow retrying the test.
233 std::string error_msg;
Christopher Ferrise07b33d2021-08-05 13:26:11 -0700234 bool found_expected = CheckExpectedLogStrings(&error_msg);
235 if (!found_expected) {
Christopher Ferrisd9d9ee82021-07-23 17:10:58 -0700236 ASSERT_NE(i, kMaxRetries - 1) << error_msg;
Christopher Ferrise07b33d2021-08-05 13:26:11 -0700237 // Sleep a random amount of time to attempt to avoid tests syncing
238 // up and sending the log messages at the same time.
239 usleep(1000 * rand_usleep_time(generator));
Christopher Ferrisd9d9ee82021-07-23 17:10:58 -0700240 }
241
242 // This doesn't need to be retried since if the log message is
243 // present, that is an immediate fail.
244 ASSERT_NO_FATAL_FAILURE(VerifyUnexpectedLogStrings());
Christopher Ferrise07b33d2021-08-05 13:26:11 -0700245 if (found_expected) {
246 break;
247 }
Christopher Ferrisd9d9ee82021-07-23 17:10:58 -0700248 }
249 }
250
251 void InternalExec(const char* test_name, const char* debug_options, int expected_exit_code) {
Christopher Ferris4990c2d2021-07-22 13:17:34 -0700252 int fds[2];
253 ASSERT_NE(-1, pipe(fds));
254 ASSERT_NE(-1, fcntl(fds[0], F_SETFL, O_NONBLOCK));
255 if ((pid_ = fork()) == 0) {
256 ASSERT_EQ(0, setenv("LIBC_DEBUG_MALLOC_OPTIONS", debug_options, 1));
257 close(fds[0]);
258 close(STDIN_FILENO);
259 close(STDOUT_FILENO);
260 close(STDERR_FILENO);
261 ASSERT_NE(0, dup2(fds[1], STDOUT_FILENO));
262 ASSERT_NE(0, dup2(fds[1], STDERR_FILENO));
263
264 std::vector<const char*> args;
265 // Get a copy of this argument so it doesn't disappear on us.
266 std::string exec(testing::internal::GetArgvs()[0]);
267 args.push_back(exec.c_str());
268 args.push_back("--gtest_also_run_disabled_tests");
269 std::string filter_arg = std::string("--gtest_filter=") + test_name;
270 args.push_back(filter_arg.c_str());
271 // Need this because some code depends on exit codes from the test run
272 // but the isolation runner does not support that.
273 args.push_back("--no_isolate");
274 args.push_back(nullptr);
275 execv(args[0], reinterpret_cast<char* const*>(const_cast<char**>(args.data())));
276 exit(20);
277 }
278 ASSERT_NE(-1, pid_);
279 close(fds[1]);
280
281 // Create threads to read the log output from the forked process as
282 // soon as possible in case there is something flooding the log.
283 log_main_.reset(new LogReader(pid_, LOG_ID_MAIN));
284 log_crash_.reset(new LogReader(pid_, LOG_ID_CRASH));
285
286 output_.clear();
287 std::vector<char> buffer(4096);
288 time_t start_time = time(nullptr);
Christopher Ferrisd9d9ee82021-07-23 17:10:58 -0700289 bool read_done = false;
Christopher Ferris4990c2d2021-07-22 13:17:34 -0700290 while (true) {
291 struct pollfd read_fd = {.fd = fds[0], .events = POLLIN};
292 if (TEMP_FAILURE_RETRY(poll(&read_fd, 1, 1)) > 0) {
293 ssize_t bytes = TEMP_FAILURE_RETRY(read(fds[0], buffer.data(), sizeof(buffer) - 1));
294 if (bytes == -1 && errno == EAGAIN) {
295 continue;
296 }
297 ASSERT_NE(-1, bytes);
298 if (bytes == 0) {
Christopher Ferrisd9d9ee82021-07-23 17:10:58 -0700299 read_done = true;
Christopher Ferris4990c2d2021-07-22 13:17:34 -0700300 break;
301 }
302 output_.append(buffer.data(), bytes);
303 }
304
Christopher Ferrisd9d9ee82021-07-23 17:10:58 -0700305 if ((time(nullptr) - start_time) > kReadOutputTimeoutSeconds) {
Christopher Ferris4990c2d2021-07-22 13:17:34 -0700306 kill(pid_, SIGINT);
307 break;
308 }
309 }
Christopher Ferris4990c2d2021-07-22 13:17:34 -0700310
Christopher Ferrisd9d9ee82021-07-23 17:10:58 -0700311 bool done = false;
Christopher Ferris4990c2d2021-07-22 13:17:34 -0700312 int status;
313 start_time = time(nullptr);
314 while (true) {
315 int wait_pid = waitpid(pid_, &status, WNOHANG);
316 if (pid_ == wait_pid) {
Christopher Ferris97b47472018-07-10 14:45:24 -0700317 done = true;
318 break;
319 }
Christopher Ferrisd9d9ee82021-07-23 17:10:58 -0700320 if ((time(nullptr) - start_time) > kWaitpidTimeoutSeconds) {
Christopher Ferris4990c2d2021-07-22 13:17:34 -0700321 break;
322 }
323 }
324 if (!done) {
325 kill(pid_, SIGKILL);
326 start_time = time(nullptr);
327 while (true) {
328 int kill_status;
329 int wait_pid = waitpid(pid_, &kill_status, WNOHANG);
Christopher Ferrisd9d9ee82021-07-23 17:10:58 -0700330 if (wait_pid == pid_ || (time(nullptr) - start_time) > kWaitpidTimeoutSeconds) {
Christopher Ferris4990c2d2021-07-22 13:17:34 -0700331 break;
332 }
333 }
Christopher Ferris97b47472018-07-10 14:45:24 -0700334 }
335
Christopher Ferrisd9d9ee82021-07-23 17:10:58 -0700336 // Check timeout conditions first.
337 ASSERT_TRUE(read_done) << "Timed out while reading data, output:\n" << output_;
Christopher Ferris4990c2d2021-07-22 13:17:34 -0700338 ASSERT_TRUE(done) << "Timed out waiting for waitpid, output:\n" << output_;
Christopher Ferrisd9d9ee82021-07-23 17:10:58 -0700339
Christopher Ferris4990c2d2021-07-22 13:17:34 -0700340 ASSERT_FALSE(WIFSIGNALED(status)) << "Failed with signal " << WTERMSIG(status) << "\nOutput:\n"
341 << output_;
342 ASSERT_EQ(expected_exit_code, WEXITSTATUS(status)) << "Output:\n" << output_;
Christopher Ferris97b47472018-07-10 14:45:24 -0700343 }
Christopher Ferris97b47472018-07-10 14:45:24 -0700344
Christopher Ferrisd9d9ee82021-07-23 17:10:58 -0700345 bool CheckExpectedLogStrings(std::string* error_msg) {
Christopher Ferris4990c2d2021-07-22 13:17:34 -0700346 time_t start = time(nullptr);
347 std::string missing_match;
348 std::string log_str;
Christopher Ferris97b47472018-07-10 14:45:24 -0700349 while (true) {
Christopher Ferris4990c2d2021-07-22 13:17:34 -0700350 log_str = log_main_->GetLog();
351 missing_match.clear();
352 // Look for the expected strings.
Christopher Ferrisd9d9ee82021-07-23 17:10:58 -0700353 for (auto str : expected_log_strings_) {
Christopher Ferris4990c2d2021-07-22 13:17:34 -0700354 if (log_str.find(str) == std::string::npos) {
355 missing_match = str;
356 break;
357 }
358 }
Christopher Ferris4990c2d2021-07-22 13:17:34 -0700359 if (missing_match.empty()) {
Christopher Ferrisd9d9ee82021-07-23 17:10:58 -0700360 return true;
Christopher Ferris4990c2d2021-07-22 13:17:34 -0700361 }
Christopher Ferrisd9d9ee82021-07-23 17:10:58 -0700362 if ((time(nullptr) - start) > kLogTimeoutSeconds) {
Christopher Ferris97b47472018-07-10 14:45:24 -0700363 break;
364 }
365 }
Christopher Ferrisd9d9ee82021-07-23 17:10:58 -0700366
367 *error_msg = android::base::StringPrintf("Didn't find string '%s' in log output:\n%s",
368 missing_match.c_str(), log_str.c_str());
369 return false;
370 }
371
372 void VerifyUnexpectedLogStrings() {
373 std::string log_str = log_main_->GetLog();
374 for (auto str : unexpected_log_strings_) {
375 ASSERT_TRUE(log_str.find(str) == std::string::npos)
376 << "Unexpectedly found string '" << str << "' in log output:\n"
377 << log_str;
378 }
Christopher Ferris4990c2d2021-07-22 13:17:34 -0700379 }
380
381 void VerifyLeak(const char* test_prefix) {
382 struct FunctionInfo {
383 const char* name;
384 size_t size;
385 };
386 static FunctionInfo functions[] = {
387 {
388 "aligned_alloc",
389 1152,
390 },
391 {
392 "calloc",
393 1123,
394 },
395 {
396 "malloc",
397 1123,
398 },
399 {
400 "memalign",
401 1123,
402 },
403 {
404 "posix_memalign",
405 1123,
406 },
407 {
408 "reallocarray",
409 1123,
410 },
411 {
412 "realloc",
413 1123,
414 },
415#if !defined(__LP64__)
416 {
417 "pvalloc",
418 4096,
419 },
420 {
421 "valloc",
422 1123,
423 }
424#endif
425 };
426
Christopher Ferrisd9d9ee82021-07-23 17:10:58 -0700427 size_t match_len = expected_log_strings_.size() + 1;
428 expected_log_strings_.resize(match_len);
Christopher Ferris4990c2d2021-07-22 13:17:34 -0700429 for (size_t i = 0; i < sizeof(functions) / sizeof(FunctionInfo); i++) {
430 SCOPED_TRACE(testing::Message()
431 << functions[i].name << " expected size " << functions[i].size);
Christopher Ferrisd9d9ee82021-07-23 17:10:58 -0700432
433 expected_log_strings_[match_len - 1] =
434 android::base::StringPrintf("leaked block of size %zu at", functions[i].size);
435
Christopher Ferris4990c2d2021-07-22 13:17:34 -0700436 std::string test = std::string("MallocTests.DISABLED_") + test_prefix + functions[i].name;
437 ASSERT_NO_FATAL_FAILURE(Exec(test.c_str(), "verbose backtrace leak_track"));
Christopher Ferris4990c2d2021-07-22 13:17:34 -0700438 }
Christopher Ferris97b47472018-07-10 14:45:24 -0700439 }
440
Christopher Ferris4990c2d2021-07-22 13:17:34 -0700441 std::unique_ptr<LogReader> log_main_;
442 std::unique_ptr<LogReader> log_crash_;
443 pid_t pid_;
444 std::string output_;
Christopher Ferrisd9d9ee82021-07-23 17:10:58 -0700445 std::vector<std::string> expected_log_strings_;
446 std::vector<std::string> unexpected_log_strings_;
447
448 static constexpr size_t kReadOutputTimeoutSeconds = 180;
449 static constexpr size_t kWaitpidTimeoutSeconds = 10;
450 static constexpr size_t kLogTimeoutSeconds = 5;
451 static constexpr size_t kMaxRetries = 3;
Christopher Ferris4990c2d2021-07-22 13:17:34 -0700452};
Christopher Ferris97b47472018-07-10 14:45:24 -0700453
Christopher Ferrisdfbc59a2022-03-23 12:22:36 -0700454TEST(MallocTests, DISABLED_smoke) {
455 void* ptr = malloc(128);
456 free(ptr);
457}
Christopher Ferris97b47472018-07-10 14:45:24 -0700458
Christopher Ferris4990c2d2021-07-22 13:17:34 -0700459TEST_F(MallocDebugSystemTest, smoke) {
Christopher Ferrisd9d9ee82021-07-23 17:10:58 -0700460 Exec("MallocTests.DISABLED_smoke", "verbose backtrace");
Christopher Ferris97b47472018-07-10 14:45:24 -0700461}
462
Christopher Ferrisdfbc59a2022-03-23 12:22:36 -0700463TEST_F(MallocDebugSystemTest, backtrace_full_smoke) {
464 Exec("MallocTests.DISABLED_smoke", "verbose backtrace backtrace_full");
465}
466
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -0800467static void SetAllocationLimit() {
468 // Set to a large value, this is only to enable the limit code and
469 // verify that malloc debug is still called properly.
470 size_t limit = 500 * 1024 * 1024;
471 ASSERT_TRUE(android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit)));
472}
473
474static void AlignedAlloc() {
475 void* ptr = aligned_alloc(64, 1152);
476 ASSERT_TRUE(ptr != nullptr);
477 memset(ptr, 0, 1152);
478}
479
480TEST(MallocTests, DISABLED_leak_memory_aligned_alloc) {
481 AlignedAlloc();
482}
483
484TEST(MallocTests, DISABLED_leak_memory_limit_aligned_alloc) {
485 SetAllocationLimit();
486 AlignedAlloc();
487}
488
489static void Calloc() {
490 void* ptr = calloc(1, 1123);
491 ASSERT_TRUE(ptr != nullptr);
492 memset(ptr, 1, 1123);
493}
494
495TEST(MallocTests, DISABLED_leak_memory_calloc) {
496 Calloc();
497}
498
499TEST(MallocTests, DISABLED_leak_memory_limit_calloc) {
500 SetAllocationLimit();
501 Calloc();
502}
503
504static void Malloc() {
Christopher Ferris97b47472018-07-10 14:45:24 -0700505 void* ptr = malloc(1123);
506 ASSERT_TRUE(ptr != nullptr);
507 memset(ptr, 0, 1123);
508}
509
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -0800510TEST(MallocTests, DISABLED_leak_memory_malloc) {
511 Malloc();
512}
Christopher Ferris97b47472018-07-10 14:45:24 -0700513
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -0800514TEST(MallocTests, DISABLED_leak_memory_limit_malloc) {
515 SetAllocationLimit();
516 Malloc();
517}
518
519static void Memalign() {
520 void* ptr = memalign(64, 1123);
521 ASSERT_TRUE(ptr != nullptr);
522 memset(ptr, 0, 1123);
523}
524
525TEST(MallocTests, DISABLED_leak_memory_memalign) {
526 Memalign();
527}
528
529TEST(MallocTests, DISABLED_leak_memory_limit_memalign) {
530 SetAllocationLimit();
531 Memalign();
532}
533
534static void PosixMemalign() {
535 void* ptr;
536 ASSERT_EQ(0, posix_memalign(&ptr, 64, 1123));
537 ASSERT_TRUE(ptr != nullptr);
538 memset(ptr, 0, 1123);
539}
540
541TEST(MallocTests, DISABLED_leak_memory_posix_memalign) {
542 PosixMemalign();
543}
544
545TEST(MallocTests, DISABLED_leak_memory_limit_posix_memalign) {
546 SetAllocationLimit();
547 PosixMemalign();
548}
549
550static void Reallocarray() {
551 void* ptr = reallocarray(nullptr, 1, 1123);
552 ASSERT_TRUE(ptr != nullptr);
553 memset(ptr, 0, 1123);
554}
555
556TEST(MallocTests, DISABLED_leak_memory_reallocarray) {
557 Reallocarray();
558}
559
560TEST(MallocTests, DISABLED_leak_memory_limit_reallocarray) {
561 SetAllocationLimit();
562 Reallocarray();
563}
564
565static void Realloc() {
566 void* ptr = realloc(nullptr, 1123);
567 ASSERT_TRUE(ptr != nullptr);
568 memset(ptr, 0, 1123);
569}
570
571TEST(MallocTests, DISABLED_leak_memory_realloc) {
572 Realloc();
573}
574
575TEST(MallocTests, DISABLED_leak_memory_limit_realloc) {
576 SetAllocationLimit();
577 Realloc();
578}
579
580#if !defined(__LP64__)
581extern "C" void* pvalloc(size_t);
582
583static void Pvalloc() {
584 void* ptr = pvalloc(1123);
585 ASSERT_TRUE(ptr != nullptr);
586 memset(ptr, 0, 1123);
587}
588
589TEST(MallocTests, DISABLED_leak_memory_pvalloc) {
590 Pvalloc();
591}
592
593TEST(MallocTests, DISABLED_leak_memory_limit_pvalloc) {
594 SetAllocationLimit();
595 Pvalloc();
596}
597
598extern "C" void* valloc(size_t);
599
600static void Valloc() {
601 void* ptr = valloc(1123);
602 ASSERT_TRUE(ptr != nullptr);
603 memset(ptr, 0, 1123);
604}
605
606TEST(MallocTests, DISABLED_leak_memory_valloc) {
607 Valloc();
608}
609
610TEST(MallocTests, DISABLED_leak_memory_limit_valloc) {
611 SetAllocationLimit();
612 Valloc();
613}
614#endif
615
Christopher Ferris4990c2d2021-07-22 13:17:34 -0700616TEST_F(MallocDebugSystemTest, verify_leak) {
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -0800617 VerifyLeak("leak_memory_");
618}
619
Christopher Ferris4990c2d2021-07-22 13:17:34 -0700620TEST_F(MallocDebugSystemTest, verify_leak_allocation_limit) {
Florian Mayerdca72292022-04-13 14:39:36 -0700621 SKIP_WITH_HWASAN;
Christopher Ferris1fc5ccf2019-02-15 18:06:15 -0800622 VerifyLeak("leak_memory_limit_");
Christopher Ferris97b47472018-07-10 14:45:24 -0700623}
Christopher Ferrisd269fcc2019-05-06 19:03:59 -0700624
625static constexpr int kExpectedExitCode = 30;
Christopher Ferris33d73372021-07-02 15:46:18 -0700626static constexpr size_t kMaxThreads = sizeof(uint32_t) * 8;
Christopher Ferrisd269fcc2019-05-06 19:03:59 -0700627
628TEST(MallocTests, DISABLED_exit_while_threads_allocating) {
Christopher Ferris33d73372021-07-02 15:46:18 -0700629 std::atomic_uint32_t thread_mask = {};
Christopher Ferrisd269fcc2019-05-06 19:03:59 -0700630
Christopher Ferris33d73372021-07-02 15:46:18 -0700631 for (size_t i = 0; i < kMaxThreads; i++) {
Christopher Ferrisd269fcc2019-05-06 19:03:59 -0700632 std::thread malloc_thread([&thread_mask, i] {
633 while (true) {
634 void* ptr = malloc(100);
635 if (ptr == nullptr) {
636 exit(1000);
637 }
638 free(ptr);
Christopher Ferrisa6035ec2021-07-15 12:58:07 -0700639 thread_mask.fetch_or(1U << i);
Christopher Ferrisd269fcc2019-05-06 19:03:59 -0700640 }
641 });
642 malloc_thread.detach();
643 }
644
645 // Wait until each thread has done at least one allocation.
Christopher Ferris33d73372021-07-02 15:46:18 -0700646 while (thread_mask.load() != UINT32_MAX)
Christopher Ferrisd269fcc2019-05-06 19:03:59 -0700647 ;
648 exit(kExpectedExitCode);
649}
650
651// Verify that exiting while other threads are doing malloc operations,
652// that there are no crashes.
Christopher Ferris4990c2d2021-07-22 13:17:34 -0700653TEST_F(MallocDebugSystemTest, exit_while_threads_allocating) {
Christopher Ferrisd269fcc2019-05-06 19:03:59 -0700654 for (size_t i = 0; i < 100; i++) {
655 SCOPED_TRACE(::testing::Message() << "Run " << i);
Christopher Ferrisd269fcc2019-05-06 19:03:59 -0700656 ASSERT_NO_FATAL_FAILURE(Exec("MallocTests.DISABLED_exit_while_threads_allocating",
Christopher Ferris4990c2d2021-07-22 13:17:34 -0700657 "verbose backtrace", kExpectedExitCode));
Christopher Ferrisd269fcc2019-05-06 19:03:59 -0700658
Christopher Ferris4990c2d2021-07-22 13:17:34 -0700659 std::string log_str = log_crash_->GetLog();
Christopher Ferrisd269fcc2019-05-06 19:03:59 -0700660 ASSERT_TRUE(log_str.find("Fatal signal") == std::string::npos)
Christopher Ferris4990c2d2021-07-22 13:17:34 -0700661 << "Found crash in log.\nLog message: " << log_str << " pid: " << pid_;
Christopher Ferrisd269fcc2019-05-06 19:03:59 -0700662 }
663}
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800664
Christopher Ferris33d73372021-07-02 15:46:18 -0700665TEST(MallocTests, DISABLED_exit_while_threads_freeing_allocs_with_header) {
666 static constexpr size_t kMaxAllocsPerThread = 1000;
667 std::atomic_uint32_t thread_mask = {};
668 std::atomic_bool run;
669
670 std::vector<std::vector<void*>> allocs(kMaxThreads);
671 // Pre-allocate a bunch of memory so that we can try to trigger
672 // the frees after the main thread finishes.
673 for (size_t i = 0; i < kMaxThreads; i++) {
674 for (size_t j = 0; j < kMaxAllocsPerThread; j++) {
675 void* ptr = malloc(8);
676 ASSERT_TRUE(ptr != nullptr);
677 allocs[i].push_back(ptr);
678 }
679 }
680
681 for (size_t i = 0; i < kMaxThreads; i++) {
682 std::thread malloc_thread([&thread_mask, &run, &allocs, i] {
Greg Kaiser5358cc42021-07-15 07:45:51 -0700683 thread_mask.fetch_or(1U << i);
Christopher Ferris33d73372021-07-02 15:46:18 -0700684 while (!run)
685 ;
686 for (auto ptr : allocs[i]) {
687 free(ptr);
688 }
689 });
690 malloc_thread.detach();
691 }
692
693 // Wait until all threads are running.
694 while (thread_mask.load() != UINT32_MAX)
695 ;
696 run = true;
697 exit(kExpectedExitCode);
698}
699
Christopher Ferris4990c2d2021-07-22 13:17:34 -0700700TEST_F(MallocDebugSystemTest, exit_while_threads_freeing_allocs_with_header) {
Christopher Ferris33d73372021-07-02 15:46:18 -0700701 for (size_t i = 0; i < 50; i++) {
702 SCOPED_TRACE(::testing::Message() << "Run " << i);
Christopher Ferris33d73372021-07-02 15:46:18 -0700703 // Enable guard to force the use of a header.
704 ASSERT_NO_FATAL_FAILURE(
705 Exec("MallocTests.DISABLED_exit_while_threads_freeing_allocs_with_header", "verbose guard",
Christopher Ferris4990c2d2021-07-22 13:17:34 -0700706 kExpectedExitCode));
Christopher Ferris33d73372021-07-02 15:46:18 -0700707
Christopher Ferris4990c2d2021-07-22 13:17:34 -0700708 std::string log_str = log_crash_->GetLog();
Christopher Ferris33d73372021-07-02 15:46:18 -0700709 ASSERT_TRUE(log_str.find("Fatal signal") == std::string::npos)
Christopher Ferris4990c2d2021-07-22 13:17:34 -0700710 << "Found crash in log.\nLog message: " << log_str << " pid: " << pid_;
Christopher Ferris33d73372021-07-02 15:46:18 -0700711 }
712}
713
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800714TEST(MallocTests, DISABLED_write_leak_info) {
715 TemporaryFile tf;
716 ASSERT_TRUE(tf.fd != -1);
717
718 FILE* fp = fdopen(tf.fd, "w+");
719 if (fp == nullptr) {
720 printf("Unable to create %s\n", tf.path);
721 _exit(1);
722 }
723 tf.release();
724
725 void* ptr = malloc(1000);
726 if (ptr == nullptr) {
727 printf("malloc failed\n");
728 _exit(1);
729 }
730 memset(ptr, 0, 1000);
731
732 android_mallopt(M_WRITE_MALLOC_LEAK_INFO_TO_FILE, fp, sizeof(fp));
733
734 fclose(fp);
735
736 free(ptr);
737}
738
Christopher Ferris4990c2d2021-07-22 13:17:34 -0700739TEST_F(MallocDebugSystemTest, write_leak_info_no_header) {
Christopher Ferrisd9d9ee82021-07-23 17:10:58 -0700740 unexpected_log_strings_.push_back(" HAS INVALID TAG ");
741 unexpected_log_strings_.push_back("USED AFTER FREE ");
742 unexpected_log_strings_.push_back("UNKNOWN POINTER ");
743 Exec("MallocTests.DISABLED_write_leak_info", "verbose backtrace");
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800744}
745
Christopher Ferris4990c2d2021-07-22 13:17:34 -0700746TEST_F(MallocDebugSystemTest, write_leak_info_header) {
Christopher Ferrisd9d9ee82021-07-23 17:10:58 -0700747 unexpected_log_strings_.push_back(" HAS INVALID TAG ");
748 unexpected_log_strings_.push_back("USED AFTER FREE ");
749 unexpected_log_strings_.push_back("UNKNOWN POINTER ");
750 Exec("MallocTests.DISABLED_write_leak_info", "verbose backtrace guard");
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800751}
Christopher Ferris9bf78172020-05-20 15:37:30 -0700752
753TEST(MallocTests, DISABLED_malloc_and_backtrace_deadlock) {
754 std::atomic_bool running(false);
755 pid_t tid;
756 std::thread thread([&tid, &running] {
757 tid = gettid();
758 running = true;
759 while (running) {
760 void* ptr = malloc(200);
761 if (ptr == nullptr) {
762 return;
763 }
764 free(ptr);
765 }
766 });
767
768 while (!running) {
769 }
770
771 static constexpr size_t kNumUnwinds = 1000;
Christopher Ferrisdfbc59a2022-03-23 12:22:36 -0700772 unwindstack::AndroidLocalUnwinder unwinder;
Christopher Ferris9bf78172020-05-20 15:37:30 -0700773 for (size_t i = 0; i < kNumUnwinds; i++) {
Christopher Ferris33d73372021-07-02 15:46:18 -0700774 // Only verify that there is at least one frame in the unwind.
775 // This is not a test of the unwinder and clang for arm seems to
776 // produces an increasing number of code that does not have unwind
777 // information.
Christopher Ferrisdfbc59a2022-03-23 12:22:36 -0700778 unwindstack::AndroidUnwinderData data;
779 ASSERT_TRUE(unwinder.Unwind(data)) << "Failed on unwind " << i;
Christopher Ferris9bf78172020-05-20 15:37:30 -0700780 }
781 running = false;
782 thread.join();
783}
784
Christopher Ferris4990c2d2021-07-22 13:17:34 -0700785TEST_F(MallocDebugSystemTest, malloc_and_backtrace_deadlock) {
Christopher Ferris9bf78172020-05-20 15:37:30 -0700786 // Make sure that malloc debug is enabled and that no timeouts occur during
787 // unwinds.
Christopher Ferrisd9d9ee82021-07-23 17:10:58 -0700788 unexpected_log_strings_.push_back("Timed out waiting for ");
789 Exec("MallocTests.DISABLED_malloc_and_backtrace_deadlock", "verbose verify_pointers", 0);
Christopher Ferris9bf78172020-05-20 15:37:30 -0700790}