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

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
100.0%37370.C++source

Line-by-line coverage:

   1    :  // Copyright 2014 Google Inc. All Rights Reserved.
   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    :  
  15    :  #include "syzygy/agent/asan/heap_checker.h"
  16    :  
  17    :  #include "syzygy/agent/asan/page_protection_helpers.h"
  18    :  #include "syzygy/agent/asan/runtime.h"
  19    :  #include "syzygy/agent/asan/shadow.h"
  20    :  
  21    :  namespace agent {
  22    :  namespace asan {
  23    :  
  24    :  HeapChecker::HeapChecker(Shadow* shadow)
  25  E :      : shadow_(shadow) {
  26  E :    DCHECK_NE(static_cast<Shadow*>(nullptr), shadow);
  27  E :  }
  28    :  
  29  E :  bool HeapChecker::IsHeapCorrupt(CorruptRangesVector* corrupt_ranges) {
  30  E :    DCHECK_NE(static_cast<CorruptRangesVector*>(nullptr), corrupt_ranges);
  31    :  
  32  E :    corrupt_ranges->clear();
  33    :  
  34    :    // Grab the page protection lock. This prevents multiple heap checkers from
  35    :    // running simultaneously, and also prevents page protections from being
  36    :    // modified from underneath us.
  37  E :    ::common::AutoRecursiveLock scoped_lock(block_protect_lock);
  38    :  
  39    :    // Walk over all of the addressable memory to find the corrupt blocks.
  40    :    // TODO(sebmarchand): Iterates over the heap slabs once we have switched to
  41    :    //     a new memory allocator.
  42    :    GetCorruptRangesInSlab(
  43    :        reinterpret_cast<const uint8*>(Shadow::kAddressLowerBound),
  44    :        shadow_->memory_size() - Shadow::kAddressLowerBound - 1,
  45  E :        corrupt_ranges);
  46    :  
  47  E :    return !corrupt_ranges->empty();
  48  E :  }
  49    :  
  50    :  void HeapChecker::GetCorruptRangesInSlab(const uint8* lower_bound,
  51    :                                           size_t length,
  52  E :                                           CorruptRangesVector* corrupt_ranges) {
  53  E :    DCHECK_NE(static_cast<const uint8*>(nullptr), lower_bound);
  54  E :    DCHECK_NE(0U, length);
  55  E :    DCHECK_NE(static_cast<CorruptRangesVector*>(nullptr), corrupt_ranges);
  56    :  
  57    :    ShadowWalker shadow_walker(
  58  E :        shadow_, false, lower_bound, lower_bound + length);
  59    :  
  60  E :    AsanCorruptBlockRange* current_corrupt_range = nullptr;
  61    :  
  62    :    // Iterates over the blocks.
  63  E :    BlockInfo block_info = {};
  64  E :    while (shadow_walker.Next(&block_info)) {
  65    :      // Remove the protections on this block so its checksum can be safely
  66    :      // validated. We leave the protections permanently removed so that the
  67    :      // minidump generation has free access to block contents.
  68  E :      BlockProtectNone(block_info, shadow_);
  69    :  
  70  E :      bool current_block_is_corrupt = IsBlockCorrupt(block_info);
  71    :      // If the current block is corrupt and |current_corrupt_range| is nullptr
  72    :      // then this means that the current block is at the beginning of a corrupt
  73    :      // range.
  74  E :      if (current_block_is_corrupt && current_corrupt_range == nullptr) {
  75    :        AsanCorruptBlockRange corrupt_range;
  76  E :        corrupt_range.address = block_info.header;
  77  E :        corrupt_range.length = 0;
  78  E :        corrupt_range.block_count = 0;
  79  E :        corrupt_range.block_info = nullptr;
  80  E :        corrupt_range.block_info_count = 0;
  81  E :        corrupt_ranges->push_back(corrupt_range);
  82  E :        current_corrupt_range = &corrupt_ranges->back();
  83  E :      } else if (!current_block_is_corrupt && current_corrupt_range != nullptr) {
  84  E :        current_corrupt_range = nullptr;
  85    :      }
  86    :  
  87  E :      if (current_block_is_corrupt) {
  88    :        // If the current block is corrupt then we need to update the size of the
  89    :        // current range.
  90    :        DCHECK_NE(reinterpret_cast<AsanCorruptBlockRange*>(nullptr),
  91  E :                  current_corrupt_range);
  92  E :        current_corrupt_range->block_count++;
  93    :        const uint8* current_block_end = block_info.RawHeader() +
  94  E :            block_info.block_size;
  95    :        current_corrupt_range->length = current_block_end -
  96  E :            reinterpret_cast<const uint8*>(current_corrupt_range->address);
  97    :      }
  98  E :    }
  99  E :  }
 100    :  
 101    :  }  // namespace asan
 102    :  }  // namespace agent

Coverage information generated Thu Jan 14 17:40:38 2016.