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

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
98.9%1851870.C++test

Line-by-line coverage:

   1    :  // Copyright 2012 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/runtime.h"
  16    :  
  17    :  #include <map>
  18    :  #include <memory>
  19    :  
  20    :  #include "base/bind.h"
  21    :  #include "base/bits.h"
  22    :  #include "base/command_line.h"
  23    :  #include "base/environment.h"
  24    :  #include "base/strings/string_number_conversions.h"
  25    :  #include "base/strings/utf_string_conversions.h"
  26    :  #include "gtest/gtest.h"
  27    :  #include "syzygy/agent/asan/unittest_util.h"
  28    :  
  29    :  namespace agent {
  30    :  namespace asan {
  31    :  
  32    :  namespace {
  33    :  
  34    :  using agent::asan::AsanErrorInfo;
  35    :  
  36    :  // Derived classes to expose protected members for unit-testing.
  37    :  class TestBlockHeapManager : public heap_managers::BlockHeapManager {
  38    :   public:
  39    :    using heap_managers::BlockHeapManager::enable_page_protections_;
  40    :  };
  41    :  
  42    :  class TestAsanRuntime : public AsanRuntime {
  43    :   public:
  44    :    using AsanRuntime::GenerateRandomFeatureSet;
  45    :    using AsanRuntime::PropagateFeatureSet;
  46    :    using AsanRuntime::PropagateParams;
  47    :    using AsanRuntime::heap_manager_;
  48    :  };
  49    :  
  50    :  class AsanRuntimeTest : public testing::TestWithAsanLogger {
  51    :   public:
  52    :    typedef testing::TestWithAsanLogger Super;
  53    :  
  54  E :    AsanRuntimeTest() : current_command_line_(base::CommandLine::NO_PROGRAM) {}
  55    :  
  56  E :    void SetUp() override {
  57  E :      Super::SetUp();
  58    :  
  59  E :      env_.reset(base::Environment::Create());
  60  E :      ASSERT_TRUE(env_.get() != NULL);
  61  E :      env_->UnSetVar(::common::kSyzyAsanOptionsEnvVar);
  62    :  
  63    :      // Setup the "global" state.
  64  E :      common::StackCapture::Init();
  65  E :      StackCaptureCache::Init();
  66  E :    }
  67    :  
  68  E :    void TearDown() override {
  69    :      // Clear the environment so other tests aren't affected.
  70  E :      env_->UnSetVar(::common::kSyzyAsanOptionsEnvVar);
  71    :  
  72  E :      Super::TearDown();
  73  E :    }
  74    :  
  75    :    // The test runtime instance.
  76    :    TestAsanRuntime asan_runtime_;
  77    :  
  78    :    // The value of the command-line that we want to test.
  79    :    base::CommandLine current_command_line_;
  80    :  
  81    :    // The process environment.
  82    :    std::unique_ptr<base::Environment> env_;
  83    :  };
  84    :  
  85    :  bool callback_called = false;
  86    :  AsanErrorInfo callback_error_info = {};
  87    :  
  88    :  // A simple callback that change the value of a boolean to indicate that it has
  89    :  // been called.
  90  E :  void TestCallback(AsanErrorInfo* error_info) {
  91  E :    callback_called = true;
  92  E :    callback_error_info = *error_info;
  93  E :  }
  94    :  
  95    :  }  // namespace
  96    :  
  97  E :  TEST_F(AsanRuntimeTest, SetUpAndTearDown) {
  98  E :    ASSERT_NO_FATAL_FAILURE(
  99  E :        asan_runtime_.SetUp(current_command_line_.GetCommandLineString()));
 100    :    // Make sure the singleton pointer matches the runtime we created.
 101  E :    ASSERT_EQ(reinterpret_cast<AsanRuntime*>(&asan_runtime_),
 102  E :              AsanRuntime::runtime());
 103  E :    ASSERT_NO_FATAL_FAILURE(asan_runtime_.TearDown());
 104  E :  }
 105    :  
 106  E :  TEST_F(AsanRuntimeTest, ThreadIdCache) {
 107  E :    ASSERT_NO_FATAL_FAILURE(
 108  E :        asan_runtime_.SetUp(current_command_line_.GetCommandLineString()));
 109    :  
 110  E :    EXPECT_FALSE(asan_runtime_.ThreadIdIsValid(1234));
 111  E :    EXPECT_FALSE(asan_runtime_.ThreadIdIsValid(5678));
 112  E :    asan_runtime_.AddThreadId(1234);
 113  E :    EXPECT_TRUE(asan_runtime_.ThreadIdIsValid(1234));
 114  E :    EXPECT_FALSE(asan_runtime_.ThreadIdIsValid(5678));
 115  E :    asan_runtime_.AddThreadId(5678);
 116  E :    EXPECT_TRUE(asan_runtime_.ThreadIdIsValid(1234));
 117  E :    EXPECT_TRUE(asan_runtime_.ThreadIdIsValid(5678));
 118    :  
 119  E :    ASSERT_NO_FATAL_FAILURE(asan_runtime_.TearDown());
 120  E :  }
 121    :  
 122  E :  TEST_F(AsanRuntimeTest, OnError) {
 123  E :    ASSERT_NO_FATAL_FAILURE(
 124  E :        asan_runtime_.SetUp(current_command_line_.GetCommandLineString()));
 125    :  
 126    :    // Disable the heap checking as this really slows down the unittests.
 127  E :    asan_runtime_.params().check_heap_on_failure = false;
 128  E :    asan_runtime_.SetErrorCallBack(base::Bind(&TestCallback));
 129  E :    callback_called = false;
 130  E :    AsanErrorInfo bad_access_info = {};
 131  E :    RtlCaptureContext(&bad_access_info.context);
 132  E :    asan_runtime_.OnError(&bad_access_info);
 133  E :    ASSERT_TRUE(callback_called);
 134  E :    ASSERT_NO_FATAL_FAILURE(asan_runtime_.TearDown());
 135  E :    ::common::AsanParameters params = asan_runtime_.params();
 136  E :    EXPECT_EQ(0u, ::memcmp(&params, &(callback_error_info.asan_parameters),
 137  E :                           sizeof(::common::AsanParameters)));
 138  E :  }
 139    :  
 140  E :  TEST_F(AsanRuntimeTest, SetCompressionReportingPeriod) {
 141  E :    ASSERT_EQ(StackCaptureCache::GetDefaultCompressionReportingPeriod(),
 142  E :              StackCaptureCache::compression_reporting_period());
 143    :  
 144    :    size_t new_period =
 145  E :        StackCaptureCache::GetDefaultCompressionReportingPeriod() + 1024;
 146  E :    std::string new_period_str = base::UintToString(new_period);
 147  E :    current_command_line_.AppendSwitchASCII(
 148    :        ::common::kParamReportingPeriod, new_period_str);
 149    :  
 150  E :    ASSERT_NO_FATAL_FAILURE(
 151  E :        asan_runtime_.SetUp(current_command_line_.GetCommandLineString()));
 152    :    // Ensure that the compression reporting period has been modified.
 153  E :    EXPECT_EQ(new_period, StackCaptureCache::compression_reporting_period());
 154  E :    ASSERT_NO_FATAL_FAILURE(asan_runtime_.TearDown());
 155  E :  }
 156    :  
 157  E :  TEST_F(AsanRuntimeTest, SetBottomFramesToSkip) {
 158  E :    size_t frames_to_skip = common::StackCapture::bottom_frames_to_skip() + 1;
 159  E :    std::string new_frames_to_skip_str = base::UintToString(frames_to_skip);
 160  E :    current_command_line_.AppendSwitchASCII(
 161    :        ::common::kParamBottomFramesToSkip, new_frames_to_skip_str);
 162    :  
 163  E :    ASSERT_NO_FATAL_FAILURE(
 164  E :        asan_runtime_.SetUp(current_command_line_.GetCommandLineString()));
 165  E :    EXPECT_EQ(frames_to_skip, common::StackCapture::bottom_frames_to_skip());
 166  E :    ASSERT_NO_FATAL_FAILURE(asan_runtime_.TearDown());
 167  E :  }
 168    :  
 169  E :  TEST_F(AsanRuntimeTest, SetDisableBreakpad) {
 170  E :    current_command_line_.AppendSwitch(::common::kParamDisableBreakpadReporting);
 171    :  
 172  E :    ASSERT_NO_FATAL_FAILURE(
 173  E :        asan_runtime_.SetUp(current_command_line_.GetCommandLineString()));
 174  E :    EXPECT_TRUE(asan_runtime_.params().disable_breakpad_reporting);
 175  E :    ASSERT_NO_FATAL_FAILURE(asan_runtime_.TearDown());
 176  E :  }
 177    :  
 178  E :  TEST_F(AsanRuntimeTest, SetExitOnFailure) {
 179  E :    current_command_line_.AppendSwitch(::common::kParamExitOnFailure);
 180    :  
 181  E :    ASSERT_NO_FATAL_FAILURE(
 182  E :        asan_runtime_.SetUp(current_command_line_.GetCommandLineString()));
 183  E :    EXPECT_TRUE(asan_runtime_.params().exit_on_failure);
 184  E :    ASSERT_NO_FATAL_FAILURE(asan_runtime_.TearDown());
 185  E :  }
 186    :  
 187  E :  TEST_F(AsanRuntimeTest, ExitOnFailure) {
 188    :    // This test always fails under a debugger, due to strangeness in how
 189    :    // gtest death tests work.
 190  E :    if (base::debug::BeingDebugged()) {
 191  i :      LOG(WARNING) << "Skipping this test under debugger.";
 192  i :      return;
 193    :    }
 194    :  
 195  E :    current_command_line_.AppendSwitch(::common::kParamExitOnFailure);
 196    :  
 197  E :    ASSERT_NO_FATAL_FAILURE(
 198  E :        asan_runtime_.SetUp(current_command_line_.GetCommandLineString()));
 199    :  
 200  E :    EXPECT_TRUE(asan_runtime_.params().exit_on_failure);
 201  E :    AsanErrorInfo bad_access_info = {};
 202  E :    RtlCaptureContext(&bad_access_info.context);
 203    :  
 204    :    // We need to delete the files and directory created by this unittest because
 205    :    // the EXPECT_EXIT macro will clone the process and this new process will exit
 206    :    // after the call to OnError, without calling the destructor of this class
 207    :    // (who takes care of deleting the temporary files/directories).
 208  E :    DeleteTempFileAndDirectory();
 209    :  
 210    :    // Disable the heap checking as this really slows down the unittests.
 211  E :    asan_runtime_.params().check_heap_on_failure = false;
 212  E :    EXPECT_EXIT(asan_runtime_.OnError(&bad_access_info),
 213  E :                ::testing::ExitedWithCode(EXIT_FAILURE), "");
 214    :  
 215  E :    ASSERT_NO_FATAL_FAILURE(asan_runtime_.TearDown());
 216  E :  }
 217    :  
 218  E :  TEST_F(AsanRuntimeTest, IgnoredStackIds) {
 219  E :    std::string ignored_stack_ids = "0x1;0X7E577E57;0xCAFEBABE;0xffffffff";
 220  E :    current_command_line_.AppendSwitchASCII(
 221    :        ::common::kParamIgnoredStackIds, ignored_stack_ids);
 222    :  
 223  E :    ASSERT_NO_FATAL_FAILURE(
 224  E :        asan_runtime_.SetUp(current_command_line_.GetCommandLineString()));
 225    :  
 226  E :    EXPECT_THAT(asan_runtime_.params().ignored_stack_ids_set,
 227  E :                testing::ElementsAre(0x1, 0x7E577E57, 0xCAFEBABE, 0xFFFFFFFF));
 228  E :    ASSERT_NO_FATAL_FAILURE(asan_runtime_.TearDown());
 229  E :  }
 230    :  
 231  E :  TEST_F(AsanRuntimeTest, HeapIdIsValid) {
 232  E :    ASSERT_NO_FATAL_FAILURE(
 233  E :        asan_runtime_.SetUp(current_command_line_.GetCommandLineString()));
 234    :  
 235  E :    EXPECT_FALSE(asan_runtime_.HeapIdIsValid(0xDEADBEEF));
 236  E :    EXPECT_TRUE(asan_runtime_.HeapIdIsValid(asan_runtime_.GetProcessHeap()));
 237    :  
 238  E :    ASSERT_NO_FATAL_FAILURE(asan_runtime_.TearDown());
 239  E :  }
 240    :  
 241  E :  TEST_F(AsanRuntimeTest, GetHeapType) {
 242  E :    ASSERT_NO_FATAL_FAILURE(
 243  E :        asan_runtime_.SetUp(current_command_line_.GetCommandLineString()));
 244    :  
 245  E :    HeapManagerInterface::HeapId heap_id = asan_runtime_.GetProcessHeap();
 246  E :    EXPECT_EQ(kWinHeap, asan_runtime_.GetHeapType(heap_id));
 247    :  
 248  E :    ASSERT_NO_FATAL_FAILURE(asan_runtime_.TearDown());
 249  E :  }
 250    :  
 251  E :  TEST_F(AsanRuntimeTest, GenerateRandomFeatureSet) {
 252  E :    const size_t kIterations = 10000;
 253  E :    std::map<size_t, size_t> feature_group_frequency;
 254    :  
 255  E :    for (size_t i = 0; i < kIterations; ++i) {
 256  E :      AsanFeatureSet feature_group = asan_runtime_.GenerateRandomFeatureSet();
 257  E :      ASSERT_LT(feature_group, ASAN_FEATURE_MAX);
 258  E :      if (feature_group_frequency.find(feature_group) !=
 259    :          feature_group_frequency.end()) {
 260  E :        feature_group_frequency[feature_group]++;
 261  E :      } else {
 262  E :        feature_group_frequency[feature_group] = 0;
 263    :      }
 264  E :    }
 265    :  
 266    :    // Count the deprecated features.
 267  E :    size_t number_of_deprecated_features = 0;
 268  E :    for (size_t i = 0; i < sizeof(kAsanDeprecatedFeatures) * 8; ++i) {
 269  E :      if ((kAsanDeprecatedFeatures & (1 << i)) != 0)
 270  E :        number_of_deprecated_features++;
 271  E :    }
 272    :  
 273    :    // This could theoretically fail, but that would imply an extremely bad
 274    :    // implementation of the underlying random number generator. We expect a
 275    :    // standard deviation of 1 / 8 * sqrt(10000 * 7) = 33. A 10% margin is
 276    :    // 1000 / 33 = 30 standard deviations. For |z| > 30, the p-value is < 0.00001
 277    :    // and can be considered as insignificant.
 278    :    const size_t kExpectedCount =
 279  E :        kIterations / (ASAN_FEATURE_MAX >> number_of_deprecated_features);
 280  E :    const size_t kErrorMargin = kExpectedCount / 10;
 281  E :    for (const auto& iter : feature_group_frequency) {
 282  E :      EXPECT_LT(kExpectedCount - kErrorMargin, iter.second);
 283  E :      EXPECT_GT(kExpectedCount + kErrorMargin, iter.second);
 284  E :    }
 285  E :  }
 286    :  
 287  E :  TEST_F(AsanRuntimeTest, PropagateFeatureSet) {
 288  E :    ASSERT_NO_FATAL_FAILURE(
 289  E :        asan_runtime_.SetUp(current_command_line_.GetCommandLineString()));
 290    :  
 291  E :    for (uint32_t feature_set = 0; feature_set < ASAN_FEATURE_MAX;
 292  E :         ++feature_set) {
 293    :      // Skip feature sets that enable deprecated features.
 294  E :      if (feature_set & kAsanDeprecatedFeatures)
 295  E :        continue;
 296    :  
 297  E :      asan_runtime_.PropagateFeatureSet(feature_set);
 298  E :      ::common::AsanParameters expected_params = {};
 299  E :      ::common::SetDefaultAsanParameters(&expected_params);
 300  E :      expected_params.enable_large_block_heap =
 301    :          ((feature_set & ASAN_FEATURE_ENABLE_LARGE_BLOCK_HEAP) != 0U);
 302  E :      EXPECT_EQ(0U, ::memcmp(&expected_params, &asan_runtime_.params(),
 303  E :                             sizeof(::common::AsanParameters)));
 304    :      TestBlockHeapManager* test_block_heap_manager =
 305  E :          static_cast<TestBlockHeapManager*>(asan_runtime_.heap_manager_.get());
 306  E :      EXPECT_EQ(test_block_heap_manager->enable_page_protections_,
 307  E :                ((feature_set & ASAN_FEATURE_ENABLE_PAGE_PROTECTIONS) != 0U));
 308    :  
 309    :      // Expect the Crashpad bit to always be cleared, as the crash reporter
 310    :      // can't be initialized without a Crashpad server running.
 311  E :      EXPECT_EQ(0u,
 312  E :          asan_runtime_.GetEnabledFeatureSet() & ASAN_FEATURE_ENABLE_CRASHPAD);
 313  E :    }
 314    :  
 315  E :    ASSERT_NO_FATAL_FAILURE(asan_runtime_.TearDown());
 316  E :  }
 317    :  
 318  E :  TEST_F(AsanRuntimeTest, OnErrorSaveEnabledFeatureList) {
 319  E :    asan_runtime_.params().feature_randomization = true;
 320  E :    ASSERT_NO_FATAL_FAILURE(
 321  E :        asan_runtime_.SetUp(current_command_line_.GetCommandLineString()));
 322    :  
 323    :    // Disable the heap checking as this really slows down the unittests.
 324  E :    asan_runtime_.params().check_heap_on_failure = false;
 325  E :    asan_runtime_.SetErrorCallBack(base::Bind(&TestCallback));
 326  E :    callback_called = false;
 327  E :    callback_error_info.feature_set = ASAN_FEATURE_MAX;
 328  E :    AsanErrorInfo bad_access_info = {};
 329  E :    RtlCaptureContext(&bad_access_info.context);
 330    :    AsanFeatureSet expected_feature_set = static_cast<AsanFeatureSet>(
 331  E :        ASAN_FEATURE_ENABLE_LARGE_BLOCK_HEAP);
 332  E :    asan_runtime_.PropagateFeatureSet(expected_feature_set);
 333  E :    asan_runtime_.OnError(&bad_access_info);
 334  E :    EXPECT_TRUE(callback_called);
 335  E :    EXPECT_EQ(expected_feature_set, callback_error_info.feature_set);
 336  E :    ASSERT_NO_FATAL_FAILURE(asan_runtime_.TearDown());
 337  E :  }
 338    :  
 339    :  }  // namespace asan
 340    :  }  // namespace agent

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