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

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
100.0%38380.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  E :    GetCorruptRangesInSlab(
  43    :        reinterpret_cast<const uint8_t*>(Shadow::kAddressLowerBound),
  44    :        shadow_->memory_size() - Shadow::kAddressLowerBound - 1, corrupt_ranges);
  45    :  
  46  E :    return !corrupt_ranges->empty();
  47  E :  }
  48    :  
  49    :  void HeapChecker::GetCorruptRangesInSlab(const uint8_t* lower_bound,
  50    :                                           size_t length,
  51  E :                                           CorruptRangesVector* corrupt_ranges) {
  52  E :    DCHECK_NE(static_cast<const uint8_t*>(nullptr), lower_bound);
  53  E :    DCHECK_NE(0U, length);
  54  E :    DCHECK_NE(static_cast<CorruptRangesVector*>(nullptr), corrupt_ranges);
  55    :  
  56  E :    ShadowWalker shadow_walker(
  57    :        shadow_, false, lower_bound, lower_bound + length);
  58    :  
  59  E :    AsanCorruptBlockRange* current_corrupt_range = nullptr;
  60    :  
  61    :    // Iterates over the blocks.
  62  E :    BlockInfo block_info = {};
  63  E :    while (shadow_walker.Next(&block_info)) {
  64    :      // Remove the protections on this block so its checksum can be safely
  65    :      // validated. We leave the protections permanently removed so that the
  66    :      // minidump generation has free access to block contents.
  67  E :      BlockProtectNone(block_info, shadow_);
  68    :  
  69  E :      bool current_block_is_corrupt = IsBlockCorrupt(block_info);
  70    :      // If the current block is corrupt and |current_corrupt_range| is nullptr
  71    :      // then this means that the current block is at the beginning of a corrupt
  72    :      // range.
  73  E :      if (current_block_is_corrupt && current_corrupt_range == nullptr) {
  74    :        AsanCorruptBlockRange corrupt_range;
  75  E :        corrupt_range.address = block_info.header;
  76  E :        corrupt_range.length = 0;
  77  E :        corrupt_range.block_count = 0;
  78  E :        corrupt_range.block_info = nullptr;
  79  E :        corrupt_range.block_info_count = 0;
  80  E :        corrupt_ranges->push_back(corrupt_range);
  81  E :        current_corrupt_range = &corrupt_ranges->back();
  82  E :      } else if (!current_block_is_corrupt && current_corrupt_range != nullptr) {
  83  E :        current_corrupt_range = nullptr;
  84    :      }
  85    :  
  86  E :      if (current_block_is_corrupt) {
  87    :        // If the current block is corrupt then we need to update the size of the
  88    :        // current range.
  89  E :        DCHECK_NE(reinterpret_cast<AsanCorruptBlockRange*>(nullptr),
  90  E :                  current_corrupt_range);
  91  E :        current_corrupt_range->block_count++;
  92    :        const uint8_t* current_block_end =
  93  E :            block_info.RawHeader() + block_info.block_size;
  94  E :        current_corrupt_range->length =
  95    :            current_block_end -
  96    :            reinterpret_cast<const uint8_t*>(current_corrupt_range->address);
  97    :      }
  98  E :    }
  99  E :  }
 100    :  
 101    :  }  // namespace asan
 102    :  }  // namespace agent

Coverage information generated Fri Jul 29 11:00:21 2016.