Coverage for /Syzygy/agent/asan/asan_heap_unittest.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
98.0%991010.C++test

Line-by-line coverage:

   1    :  // Copyright 2012 Google Inc.
   2    :  //
   3    :  // Licensed under the Apache License, Version 2.0 (the "License");
   4    :  // you may not use this file except in compliance with the License.
   5    :  // You may obtain a copy of the License at
   6    :  //
   7    :  //     http://www.apache.org/licenses/LICENSE-2.0
   8    :  //
   9    :  // Unless required by applicable law or agreed to in writing, software
  10    :  // distributed under the License is distributed on an "AS IS" BASIS,
  11    :  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12    :  // See the License for the specific language governing permissions and
  13    :  // limitations under the License.
  14    :  #include "syzygy/agent/asan/asan_heap.h"
  15    :  
  16    :  #include "base/compiler_specific.h"
  17    :  #include "base/logging.h"
  18    :  #include "base/rand_util.h"
  19    :  #include "base/sha1.h"
  20    :  #include "base/debug/debugger.h"
  21    :  #include "gtest/gtest.h"
  22    :  #include "syzygy/agent/asan/asan_shadow.h"
  23    :  
  24    :  namespace agent {
  25    :  namespace asan {
  26    :  
  27    :  namespace {
  28    :  
  29    :  class HeapTest : public testing::Test {
  30    :   public:
  31  E :    virtual void SetUp() OVERRIDE {
  32  E :      ASSERT_TRUE(proxy_.Create(0, 0, 0));
  33  E :    }
  34    :  
  35  E :    virtual void TearDown() OVERRIDE {
  36  E :      ASSERT_TRUE(proxy_.Destroy());
  37  E :    }
  38    :  
  39    :    // Verifies that [alloc, alloc + size) is accessible, and that
  40    :    // [alloc - 1] and [alloc+size] are poisoned.
  41  E :    void VerifyAllocAccess(void* alloc, size_t size) {
  42  E :      uint8* mem = reinterpret_cast<uint8*>(alloc);
  43  E :      ASSERT_FALSE(Shadow::IsAccessible(mem - 1));
  44  E :      for (size_t i = 0; i < size; ++i)
  45  E :        ASSERT_TRUE(Shadow::IsAccessible(mem + i));
  46  E :      ASSERT_FALSE(Shadow::IsAccessible(mem + size));
  47  E :    }
  48    :  
  49    :    // Verifies that [alloc-1, alloc+size] is poisoned.
  50  E :    void VerifyFreedAccess(void* alloc, size_t size) {
  51  E :      uint8* mem = reinterpret_cast<uint8*>(alloc);
  52  E :      ASSERT_FALSE(Shadow::IsAccessible(mem - 1));
  53  E :      for (size_t i = 0; i < size; ++i)
  54  E :        ASSERT_FALSE(Shadow::IsAccessible(mem + i));
  55  E :      ASSERT_FALSE(Shadow::IsAccessible(mem + size));
  56  E :    }
  57    :  
  58  E :    void RandomSetMemory(void* alloc, size_t size) {
  59  E :      base::RandBytes(alloc, size);
  60  E :    }
  61    :  
  62    :   protected:
  63    :    // Arbitrary constant for all size limit.
  64    :    static const size_t kMaxAllocSize = 134584;
  65    :  
  66    :    HeapProxy proxy_;
  67    :  };
  68    :  
  69    :  }  // namespace
  70    :  
  71  E :  TEST_F(HeapTest, ToFromHandle) {
  72  E :    HANDLE handle = HeapProxy::ToHandle(&proxy_);
  73  E :    ASSERT_TRUE(handle != NULL);
  74  E :    ASSERT_EQ(&proxy_, HeapProxy::FromHandle(handle));
  75  E :  }
  76    :  
  77  E :  TEST_F(HeapTest, AllocFree) {
  78  E :    const size_t kAllocSize = 100;
  79  E :    LPVOID mem = proxy_.Alloc(0, kAllocSize);
  80  E :    ASSERT_TRUE(mem != NULL);
  81  E :    ASSERT_EQ(kAllocSize, proxy_.Size(0, mem));
  82  E :    const size_t kReAllocSize = 2 * kAllocSize;
  83  E :    mem = proxy_.ReAlloc(0, mem, kReAllocSize);
  84  E :    ASSERT_EQ(kReAllocSize, proxy_.Size(0, mem));
  85  E :    ASSERT_TRUE(proxy_.Free(0, mem));
  86  E :  }
  87    :  
  88  E :  TEST_F(HeapTest, AllocsAccessibility) {
  89  E :    for (size_t size = 10; size < kMaxAllocSize; size = size * 5 + 123) {
  90    :      // Do an alloc/realloc/free and test that access is correctly managed.
  91  E :      void* mem = proxy_.Alloc(0, size);
  92  E :      ASSERT_TRUE(mem != NULL);
  93  E :      ASSERT_NO_FATAL_FAILURE(VerifyAllocAccess(mem, size));
  94  E :      RandomSetMemory(mem, size);
  95    :  
  96  E :      size_t new_size = size;
  97  E :      while (new_size == size)
  98  E :        new_size = base::RandInt(size / 2, size * 2);
  99    :  
 100  E :      unsigned char sha1_before[base::kSHA1Length] = {};
 101    :      base::SHA1HashBytes(reinterpret_cast<unsigned char*>(mem),
 102    :                          std::min(size, new_size),
 103  E :                          sha1_before);
 104    :  
 105  E :      void* new_mem = proxy_.ReAlloc(0, mem, size * 2);
 106  E :      ASSERT_TRUE(new_mem != NULL);
 107  E :      ASSERT_NE(mem, new_mem);
 108    :  
 109  E :      unsigned char sha1_after[base::kSHA1Length] = {};
 110    :      base::SHA1HashBytes(reinterpret_cast<unsigned char*>(new_mem),
 111    :                          std::min(size, new_size),
 112  E :                          sha1_after);
 113  E :      ASSERT_EQ(0, memcmp(sha1_before, sha1_after, base::kSHA1Length));
 114    :  
 115  E :      ASSERT_NO_FATAL_FAILURE(VerifyFreedAccess(mem, size));
 116  E :      ASSERT_NO_FATAL_FAILURE(VerifyAllocAccess(new_mem, size * 2));
 117    :  
 118  E :      ASSERT_TRUE(proxy_.Free(0, new_mem));
 119  E :      ASSERT_NO_FATAL_FAILURE(VerifyFreedAccess(new_mem, size * 2));
 120  E :    }
 121  E :  }
 122    :  
 123  E :  TEST_F(HeapTest, Size) {
 124  E :    for (size_t size = 10; size < kMaxAllocSize; size = size * 5 + 123) {
 125  E :      void* mem = proxy_.Alloc(0, size);
 126  E :      ASSERT_FALSE(mem == NULL);
 127  E :      ASSERT_EQ(size, proxy_.Size(0, mem));
 128  E :      ASSERT_TRUE(proxy_.Free(0, mem));
 129  E :    }
 130  E :  }
 131    :  
 132  E :  TEST_F(HeapTest, Validate) {
 133  E :    for (size_t size = 10; size < kMaxAllocSize; size = size * 5 + 123) {
 134  E :      void* mem = proxy_.Alloc(0, size);
 135  E :      ASSERT_FALSE(mem == NULL);
 136  E :      ASSERT_TRUE(proxy_.Validate(0, mem));
 137  E :      ASSERT_TRUE(proxy_.Free(0, mem));
 138  E :    }
 139  E :  }
 140    :  
 141  E :  TEST_F(HeapTest, Compact) {
 142    :    // Compact should return a non-zero size.
 143  E :    ASSERT_LT(0U, proxy_.Compact(0));
 144    :  
 145    :    // TODO(siggi): It may not be possible to allocate the size returned due
 146    :    //     to padding - fix and test.
 147  E :  }
 148    :  
 149  E :  TEST_F(HeapTest, LockUnlock) {
 150    :    // We can't really test these, aside from not crashing.
 151  E :    ASSERT_TRUE(proxy_.Lock());
 152  E :    ASSERT_TRUE(proxy_.Unlock());
 153  E :  }
 154    :  
 155  E :  TEST_F(HeapTest, Walk) {
 156    :    // We assume at least two entries to walk through.
 157  E :    PROCESS_HEAP_ENTRY entry = {};
 158  E :    ASSERT_TRUE(proxy_.Walk(&entry));
 159  E :    ASSERT_TRUE(proxy_.Walk(&entry));
 160  E :  }
 161    :  
 162  E :  TEST_F(HeapTest, SetQueryInformation) {
 163  E :    ULONG compat_flag = -1;
 164  E :    unsigned long ret = 0;
 165    :    // Get the current value of the compat flag.
 166    :    ASSERT_TRUE(
 167    :        proxy_.QueryInformation(HeapCompatibilityInformation,
 168  E :                                &compat_flag, sizeof(compat_flag), &ret));
 169  E :    ASSERT_EQ(sizeof(compat_flag), ret);
 170  E :    ASSERT_TRUE(compat_flag != -1);
 171    :  
 172    :    // Put the heap in LFH, which should always succeed, except when a debugger
 173    :    // is attached. When a debugger is attached, the heap is wedged in certain
 174    :    // debug settings.
 175  E :    if (base::debug::BeingDebugged()) {
 176  i :      LOG(WARNING) << "Can't test HeapProxy::SetInformation under debugger.";
 177  i :      return;
 178    :    }
 179    :  
 180  E :    compat_flag = 2;
 181    :    ASSERT_TRUE(
 182    :        proxy_.SetInformation(HeapCompatibilityInformation,
 183  E :                              &compat_flag, sizeof(compat_flag)));
 184  E :  }
 185    :  
 186    :  }  // namespace asan
 187    :  }  // namespace agent

Coverage information generated Thu Sep 06 11:30:46 2012.