diff options
author | Christopher Ferris <cferris@google.com> | 2018-05-01 12:59:37 -0700 |
---|---|---|
committer | Christopher Ferris <cferris@google.com> | 2018-05-02 14:42:33 -0700 |
commit | a9001ceb0a5083f9786652918d16cafbdabcf459 (patch) | |
tree | 7b7fd4a17a8a704b729477d4a6dd315c2da8c92d | |
parent | 94f7a87510138ac7b061611b181fa6e995d41764 (diff) | |
download | bionic-a9001ceb0a5083f9786652918d16cafbdabcf459.tar.gz |
Fix nullptr dereference during sort.
Add new unit test that will crash without this fix.
Bug: 78900050
Test: Ran unit tests.
Change-Id: I73e1b89e965a7b399822c3a6f25cbc70d2d355e2
(cherry picked from commit c151bc30789ade22d5423b20d2c72948284bba3c)
-rw-r--r-- | libc/malloc_debug/PointerData.cpp | 6 | ||||
-rw-r--r-- | libc/malloc_debug/tests/malloc_debug_unit_tests.cpp | 47 |
2 files changed, 51 insertions, 2 deletions
diff --git a/libc/malloc_debug/PointerData.cpp b/libc/malloc_debug/PointerData.cpp index f811a5eb4..85139e607 100644 --- a/libc/malloc_debug/PointerData.cpp +++ b/libc/malloc_debug/PointerData.cpp @@ -392,10 +392,12 @@ void PointerData::GetList(std::vector<ListInfoType>* list, bool only_with_backtr FrameInfoType* b_frame = b.frame_info; if (a_frame == nullptr && b_frame != nullptr) { return false; - } - if (a_frame != nullptr && b_frame == nullptr) { + } else if (a_frame != nullptr && b_frame == nullptr) { return true; + } else if (a_frame == nullptr && b_frame == nullptr) { + return a.pointer < b.pointer; } + // Put the pointers with longest backtrace first. if (a_frame->frames.size() != b_frame->frames.size()) { return a_frame->frames.size() > b_frame->frames.size(); diff --git a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp index 8b2818872..1504d06dd 100644 --- a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp +++ b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp @@ -1756,6 +1756,53 @@ TEST_F(MallocDebugTest, backtrace_same_stack_mix_zygote) { ASSERT_STREQ(expected_log.c_str(), getFakeLogPrint().c_str()); } +TEST_F(MallocDebugTest, backtrace_frame_data_nullptr_same_size) { + Init("backtrace=4"); + + size_t individual_size = GetInfoEntrySize(4); + + void* pointers[4]; + pointers[0] = debug_malloc(100); + ASSERT_TRUE(pointers[0] != nullptr); + pointers[1] = debug_malloc(100); + ASSERT_TRUE(pointers[1] != nullptr); + pointers[2] = debug_malloc(100); + ASSERT_TRUE(pointers[2] != nullptr); + pointers[3] = debug_malloc(100); + ASSERT_TRUE(pointers[3] != nullptr); + + uint8_t* info; + size_t overall_size; + size_t info_size; + size_t total_memory; + size_t backtrace_size; + + debug_get_malloc_leak_info(&info, &overall_size, &info_size, &total_memory, &backtrace_size); + ASSERT_TRUE(info != nullptr); + ASSERT_EQ(individual_size, overall_size); + EXPECT_EQ(individual_size, info_size); + EXPECT_EQ(400U, total_memory); + EXPECT_EQ(4U, backtrace_size); + + EXPECT_EQ(100U, *reinterpret_cast<size_t*>(&info[0])); + EXPECT_EQ(4U, *reinterpret_cast<size_t*>(&info[sizeof(size_t)])); + uintptr_t* ips = reinterpret_cast<uintptr_t*>(&info[2 * sizeof(size_t)]); + EXPECT_EQ(0U, ips[0]); + + debug_free_malloc_leak_info(info); + + debug_free(pointers[0]); + debug_free(pointers[1]); + debug_free(pointers[2]); + debug_free(pointers[3]); + + ASSERT_STREQ("", getFakeLogBuf().c_str()); + std::string expected_log = android::base::StringPrintf( + "4 malloc_debug malloc_testing: Run: 'kill -%d %d' to dump the backtrace.\n", + SIGRTMAX - 17, getpid()); + ASSERT_STREQ(expected_log.c_str(), getFakeLogPrint().c_str()); +} + TEST_F(MallocDebugTest, overflow) { Init("guard fill_on_free"); |