aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Ferris <cferris@google.com>2018-05-01 12:59:37 -0700
committerChristopher Ferris <cferris@google.com>2018-05-02 14:42:33 -0700
commita9001ceb0a5083f9786652918d16cafbdabcf459 (patch)
tree7b7fd4a17a8a704b729477d4a6dd315c2da8c92d
parent94f7a87510138ac7b061611b181fa6e995d41764 (diff)
downloadbionic-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.cpp6
-rw-r--r--libc/malloc_debug/tests/malloc_debug_unit_tests.cpp47
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");