summaryrefslogtreecommitdiff
path: root/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
diff options
context:
space:
mode:
authorChristopher Ferris <cferris@google.com>2016-03-15 22:39:39 -0700
committerChristopher Ferris <cferris@google.com>2016-03-16 17:38:08 -0700
commitd0919623a2ef56107590eca9a9522a250fb8bd4a (patch)
treeb0e66ab45ca64f3fb90e03205ebd814f5c55c4f0 /libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
parent8d0af0bf8004c65f13b985643004a915d7e382eb (diff)
Fix race in malloc debug option free_track.
The free track mechanism could fail if, at the same time a free occurs, another thread is trying to free and verify the same allocation. This doesn't work if the freed allocation is added to the list and we still do work on it. The fix is to only add to the free list when we are done with the allocation. Also fix a problem where the usable size is computed incorrectly because two of the arguments where reversed. In addition, add a check that the allocation being verified has the correct tag before trying to check the body of the allocation. Add a test to catch the original failure. Add a test for the tag being different. Bug: 27601650 Change-Id: Ie9200677d066255b8e668a48422f23f909f4ddee
Diffstat (limited to 'libc/malloc_debug/tests/malloc_debug_unit_tests.cpp')
-rw-r--r--libc/malloc_debug/tests/malloc_debug_unit_tests.cpp48
1 files changed, 48 insertions, 0 deletions
diff --git a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
index 2503981b0..b6bf7bc43 100644
--- a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
+++ b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
@@ -24,6 +24,7 @@
#include <unistd.h>
#include <algorithm>
+#include <thread>
#include <vector>
#include <utility>
@@ -898,6 +899,53 @@ TEST_F(MallocDebugTest, free_track_use_after_free_call_free) {
ASSERT_STREQ(expected_log.c_str(), getFakeLogPrint().c_str());
}
+TEST_F(MallocDebugTest, free_track_header_tag_corrupted) {
+ Init("free_track=100 free_track_backtrace_num_frames=0");
+
+ uint8_t* pointer = reinterpret_cast<uint8_t*>(debug_malloc(100));
+ ASSERT_TRUE(pointer != nullptr);
+ memset(pointer, 0, 100);
+ debug_free(pointer);
+
+ pointer[-get_tag_offset()] = 0x00;
+
+ ASSERT_STREQ("", getFakeLogBuf().c_str());
+ ASSERT_STREQ("", getFakeLogPrint().c_str());
+
+ debug_finalize();
+ initialized = false;
+
+ ASSERT_STREQ("", getFakeLogBuf().c_str());
+ std::string expected_log(DIVIDER);
+ expected_log += android::base::StringPrintf(
+ "6 malloc_debug +++ ALLOCATION %p HAS CORRUPTED HEADER TAG 0x1cc7dc00 AFTER FREE\n",
+ pointer);
+ expected_log += DIVIDER;
+ ASSERT_STREQ(expected_log.c_str(), getFakeLogPrint().c_str());
+}
+
+TEST_F(MallocDebugTest, free_track_multiple_thread) {
+ Init("free_track=10 free_track_backtrace_num_frames=0");
+
+ std::vector<std::thread*> threads(1000);
+ for (size_t i = 0; i < threads.size(); i++) {
+ threads[i] = new std::thread([](){
+ for (size_t j = 0; j < 100; j++) {
+ void* mem = debug_malloc(100);
+ write(0, mem, 0);
+ debug_free(mem);
+ }
+ });
+ }
+ for (size_t i = 0; i < threads.size(); i++) {
+ threads[i]->join();
+ delete threads[i];
+ }
+
+ ASSERT_STREQ("", getFakeLogBuf().c_str());
+ ASSERT_STREQ("", getFakeLogPrint().c_str());
+}
+
TEST_F(MallocDebugTest, get_malloc_leak_info_invalid) {
Init("fill");