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

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
86.9%1191370.C++source

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/logging.h"
  17    :  #include "syzygy/agent/asan/asan_shadow.h"
  18    :  
  19    :  namespace agent {
  20    :  namespace asan {
  21    :  
  22    :  namespace {
  23    :  
  24    :  // Redzone size allocated at the start of every heap block.
  25    :  const size_t kRedZoneSize = 32;
  26    :  
  27    :  }  // namespace
  28    :  
  29    :  HeapProxy::HeapProxy()
  30    :      : heap_(NULL),
  31    :        head_(NULL),
  32    :        tail_(NULL),
  33  E :        quarantine_size_(0) {
  34  E :  }
  35    :  
  36  E :  HeapProxy::~HeapProxy() {
  37  E :    if (heap_ != NULL)
  38  i :      Destroy();
  39    :  
  40  E :    DCHECK(heap_ == NULL);
  41  E :  }
  42    :  
  43  E :  HANDLE HeapProxy::ToHandle(HeapProxy* proxy) {
  44  E :    return proxy;
  45  E :  }
  46    :  
  47  E :  HeapProxy* HeapProxy::FromHandle(HANDLE heap) {
  48  E :    return reinterpret_cast<HeapProxy*>(heap);
  49  E :  }
  50    :  
  51    :  bool HeapProxy::Create(DWORD options,
  52    :                         size_t initial_size,
  53  E :                         size_t maximum_size) {
  54  E :    DCHECK(heap_ == NULL);
  55    :  
  56  E :    heap_ = ::HeapCreate(options, initial_size, maximum_size);
  57  E :    if (heap_ != NULL)
  58  E :      return true;
  59    :  
  60  i :    return false;
  61  E :  }
  62    :  
  63  E :  bool HeapProxy::Destroy(){
  64  E :    DCHECK(heap_ != NULL);
  65  E :    if (::HeapDestroy(heap_)) {
  66  E :      heap_ = NULL;
  67  E :      return true;
  68    :    }
  69    :  
  70  i :    return false;
  71  E :  }
  72    :  
  73  E :  void* HeapProxy::Alloc(DWORD flags, size_t bytes){
  74  E :    DCHECK(heap_ != NULL);
  75    :  
  76  E :    size_t alloc_size = GetAllocSize(bytes);
  77    :    BlockHeader* block =
  78  E :        reinterpret_cast<BlockHeader*>(::HeapAlloc(heap_, flags, alloc_size));
  79    :  
  80  E :    if (block == NULL)
  81  i :      return NULL;
  82    :  
  83    :    // Poison head and tail zones, and unpoison alloc.
  84  E :    size_t header_size = kRedZoneSize;
  85  E :    size_t trailer_size = alloc_size - kRedZoneSize - bytes;
  86  E :    memset(block, '0xCC', header_size);
  87  E :    Shadow::Poison(block, kRedZoneSize);
  88    :  
  89  E :    Shadow::Unpoison(ToAlloc(block), bytes);
  90    :  
  91  E :    memset(ToAlloc(block) + bytes, '0xCD', trailer_size);
  92  E :    Shadow::Poison(ToAlloc(block) + bytes, trailer_size);
  93    :  
  94  E :    block->size = bytes;
  95    :  
  96  E :    return ToAlloc(block);
  97  E :  }
  98    :  
  99  E :  void* HeapProxy::ReAlloc(DWORD flags, void* mem, size_t bytes){
 100  E :    DCHECK(heap_ != NULL);
 101    :  
 102  E :    void *new_mem = Alloc(flags, bytes);
 103  E :    if (new_mem != NULL && mem != NULL)
 104  E :      memcpy(new_mem, mem, std::min(bytes, Size(0, mem)));
 105    :  
 106  E :    if (mem)
 107  E :      Free(flags, mem);
 108    :  
 109  E :    return new_mem;
 110  E :  }
 111    :  
 112  E :  bool HeapProxy::Free(DWORD flags, void* mem){
 113  E :    DCHECK(heap_ != NULL);
 114  E :    BlockHeader* block = ToBlock(mem);
 115  E :    if (block == NULL)
 116  i :      return true;
 117    :  
 118  E :    QuarantineBlock(block);
 119    :  
 120  E :    return true;
 121  E :  }
 122    :  
 123  E :  size_t HeapProxy::Size(DWORD flags, const void* mem){
 124  E :    DCHECK(heap_ != NULL);
 125  E :    BlockHeader* block = ToBlock(mem);
 126  E :    if (block == NULL)
 127  i :      return -1;
 128    :  
 129  E :    return block->size;
 130  E :  }
 131    :  
 132  E :  bool HeapProxy::Validate(DWORD flags, const void* mem){
 133  E :    DCHECK(heap_ != NULL);
 134  E :    return ::HeapValidate(heap_, flags, ToBlock(mem)) == TRUE;
 135  E :  }
 136    :  
 137  E :  size_t HeapProxy::Compact(DWORD flags){
 138  E :    DCHECK(heap_ != NULL);
 139  E :    return ::HeapCompact(heap_, flags);
 140  E :  }
 141    :  
 142  E :  bool HeapProxy::Lock(){
 143  E :    DCHECK(heap_ != NULL);
 144  E :    return ::HeapLock(heap_) == TRUE;
 145  E :  }
 146    :  
 147  E :  bool HeapProxy::Unlock(){
 148  E :    DCHECK(heap_ != NULL);
 149  E :    return ::HeapUnlock(heap_) == TRUE;
 150  E :  }
 151    :  
 152  E :  bool HeapProxy::Walk(PROCESS_HEAP_ENTRY* entry){
 153  E :    DCHECK(heap_ != NULL);
 154  E :    return ::HeapWalk(heap_, entry) == TRUE;
 155  E :  }
 156    :  
 157    :  bool HeapProxy::SetInformation(HEAP_INFORMATION_CLASS info_class,
 158    :                                 void* info,
 159  E :                                 size_t info_length){
 160  E :    DCHECK(heap_ != NULL);
 161  E :    return ::HeapSetInformation(heap_, info_class, info, info_length) == TRUE;
 162  E :  }
 163    :  
 164    :  bool HeapProxy::QueryInformation(HEAP_INFORMATION_CLASS info_class,
 165    :                                   void* info,
 166    :                                   size_t info_length,
 167  E :                                   unsigned long* return_length){
 168  E :    DCHECK(heap_ != NULL);
 169    :    return ::HeapQueryInformation(heap_,
 170    :                                  info_class,
 171    :                                  info,
 172    :                                  info_length,
 173  E :                                  return_length) == TRUE;
 174  E :  }
 175    :  
 176  E :  void HeapProxy::QuarantineBlock(BlockHeader* block) {
 177  E :    base::AutoLock lock(lock_);
 178  E :    FreeBlockHeader* free_block = static_cast<FreeBlockHeader*>(block);
 179    :  
 180  E :    free_block->next = NULL;
 181  E :    if (tail_ != NULL) {
 182  E :      tail_->next = free_block;
 183  E :    } else {
 184  E :      DCHECK(head_ == NULL);
 185  E :      head_ = free_block;
 186    :    }
 187  E :    tail_ = free_block;
 188    :  
 189    :    // Poison the released alloc.
 190  E :    size_t alloc_size = GetAllocSize(free_block->size);
 191    :    // Trash the data in the block and poison it.
 192  E :    memset(ToAlloc(free_block), 0xCC, free_block->size);
 193  E :    Shadow::Poison(free_block, alloc_size);
 194  E :    quarantine_size_ += alloc_size;
 195    :  
 196    :    // Arbitrarily keep ten megabytes of quarantine per heap.
 197  E :    const size_t kMaxQuarantineSizeBytes = 10 * 1024 * 1024;
 198    :  
 199    :    // Flush quarantine overage.
 200  E :    while (quarantine_size_ > kMaxQuarantineSizeBytes) {
 201  i :      DCHECK(head_ != NULL && tail_ != NULL);
 202    :  
 203  i :      free_block = head_;
 204  i :      head_ = free_block->next;
 205  i :      if (head_ == NULL)
 206  i :        tail_ = NULL;
 207    :  
 208  i :      alloc_size = GetAllocSize(free_block->size);
 209  i :      Shadow::Unpoison(free_block, alloc_size);
 210  i :      ::HeapFree(heap_, 0, free_block);
 211    :  
 212  i :      DCHECK_GE(quarantine_size_, alloc_size);
 213  i :      quarantine_size_ -= alloc_size;
 214  i :    }
 215  E :  }
 216    :  
 217  E :  size_t HeapProxy::GetAllocSize(size_t bytes) {
 218  E :    bytes += kRedZoneSize;
 219  E :    return (bytes + kRedZoneSize + kRedZoneSize - 1) & ~(kRedZoneSize - 1);
 220  E :  }
 221    :  
 222  E :  HeapProxy::BlockHeader* HeapProxy::ToBlock(const void* alloc) {
 223  E :    if (alloc == NULL)
 224  i :      return NULL;
 225    :  
 226  E :    uint8* mem = reinterpret_cast<uint8*>(const_cast<void*>(alloc));
 227    :  
 228  E :    return reinterpret_cast<BlockHeader*>(mem - kRedZoneSize);
 229  E :  }
 230    :  
 231  E :  uint8* HeapProxy::ToAlloc(BlockHeader* block) {
 232  E :    uint8* mem = reinterpret_cast<uint8*>(block);
 233    :  
 234  E :    return mem + kRedZoneSize;
 235  E :  }
 236    :  
 237    :  }  // namespace asan
 238    :  }  // namespace agent

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