Loading libmemunreachable/MemUnreachable.cpp +15 −0 Original line number Diff line number Diff line Loading @@ -495,6 +495,21 @@ std::string UnreachableMemoryInfo::ToString(bool log_contents) const { return oss.str(); } UnreachableMemoryInfo::~UnreachableMemoryInfo() { // Clear the memory that holds the leaks, otherwise the next attempt to // detect leaks may find the old data (for example in the jemalloc tcache) // and consider all the leaks to be referenced. memset(leaks.data(), 0, leaks.capacity() * sizeof(Leak)); std::vector<Leak> tmp; leaks.swap(tmp); // Disable and re-enable malloc to flush the jemalloc tcache to make sure // there are no copies of the leaked pointer addresses there. malloc_disable(); malloc_enable(); } std::string GetUnreachableMemoryString(bool log_contents, size_t limit) { UnreachableMemoryInfo info; if (!GetUnreachableMemory(info, limit)) { Loading libmemunreachable/include/memunreachable/memunreachable.h +1 −6 Original line number Diff line number Diff line Loading @@ -62,12 +62,7 @@ struct UnreachableMemoryInfo { size_t allocation_bytes; UnreachableMemoryInfo() {} ~UnreachableMemoryInfo() { // Clear the memory that holds the leaks, otherwise the next attempt to // detect leaks may find the old data (for example in the jemalloc tcache) // and consider all the leaks to be referenced. memset(leaks.data(), 0, leaks.capacity() * sizeof(Leak)); } ~UnreachableMemoryInfo(); std::string ToString(bool log_contents) const; }; Loading libmemunreachable/tests/MemUnreachable_test.cpp +57 −9 Original line number Diff line number Diff line Loading @@ -23,6 +23,8 @@ #include <memunreachable/memunreachable.h> #include "bionic.h" namespace android { class HiddenPointer { Loading @@ -48,7 +50,35 @@ static void Ref(void** ptr) { write(0, ptr, 0); } TEST(MemunreachableTest, clean) { class MemunreachableTest : public ::testing::Test { protected: virtual void SetUp() { CleanStack(8192); CleanTcache(); } virtual void TearDown() { CleanStack(8192); CleanTcache(); } // Allocate a buffer on the stack and zero it to make sure there are no // stray pointers from old test runs. void __attribute__((noinline)) CleanStack(size_t size) { void* buf = alloca(size); memset(buf, 0, size); Ref(&buf); } // Disable and re-enable malloc to flush the jemalloc tcache to make sure // there are stray pointers from old test runs there. void CleanTcache() { malloc_disable(); malloc_enable(); } }; TEST_F(MemunreachableTest, clean) { UnreachableMemoryInfo info; ASSERT_TRUE(LogUnreachableMemory(true, 100)); Loading @@ -57,7 +87,7 @@ TEST(MemunreachableTest, clean) { ASSERT_EQ(0U, info.leaks.size()); } TEST(MemunreachableTest, stack) { TEST_F(MemunreachableTest, stack) { HiddenPointer hidden_ptr; { Loading Loading @@ -91,7 +121,7 @@ TEST(MemunreachableTest, stack) { void* g_ptr; TEST(MemunreachableTest, global) { TEST_F(MemunreachableTest, global) { HiddenPointer hidden_ptr; g_ptr = hidden_ptr.Get(); Loading Loading @@ -122,7 +152,7 @@ TEST(MemunreachableTest, global) { } } TEST(MemunreachableTest, tls) { TEST_F(MemunreachableTest, tls) { HiddenPointer hidden_ptr; pthread_key_t key; pthread_key_create(&key, nullptr); Loading Loading @@ -157,9 +187,21 @@ TEST(MemunreachableTest, tls) { pthread_key_delete(key); } TEST(MemunreachableTest, twice) { TEST_F(MemunreachableTest, twice) { HiddenPointer hidden_ptr; { void* ptr = hidden_ptr.Get(); Ref(&ptr); UnreachableMemoryInfo info; ASSERT_TRUE(GetUnreachableMemory(info)); ASSERT_EQ(0U, info.leaks.size()); ptr = nullptr; } { UnreachableMemoryInfo info; Loading @@ -184,7 +226,7 @@ TEST(MemunreachableTest, twice) { } } TEST(MemunreachableTest, log) { TEST_F(MemunreachableTest, log) { HiddenPointer hidden_ptr; ASSERT_TRUE(LogUnreachableMemory(true, 100)); Loading @@ -199,17 +241,23 @@ TEST(MemunreachableTest, log) { } } TEST(MemunreachableTest, notdumpable) { TEST_F(MemunreachableTest, notdumpable) { if (getuid() == 0) { // TODO(ccross): make this a skipped test when gtest supports them printf("[ SKIP ] Not testable when running as root\n"); return; } ASSERT_EQ(0, prctl(PR_SET_DUMPABLE, 0)); HiddenPointer hidden_ptr; ASSERT_TRUE(LogUnreachableMemory(true, 100)); EXPECT_FALSE(LogUnreachableMemory(true, 100)); ASSERT_EQ(0, prctl(PR_SET_DUMPABLE, 1)); } TEST(MemunreachableTest, leak_lots) { TEST_F(MemunreachableTest, leak_lots) { std::vector<HiddenPointer> hidden_ptrs; hidden_ptrs.resize(1024); Loading Loading
libmemunreachable/MemUnreachable.cpp +15 −0 Original line number Diff line number Diff line Loading @@ -495,6 +495,21 @@ std::string UnreachableMemoryInfo::ToString(bool log_contents) const { return oss.str(); } UnreachableMemoryInfo::~UnreachableMemoryInfo() { // Clear the memory that holds the leaks, otherwise the next attempt to // detect leaks may find the old data (for example in the jemalloc tcache) // and consider all the leaks to be referenced. memset(leaks.data(), 0, leaks.capacity() * sizeof(Leak)); std::vector<Leak> tmp; leaks.swap(tmp); // Disable and re-enable malloc to flush the jemalloc tcache to make sure // there are no copies of the leaked pointer addresses there. malloc_disable(); malloc_enable(); } std::string GetUnreachableMemoryString(bool log_contents, size_t limit) { UnreachableMemoryInfo info; if (!GetUnreachableMemory(info, limit)) { Loading
libmemunreachable/include/memunreachable/memunreachable.h +1 −6 Original line number Diff line number Diff line Loading @@ -62,12 +62,7 @@ struct UnreachableMemoryInfo { size_t allocation_bytes; UnreachableMemoryInfo() {} ~UnreachableMemoryInfo() { // Clear the memory that holds the leaks, otherwise the next attempt to // detect leaks may find the old data (for example in the jemalloc tcache) // and consider all the leaks to be referenced. memset(leaks.data(), 0, leaks.capacity() * sizeof(Leak)); } ~UnreachableMemoryInfo(); std::string ToString(bool log_contents) const; }; Loading
libmemunreachable/tests/MemUnreachable_test.cpp +57 −9 Original line number Diff line number Diff line Loading @@ -23,6 +23,8 @@ #include <memunreachable/memunreachable.h> #include "bionic.h" namespace android { class HiddenPointer { Loading @@ -48,7 +50,35 @@ static void Ref(void** ptr) { write(0, ptr, 0); } TEST(MemunreachableTest, clean) { class MemunreachableTest : public ::testing::Test { protected: virtual void SetUp() { CleanStack(8192); CleanTcache(); } virtual void TearDown() { CleanStack(8192); CleanTcache(); } // Allocate a buffer on the stack and zero it to make sure there are no // stray pointers from old test runs. void __attribute__((noinline)) CleanStack(size_t size) { void* buf = alloca(size); memset(buf, 0, size); Ref(&buf); } // Disable and re-enable malloc to flush the jemalloc tcache to make sure // there are stray pointers from old test runs there. void CleanTcache() { malloc_disable(); malloc_enable(); } }; TEST_F(MemunreachableTest, clean) { UnreachableMemoryInfo info; ASSERT_TRUE(LogUnreachableMemory(true, 100)); Loading @@ -57,7 +87,7 @@ TEST(MemunreachableTest, clean) { ASSERT_EQ(0U, info.leaks.size()); } TEST(MemunreachableTest, stack) { TEST_F(MemunreachableTest, stack) { HiddenPointer hidden_ptr; { Loading Loading @@ -91,7 +121,7 @@ TEST(MemunreachableTest, stack) { void* g_ptr; TEST(MemunreachableTest, global) { TEST_F(MemunreachableTest, global) { HiddenPointer hidden_ptr; g_ptr = hidden_ptr.Get(); Loading Loading @@ -122,7 +152,7 @@ TEST(MemunreachableTest, global) { } } TEST(MemunreachableTest, tls) { TEST_F(MemunreachableTest, tls) { HiddenPointer hidden_ptr; pthread_key_t key; pthread_key_create(&key, nullptr); Loading Loading @@ -157,9 +187,21 @@ TEST(MemunreachableTest, tls) { pthread_key_delete(key); } TEST(MemunreachableTest, twice) { TEST_F(MemunreachableTest, twice) { HiddenPointer hidden_ptr; { void* ptr = hidden_ptr.Get(); Ref(&ptr); UnreachableMemoryInfo info; ASSERT_TRUE(GetUnreachableMemory(info)); ASSERT_EQ(0U, info.leaks.size()); ptr = nullptr; } { UnreachableMemoryInfo info; Loading @@ -184,7 +226,7 @@ TEST(MemunreachableTest, twice) { } } TEST(MemunreachableTest, log) { TEST_F(MemunreachableTest, log) { HiddenPointer hidden_ptr; ASSERT_TRUE(LogUnreachableMemory(true, 100)); Loading @@ -199,17 +241,23 @@ TEST(MemunreachableTest, log) { } } TEST(MemunreachableTest, notdumpable) { TEST_F(MemunreachableTest, notdumpable) { if (getuid() == 0) { // TODO(ccross): make this a skipped test when gtest supports them printf("[ SKIP ] Not testable when running as root\n"); return; } ASSERT_EQ(0, prctl(PR_SET_DUMPABLE, 0)); HiddenPointer hidden_ptr; ASSERT_TRUE(LogUnreachableMemory(true, 100)); EXPECT_FALSE(LogUnreachableMemory(true, 100)); ASSERT_EQ(0, prctl(PR_SET_DUMPABLE, 1)); } TEST(MemunreachableTest, leak_lots) { TEST_F(MemunreachableTest, leak_lots) { std::vector<HiddenPointer> hidden_ptrs; hidden_ptrs.resize(1024); Loading