Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 32fcdf8d authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Make memunreachable_test more robust against false negative leaks"

parents 313aa717 ca71f170
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -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)) {
+1 −6
Original line number Diff line number Diff line
@@ -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;
};
+57 −9
Original line number Diff line number Diff line
@@ -23,6 +23,8 @@

#include <memunreachable/memunreachable.h>

#include "bionic.h"

namespace android {

class HiddenPointer {
@@ -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));
@@ -57,7 +87,7 @@ TEST(MemunreachableTest, clean) {
  ASSERT_EQ(0U, info.leaks.size());
}

TEST(MemunreachableTest, stack) {
TEST_F(MemunreachableTest, stack) {
  HiddenPointer hidden_ptr;

  {
@@ -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();
@@ -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);
@@ -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;

@@ -184,7 +226,7 @@ TEST(MemunreachableTest, twice) {
  }
}

TEST(MemunreachableTest, log) {
TEST_F(MemunreachableTest, log) {
  HiddenPointer hidden_ptr;

  ASSERT_TRUE(LogUnreachableMemory(true, 100));
@@ -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);