Home | History | Annotate | Download | only in tests
      1 /*
      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>
     32 #include <signal.h>
     33 #include <stdio.h>
     34 #include <stdlib.h>
     35 #include <sys/types.h>
     36 #include <sys/wait.h>
     37 #include <time.h>
     38 #include <unistd.h>
     39 
     40 #include <android-base/stringprintf.h>
     41 #include <gtest/gtest.h>
     42 #include <log/log.h>
     43 
     44 #include <string>
     45 #include <thread>
     46 #include <vector>
     47 
     48 #include "private/bionic_malloc.h"
     49 
     50 static constexpr time_t kTimeoutSeconds = 10;
     51 
     52 static void Exec(const char* test_name, const char* debug_options, pid_t* pid, int exit_code = 0,
     53                  time_t timeout_seconds = kTimeoutSeconds) {
     54   int fds[2];
     55   ASSERT_NE(-1, pipe(fds));
     56   ASSERT_NE(-1, fcntl(fds[0], F_SETFL, O_NONBLOCK));
     57   if ((*pid = fork()) == 0) {
     58     ASSERT_EQ(0, setenv("LIBC_DEBUG_MALLOC_OPTIONS", debug_options, 1));
     59     close(fds[0]);
     60     close(STDIN_FILENO);
     61     close(STDOUT_FILENO);
     62     close(STDERR_FILENO);
     63     ASSERT_NE(0, dup2(fds[1], STDOUT_FILENO));
     64     ASSERT_NE(0, dup2(fds[1], STDERR_FILENO));
     65 
     66     std::vector<const char*> args;
     67     // Get a copy of this argument so it doesn't disappear on us.
     68     std::string exec(testing::internal::GetArgvs()[0]);
     69     args.push_back(exec.c_str());
     70     args.push_back("--gtest_also_run_disabled_tests");
     71     std::string filter_arg = std::string("--gtest_filter=") + test_name;
     72     args.push_back(filter_arg.c_str());
     73     args.push_back(nullptr);
     74     execv(args[0], reinterpret_cast<char* const*>(const_cast<char**>(args.data())));
     75     exit(20);
     76   }
     77   ASSERT_NE(-1, *pid);
     78   close(fds[1]);
     79 
     80   std::string output;
     81   std::vector<char> buffer(4096);
     82   time_t start_time = time(nullptr);
     83   bool done = false;
     84   while (true) {
     85     struct pollfd read_fd = {.fd = fds[0], .events = POLLIN};
     86     if (TEMP_FAILURE_RETRY(poll(&read_fd, 1, 1)) > 0) {
     87       ssize_t bytes = TEMP_FAILURE_RETRY(read(fds[0], buffer.data(), sizeof(buffer) - 1));
     88       if (bytes == -1 && errno == EAGAIN) {
     89         continue;
     90       }
     91       ASSERT_NE(-1, bytes);
     92       if (bytes == 0) {
     93         done = true;
     94         break;
     95       }
     96       output.append(buffer.data(), bytes);
     97     }
     98 
     99     if ((time(nullptr) - start_time) > timeout_seconds) {
    100       kill(*pid, SIGINT);
    101       break;
    102     }
    103   }
    104   EXPECT_TRUE(done) << "Timed out while reading data, output:\n" << output;
    105 
    106   done = false;
    107   int status;
    108   start_time = time(nullptr);
    109   while (true) {
    110     int wait_pid = waitpid(*pid, &status, WNOHANG);
    111     if (*pid == wait_pid) {
    112       done = true;
    113       break;
    114     }
    115     if ((time(nullptr) - start_time) > timeout_seconds) {
    116       break;
    117     }
    118   }
    119   if (!done) {
    120     kill(*pid, SIGKILL);
    121     start_time = time(nullptr);
    122     while (true) {
    123       int kill_status;
    124       int wait_pid = waitpid(*pid, &kill_status, WNOHANG);
    125       if (wait_pid == *pid || (time(nullptr) - start_time) > timeout_seconds) {
    126         break;
    127       }
    128     }
    129   }
    130 
    131   ASSERT_TRUE(done) << "Timed out waiting for waitpid, output:\n" << output;
    132   ASSERT_FALSE(WIFSIGNALED(status))
    133       << "Failed with signal " << WTERMSIG(status) << "\nOutput:\n" << output;
    134   ASSERT_EQ(exit_code, WEXITSTATUS(status)) << "Output:\n" << output;
    135 }
    136 
    137 static void GetLogStr(pid_t pid, std::string* log_str, log_id log = LOG_ID_MAIN) {
    138   log_str->clear();
    139 
    140   logger_list* list;
    141   list = android_logger_list_open(log, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid);
    142   ASSERT_TRUE(list != nullptr);
    143 
    144   while (true) {
    145     log_msg msg;
    146     ssize_t actual = android_logger_list_read(list, &msg);
    147     if (actual < 0) {
    148       if (actual == -EINTR) {
    149         // Interrupted retry.
    150         continue;
    151       } else if (actual == -EAGAIN) {
    152         // Non-blocking EOF, finished.
    153         break;
    154       } else {
    155         break;
    156       }
    157     } else if (actual == 0) {
    158       break;
    159     }
    160     ASSERT_EQ(msg.entry.pid, pid);
    161 
    162     char* msg_str = msg.msg();
    163     if (msg_str != nullptr) {
    164       char* tag = msg_str + 1;
    165       msg_str = tag + strlen(tag) + 1;
    166       *log_str += msg_str;
    167       if (log_str->back() != '\n') {
    168         *log_str += '\n';
    169       }
    170     }
    171   }
    172 
    173   android_logger_list_close(list);
    174 }
    175 
    176 static void FindStrings(pid_t pid, std::vector<const char*> match_strings,
    177                         time_t timeout_seconds = kTimeoutSeconds) {
    178   std::string log_str;
    179   time_t start = time(nullptr);
    180   bool found_all;
    181   while (true) {
    182     GetLogStr(pid, &log_str);
    183     found_all = true;
    184     for (auto str : match_strings) {
    185       if (log_str.find(str) == std::string::npos) {
    186         found_all = false;
    187         break;
    188       }
    189     }
    190     if (found_all) {
    191       return;
    192     }
    193     if ((time(nullptr) - start) > timeout_seconds) {
    194       break;
    195     }
    196   }
    197   ASSERT_TRUE(found_all) << "Didn't find expected log output:\n" + log_str;
    198 }
    199 
    200 TEST(MallocTests, DISABLED_smoke) {}
    201 
    202 TEST(MallocDebugSystemTest, smoke) {
    203   pid_t pid;
    204   ASSERT_NO_FATAL_FAILURE(Exec("MallocTests.DISABLED_smoke", "verbose backtrace", &pid));
    205 
    206   ASSERT_NO_FATAL_FAILURE(FindStrings(pid, std::vector<const char*>{"malloc debug enabled"}));
    207 }
    208 
    209 static void SetAllocationLimit() {
    210   // Set to a large value, this is only to enable the limit code and
    211   // verify that malloc debug is still called properly.
    212   size_t limit = 500 * 1024 * 1024;
    213   ASSERT_TRUE(android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &limit, sizeof(limit)));
    214 }
    215 
    216 static void AlignedAlloc() {
    217   void* ptr = aligned_alloc(64, 1152);
    218   ASSERT_TRUE(ptr != nullptr);
    219   memset(ptr, 0, 1152);
    220 }
    221 
    222 TEST(MallocTests, DISABLED_leak_memory_aligned_alloc) {
    223   AlignedAlloc();
    224 }
    225 
    226 TEST(MallocTests, DISABLED_leak_memory_limit_aligned_alloc) {
    227   SetAllocationLimit();
    228   AlignedAlloc();
    229 }
    230 
    231 static void Calloc() {
    232   void* ptr = calloc(1, 1123);
    233   ASSERT_TRUE(ptr != nullptr);
    234   memset(ptr, 1, 1123);
    235 }
    236 
    237 TEST(MallocTests, DISABLED_leak_memory_calloc) {
    238   Calloc();
    239 }
    240 
    241 TEST(MallocTests, DISABLED_leak_memory_limit_calloc) {
    242   SetAllocationLimit();
    243   Calloc();
    244 }
    245 
    246 static void Malloc() {
    247   void* ptr = malloc(1123);
    248   ASSERT_TRUE(ptr != nullptr);
    249   memset(ptr, 0, 1123);
    250 }
    251 
    252 TEST(MallocTests, DISABLED_leak_memory_malloc) {
    253   Malloc();
    254 }
    255 
    256 TEST(MallocTests, DISABLED_leak_memory_limit_malloc) {
    257   SetAllocationLimit();
    258   Malloc();
    259 }
    260 
    261 static void Memalign() {
    262   void* ptr = memalign(64, 1123);
    263   ASSERT_TRUE(ptr != nullptr);
    264   memset(ptr, 0, 1123);
    265 }
    266 
    267 TEST(MallocTests, DISABLED_leak_memory_memalign) {
    268   Memalign();
    269 }
    270 
    271 TEST(MallocTests, DISABLED_leak_memory_limit_memalign) {
    272   SetAllocationLimit();
    273   Memalign();
    274 }
    275 
    276 static void PosixMemalign() {
    277   void* ptr;
    278   ASSERT_EQ(0, posix_memalign(&ptr, 64, 1123));
    279   ASSERT_TRUE(ptr != nullptr);
    280   memset(ptr, 0, 1123);
    281 }
    282 
    283 TEST(MallocTests, DISABLED_leak_memory_posix_memalign) {
    284   PosixMemalign();
    285 }
    286 
    287 TEST(MallocTests, DISABLED_leak_memory_limit_posix_memalign) {
    288   SetAllocationLimit();
    289   PosixMemalign();
    290 }
    291 
    292 static void Reallocarray() {
    293   void* ptr = reallocarray(nullptr, 1, 1123);
    294   ASSERT_TRUE(ptr != nullptr);
    295   memset(ptr, 0, 1123);
    296 }
    297 
    298 TEST(MallocTests, DISABLED_leak_memory_reallocarray) {
    299   Reallocarray();
    300 }
    301 
    302 TEST(MallocTests, DISABLED_leak_memory_limit_reallocarray) {
    303   SetAllocationLimit();
    304   Reallocarray();
    305 }
    306 
    307 static void Realloc() {
    308   void* ptr = realloc(nullptr, 1123);
    309   ASSERT_TRUE(ptr != nullptr);
    310   memset(ptr, 0, 1123);
    311 }
    312 
    313 TEST(MallocTests, DISABLED_leak_memory_realloc) {
    314   Realloc();
    315 }
    316 
    317 TEST(MallocTests, DISABLED_leak_memory_limit_realloc) {
    318   SetAllocationLimit();
    319   Realloc();
    320 }
    321 
    322 #if !defined(__LP64__)
    323 extern "C" void* pvalloc(size_t);
    324 
    325 static void Pvalloc() {
    326   void* ptr = pvalloc(1123);
    327   ASSERT_TRUE(ptr != nullptr);
    328   memset(ptr, 0, 1123);
    329 }
    330 
    331 TEST(MallocTests, DISABLED_leak_memory_pvalloc) {
    332   Pvalloc();
    333 }
    334 
    335 TEST(MallocTests, DISABLED_leak_memory_limit_pvalloc) {
    336   SetAllocationLimit();
    337   Pvalloc();
    338 }
    339 
    340 extern "C" void* valloc(size_t);
    341 
    342 static void Valloc() {
    343   void* ptr = valloc(1123);
    344   ASSERT_TRUE(ptr != nullptr);
    345   memset(ptr, 0, 1123);
    346 }
    347 
    348 TEST(MallocTests, DISABLED_leak_memory_valloc) {
    349   Valloc();
    350 }
    351 
    352 TEST(MallocTests, DISABLED_leak_memory_limit_valloc) {
    353   SetAllocationLimit();
    354   Valloc();
    355 }
    356 #endif
    357 
    358 static void VerifyLeak(const char* test_prefix) {
    359   struct FunctionInfo {
    360     const char* name;
    361     size_t size;
    362   };
    363   static FunctionInfo functions[] = {
    364     {
    365       "aligned_alloc",
    366       1152,
    367     },
    368     {
    369       "calloc",
    370       1123,
    371     },
    372     {
    373       "malloc",
    374       1123,
    375     },
    376     {
    377       "memalign",
    378       1123,
    379     },
    380     {
    381       "posix_memalign",
    382       1123,
    383     },
    384     {
    385       "reallocarray",
    386       1123,
    387     },
    388     {
    389       "realloc",
    390       1123,
    391     },
    392 #if !defined(__LP64__)
    393     {
    394       "pvalloc",
    395       4096,
    396     },
    397     {
    398       "valloc",
    399       1123,
    400     }
    401 #endif
    402   };
    403 
    404   for (size_t i = 0; i < sizeof(functions) / sizeof(FunctionInfo); i++) {
    405     pid_t pid;
    406     SCOPED_TRACE(testing::Message() << functions[i].name << " expected size " << functions[i].size);
    407     std::string test = std::string("MallocTests.DISABLED_") + test_prefix + functions[i].name;
    408     EXPECT_NO_FATAL_FAILURE(Exec(test.c_str(), "verbose backtrace leak_track", &pid));
    409 
    410     std::string expected_leak = android::base::StringPrintf("leaked block of size %zu at", functions[i].size);
    411     EXPECT_NO_FATAL_FAILURE(FindStrings(
    412         pid, std::vector<const char*>{"malloc debug enabled", expected_leak.c_str()}));
    413   }
    414 }
    415 
    416 TEST(MallocDebugSystemTest, verify_leak) {
    417   VerifyLeak("leak_memory_");
    418 }
    419 
    420 TEST(MallocDebugSystemTest, verify_leak_allocation_limit) {
    421   VerifyLeak("leak_memory_limit_");
    422 }
    423 
    424 static constexpr int kExpectedExitCode = 30;
    425 
    426 TEST(MallocTests, DISABLED_exit_while_threads_allocating) {
    427   std::atomic_uint32_t thread_mask;
    428   thread_mask = 0;
    429 
    430   for (size_t i = 0; i < 32; i++) {
    431     std::thread malloc_thread([&thread_mask, i] {
    432       while (true) {
    433         void* ptr = malloc(100);
    434         if (ptr == nullptr) {
    435           exit(1000);
    436         }
    437         free(ptr);
    438         thread_mask.fetch_or(1 << i);
    439       }
    440     });
    441     malloc_thread.detach();
    442   }
    443 
    444   // Wait until each thread has done at least one allocation.
    445   while (thread_mask.load() != 0xffffffff)
    446     ;
    447   exit(kExpectedExitCode);
    448 }
    449 
    450 // Verify that exiting while other threads are doing malloc operations,
    451 // that there are no crashes.
    452 TEST(MallocDebugSystemTest, exit_while_threads_allocating) {
    453   for (size_t i = 0; i < 100; i++) {
    454     SCOPED_TRACE(::testing::Message() << "Run " << i);
    455     pid_t pid;
    456     ASSERT_NO_FATAL_FAILURE(Exec("MallocTests.DISABLED_exit_while_threads_allocating",
    457                                  "verbose backtrace", &pid, kExpectedExitCode));
    458 
    459     ASSERT_NO_FATAL_FAILURE(FindStrings(pid, std::vector<const char*>{"malloc debug enabled"}));
    460 
    461     std::string log_str;
    462     GetLogStr(pid, &log_str, LOG_ID_CRASH);
    463     ASSERT_TRUE(log_str.find("Fatal signal") == std::string::npos)
    464         << "Found crash in log.\nLog message: " << log_str;
    465   }
    466 }
    467