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

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
85.0%4325080.C++test

Line-by-line coverage:

   1    :  // Copyright 2013 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    :  // Common unittest fixtures and utilities for the Asan runtime library.
  16    :  
  17    :  #include "syzygy/agent/asan/unittest_util.h"
  18    :  
  19    :  #include <algorithm>
  20    :  
  21    :  #include "base/bind.h"
  22    :  #include "base/command_line.h"
  23    :  #include "base/environment.h"
  24    :  #include "base/debug/alias.h"
  25    :  #include "base/process/kill.h"
  26    :  #include "base/process/launch.h"
  27    :  #include "base/strings/string_number_conversions.h"
  28    :  #include "base/strings/stringprintf.h"
  29    :  #include "base/strings/utf_string_conversions.h"
  30    :  #include "syzygy/agent/asan/block.h"
  31    :  #include "syzygy/agent/asan/error_info.h"
  32    :  #include "syzygy/agent/asan/rtl_impl.h"
  33    :  #include "syzygy/agent/asan/runtime.h"
  34    :  #include "syzygy/agent/common/stack_capture.h"
  35    :  #include "syzygy/trace/protocol/call_trace_defs.h"
  36    :  
  37    :  namespace testing {
  38    :  
  39    :  namespace {
  40    :  
  41    :  typedef agent::asan::HeapManagerInterface::HeapId HeapId;
  42    :  
  43    :  using agent::asan::BlockHeader;
  44    :  using agent::asan::BlockInfo;
  45    :  using agent::asan::BlockLayout;
  46    :  using agent::common::StackCapture;
  47    :  
  48    :  }  // namespace
  49    :  
  50    :  const wchar_t kSyzyAsanRtlDll[] = L"syzyasan_rtl.dll";
  51    :  // The maximum time we're willing to wait for the logger process to get
  52    :  // started/killed. This is very generous, but also prevents the unittests
  53    :  // from hanging if the event never fires.
  54    :  static const size_t kLoggerTimeOutMs = 10000;
  55    :  
  56    :  namespace {
  57    :  
  58    :  FARPROC check_access_fn = NULL;
  59    :  bool direction_flag_forward = true;
  60    :  
  61    :  // An exception filter that grabs and sets an exception pointer, and
  62    :  // triggers only for access violations.
  63  E :  DWORD AccessViolationFilter(EXCEPTION_POINTERS* e, EXCEPTION_POINTERS** pe) {
  64  E :    if (e->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) {
  65  E :      *pe = e;
  66  E :      return EXCEPTION_EXECUTE_HANDLER;
  67    :    }
  68  i :    return EXCEPTION_CONTINUE_SEARCH;
  69  E :  }
  70    :  
  71    :  // Tries to access the given address, validating whether or not an
  72    :  // access violation occurs.
  73  i :  bool TestReadAccess(void* address, bool expect_access_violation) {
  74  i :    uint8_t* m = reinterpret_cast<uint8_t*>(address);
  75  i :    ULONG_PTR p = reinterpret_cast<ULONG_PTR>(address);
  76    :  
  77    :    // Try a read.
  78  i :    uint8_t value = 0;
  79  i :    EXCEPTION_POINTERS* e = NULL;
  80  i :    __try {
  81  i :      value = m[0];
  82  i :      if (expect_access_violation)
  83  i :        return false;
  84  i :    }
  85  i :    __except(AccessViolationFilter(GetExceptionInformation(), &e)) {
  86  i :      if (!expect_access_violation)
  87  i :        return false;
  88    :      if (e->ExceptionRecord == NULL ||
  89  i :        e->ExceptionRecord->NumberParameters < 2 ||
  90    :        e->ExceptionRecord->ExceptionInformation[1] != p) {
  91  i :        return false;
  92    :      }
  93  i :      return true;
  94    :    }
  95    :  
  96    :    // Ensure that |value| doesn't get optimized away. If so, the attempted
  97    :    // read never occurs.
  98  i :    base::debug::Alias(&value);
  99    :  
 100  i :    return true;
 101  i :  }
 102    :  
 103    :  // Tries to write at the given address, validating whether or not an
 104    :  // access violation occurs.
 105  i :  bool TestWriteAccess(void* address, bool expect_access_violation) {
 106  i :    uint8_t* m = reinterpret_cast<uint8_t*>(address);
 107  i :    ULONG_PTR p = reinterpret_cast<ULONG_PTR>(address);
 108    :  
 109    :    // Try a write.
 110  i :    EXCEPTION_POINTERS* e = NULL;
 111  i :    __try {
 112  i :      m[0] = 0;
 113  i :      if (expect_access_violation)
 114  i :        return false;
 115  i :    }
 116  i :    __except(AccessViolationFilter(GetExceptionInformation(), &e)) {
 117  i :      if (!expect_access_violation)
 118  i :        return false;
 119    :      if (e->ExceptionRecord == NULL ||
 120  i :        e->ExceptionRecord->NumberParameters < 2 ||
 121    :        e->ExceptionRecord->ExceptionInformation[1] != p) {
 122  i :        return false;
 123    :      }
 124    :    }
 125    :  
 126  i :    return true;
 127  i :  }
 128    :  
 129    :  // Tries to access (read/write) at the given address, validating whether or
 130    :  // not an access violation occurs.
 131  E :  bool TestAccess(void* address, bool expect_access_violation) {
 132  E :    return TestReadAccess(address, expect_access_violation) &&
 133    :      TestWriteAccess(address, expect_access_violation);
 134  E :  }
 135    :  
 136    :  }  // namespace
 137    :  
 138    :  MemoryAccessorTester* MemoryAccessorTester::instance_ = NULL;
 139    :  
 140    :  // Define the function pointers.
 141    :  #define DEFINE_FUNCTION_PTR_VARIABLE(convention, ret, name, args, argnames)  \
 142    :      name##FunctionPtr TestAsanRtl::name##Function;
 143    :  ASAN_RTL_FUNCTIONS(DEFINE_FUNCTION_PTR_VARIABLE)
 144    :  #undef DEFINE_FUNCTION_PTR_VARIABLE
 145    :  
 146    :  // Define versions of all of the functions that expect an error to be thrown by
 147    :  // the AsanErrorCallback, and in turn raise an exception if the underlying
 148    :  // function didn't fail.
 149    :  #define DEFINE_FAILING_FUNCTION(convention, ret, name, args, argnames)  \
 150    :    bool name##FunctionFailed args {  \
 151    :      __try {  \
 152    :        testing::TestAsanRtl::name##Function argnames;  \
 153    :      } __except(::GetExceptionCode() == EXCEPTION_ARRAY_BOUNDS_EXCEEDED) {  \
 154    :        return true;  \
 155    :      }  \
 156    :      return false;  \
 157    :    }  \
 158    :    void testing::TestAsanRtl::name##FunctionFailing args {  \
 159    :      ASSERT_TRUE(name##FunctionFailed argnames);  \
 160    :    }
 161  E :  ASAN_RTL_FUNCTIONS(DEFINE_FAILING_FUNCTION)
 162    :  #undef DEFINE_FAILING_FUNCTION
 163    :  
 164    :  TestWithAsanLogger::TestWithAsanLogger()
 165  E :      : logger_running_(false), log_contents_read_(false) {
 166  E :  }
 167    :  
 168  E :  void TestWithAsanLogger::SetUp() {
 169    :    // Create the log file.
 170  E :    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
 171  E :    CHECK(base::CreateTemporaryFileInDir(temp_dir_.path(), &log_file_path_));
 172    :  
 173    :    // Open files used to redirect standard in/out/err of the logger, to not
 174    :    // pollute the console.
 175  E :    logger_stdin_file_.reset(base::OpenFile(
 176    :        temp_dir_.path().AppendASCII("agent_logger_stdin.txt"), "w"));
 177  E :    CHECK(logger_stdin_file_);
 178  E :    logger_stdout_file_.reset(base::OpenFile(
 179    :        temp_dir_.path().AppendASCII("agent_logger_stdout.txt"), "w"));
 180  E :    CHECK(logger_stdout_file_);
 181  E :    logger_stderr_file_.reset(base::OpenFile(
 182    :        temp_dir_.path().AppendASCII("agent_logger_stderr.txt"), "w"));
 183  E :    CHECK(logger_stderr_file_);
 184    :  
 185    :    // Save the environment we found.
 186  E :    std::unique_ptr<base::Environment> env(base::Environment::Create());
 187  E :    env->GetVar(kSyzygyRpcInstanceIdEnvVar, &old_logger_env_);
 188    :  
 189    :    // Configure the environment (to pass the instance id to the agent DLL).
 190    :    // We append "-0" to the process id to avoid potential conflict with other
 191    :    // tests.
 192  E :    instance_id_ = base::UintToString16(::GetCurrentProcessId()) + L"-0";
 193  E :    AppendToLoggerEnv(base::StringPrintf("%ls,%ls",
 194    :                                         kSyzyAsanRtlDll,
 195    :                                         instance_id_.c_str()));
 196    :  
 197  E :    log_contents_read_ = false;
 198  E :    StartLogger();
 199  E :  }
 200    :  
 201  E :  void TestWithAsanLogger::TearDown() {
 202  E :    StopLogger();
 203    :  
 204    :    // Restore the environment variable as we found it.
 205  E :    std::unique_ptr<base::Environment> env(base::Environment::Create());
 206  E :    env->SetVar(kSyzygyRpcInstanceIdEnvVar, old_logger_env_);
 207  E :  }
 208    :  
 209  E :  bool TestWithAsanLogger::LogContains(const base::StringPiece& message) {
 210  E :    if (!log_contents_read_ && logger_running_) {
 211  E :      CHECK(base::ReadFileToString(log_file_path_, &log_contents_));
 212  E :      log_contents_read_ = true;
 213    :    }
 214  E :    return log_contents_.find(message.as_string()) != std::string::npos;
 215  E :  }
 216    :  
 217  E :  void TestWithAsanLogger::DeleteTempFileAndDirectory() {
 218  E :    StopLogger();
 219  E :    logger_stdin_file_.reset();
 220  E :    logger_stdout_file_.reset();
 221  E :    logger_stderr_file_.reset();
 222  E :    if (temp_dir_.IsValid())
 223  E :      temp_dir_.Delete();
 224  E :  }
 225    :  
 226  E :  void TestWithAsanLogger::StartLogger() {
 227    :    // Launch the logger as a separate process and make sure it succeeds.
 228  E :    base::CommandLine cmd_line(testing::GetExeRelativePath(L"agent_logger.exe"));
 229  E :    cmd_line.AppendSwitchNative("instance-id", instance_id_);
 230  E :    cmd_line.AppendSwitchNative("output-file", log_file_path_.value());
 231  E :    cmd_line.AppendSwitchNative("minidump-dir", temp_dir_.path().value());
 232  E :    cmd_line.AppendArgNative(L"start");
 233  E :    base::LaunchOptions options;
 234  E :    options.start_hidden = true;
 235  E :    options.stdin_handle = reinterpret_cast<HANDLE>(
 236    :        _get_osfhandle(_fileno(logger_stdin_file_.get())));
 237  E :    options.stdout_handle = reinterpret_cast<HANDLE>(
 238    :        _get_osfhandle(_fileno(logger_stdout_file_.get())));
 239  E :    options.stderr_handle = reinterpret_cast<HANDLE>(
 240    :        _get_osfhandle(_fileno(logger_stderr_file_.get())));
 241  E :    options.inherit_handles = true;  // As per documentation.
 242  E :    base::Process process = base::LaunchProcess(cmd_line, options);
 243  E :    ASSERT_TRUE(process.IsValid());
 244    :  
 245    :    // Wait for the logger to be ready before continuing.
 246  E :    std::wstring event_name;
 247  E :    trace::agent_logger::AgentLogger::GetSyzygyAgentLoggerEventName(
 248    :        instance_id_, &event_name);
 249  E :    base::win::ScopedHandle event(
 250    :        ::CreateEvent(NULL, FALSE, FALSE, event_name.c_str()));
 251  E :    ::WaitForSingleObject(event.Get(), kLoggerTimeOutMs);
 252  E :    logger_running_ = true;
 253  E :  }
 254    :  
 255  E :  void TestWithAsanLogger::StopLogger() {
 256  E :    if (!logger_running_)
 257  E :      return;
 258    :    // Launch the logger as a separate process to stop it and make sure it
 259    :    // succeeds.
 260  E :    base::CommandLine cmd_line(base::FilePath(L"agent_logger.exe"));
 261  E :    cmd_line.AppendSwitchNative("instance-id", instance_id_);
 262  E :    cmd_line.AppendArgNative(L"stop");
 263  E :    base::LaunchOptions options;
 264  E :    options.start_hidden = true;
 265  E :    base::Process process = base::LaunchProcess(cmd_line, options);
 266  E :    ASSERT_TRUE(process.IsValid());
 267    :  
 268  E :    int exit_code = 0;
 269  E :    ASSERT_TRUE(process.WaitForExitWithTimeout(
 270  E :        base::TimeDelta::FromMilliseconds(kLoggerTimeOutMs), &exit_code));
 271  E :    logger_running_ = false;
 272  E :  }
 273    :  
 274  E :  void TestWithAsanLogger::ResetLog() {
 275  E :    StopLogger();
 276  E :    CHECK(base::CreateTemporaryFileInDir(temp_dir_.path(), &log_file_path_));
 277  E :    StartLogger();
 278  E :    log_contents_read_ = false;
 279  E :  }
 280    :  
 281  E :  void TestWithAsanLogger::AppendToLoggerEnv(const std::string &instance) {
 282  E :    std::string instance_id;
 283  E :    std::unique_ptr<base::Environment> env(base::Environment::Create());
 284  E :    env->GetVar(kSyzygyRpcInstanceIdEnvVar, &instance_id);
 285    :  
 286  E :    instance_id.append(";");
 287  E :    instance_id.append(instance);
 288    :  
 289  E :    env->SetVar(kSyzygyRpcInstanceIdEnvVar, instance_id);
 290  E :  }
 291    :  
 292    :  FakeAsanBlock::FakeAsanBlock(Shadow* shadow,
 293    :                               size_t alloc_alignment_log,
 294    :                               StackCaptureCache* stack_cache)
 295  E :      : is_initialized(false), alloc_alignment_log(alloc_alignment_log),
 296  E :        alloc_alignment(1 << alloc_alignment_log), shadow_(shadow),
 297  E :        stack_cache(stack_cache) {
 298  E :    DCHECK_NE(static_cast<Shadow*>(nullptr), shadow);
 299  E :    DCHECK_NE(static_cast<StackCaptureCache*>(nullptr), stack_cache);
 300    :    // Align the beginning of the buffer to the current granularity. Ensure that
 301    :    // there's room to store magic bytes in front of this block.
 302  E :    buffer_align_begin = reinterpret_cast<uint8_t*>(
 303    :        common::AlignUp(reinterpret_cast<size_t>(buffer) + 1, alloc_alignment));
 304  E :    ::memset(&block_info, 0, sizeof(block_info));
 305  E :  }
 306    :  
 307  E :  FakeAsanBlock::~FakeAsanBlock() {
 308  E :    EXPECT_NE(0U, block_info.block_size);
 309  E :    shadow_->Unpoison(buffer_align_begin, block_info.block_size);
 310  E :    ::memset(buffer, 0, sizeof(buffer));
 311  E :  }
 312    :  
 313  E :  bool FakeAsanBlock::InitializeBlock(size_t alloc_size) {
 314  E :    BlockLayout layout = {};
 315  E :    EXPECT_TRUE(BlockPlanLayout(alloc_alignment,
 316    :                                alloc_alignment,
 317    :                                alloc_size,
 318    :                                0,
 319    :                                0,
 320  E :                                &layout));
 321    :  
 322    :    // Initialize the Asan block.
 323  E :    BlockInitialize(layout, buffer_align_begin, false, &block_info);
 324  E :    EXPECT_NE(reinterpret_cast<void*>(NULL), block_info.body);
 325    :  
 326  E :    StackCapture stack;
 327  E :    stack.InitFromStack();
 328  E :    block_info.header->alloc_stack = stack_cache->SaveStackTrace(stack);
 329    :  
 330  E :    shadow_->PoisonAllocatedBlock(block_info);
 331  E :    BlockSetChecksum(block_info);
 332    :  
 333    :    // Calculate the size of the zone of the buffer that we use to ensure that
 334    :    // we don't corrupt the heap.
 335  E :    buffer_header_size = buffer_align_begin - buffer;
 336  E :    buffer_trailer_size = kBufferSize - buffer_header_size -
 337    :        block_info.block_size;
 338  E :    EXPECT_GT(kBufferSize, layout.block_size + buffer_header_size);
 339    :  
 340    :    // Initialize the buffer header and trailer.
 341  E :    ::memset(buffer, kBufferHeaderValue, buffer_header_size);
 342  E :    ::memset(buffer_align_begin + block_info.block_size, kBufferTrailerValue,
 343    :        buffer_trailer_size);
 344    :  
 345  E :    EXPECT_TRUE(common::IsAligned(reinterpret_cast<size_t>(block_info.body),
 346  E :        alloc_alignment));
 347  E :    EXPECT_TRUE(common::IsAligned(
 348    :        reinterpret_cast<size_t>(buffer_align_begin) + block_info.block_size,
 349  E :        agent::asan::kShadowRatio));
 350  E :    EXPECT_EQ(buffer_align_begin, block_info.RawBlock());
 351    :  
 352    :    void* expected_user_ptr = reinterpret_cast<void*>(
 353  E :        buffer_align_begin + std::max(sizeof(BlockHeader), alloc_alignment));
 354  E :    EXPECT_EQ(block_info.body, expected_user_ptr);
 355    :  
 356  E :    size_t i = 0;
 357    :    // Ensure that the buffer header is accessible and correctly tagged.
 358  E :    for (; i < buffer_header_size; ++i) {
 359  E :      EXPECT_EQ(kBufferHeaderValue, buffer[i]);
 360  E :      EXPECT_TRUE(shadow_->IsAccessible(buffer + i));
 361  E :    }
 362  E :    size_t user_block_offset = block_info.RawBody() - buffer;
 363    :    // Ensure that the block header isn't accessible.
 364  E :    for (; i < user_block_offset; ++i)
 365  E :      EXPECT_FALSE(shadow_->IsAccessible(buffer + i));
 366    :  
 367    :    // Ensure that the user block is accessible.
 368  E :    size_t block_trailer_offset = i + alloc_size;
 369  E :    for (; i < block_trailer_offset; ++i)
 370  E :      EXPECT_TRUE(shadow_->IsAccessible(buffer + i));
 371    :  
 372    :    // Ensure that the block trailer isn't accessible.
 373  E :    for (; i < buffer_header_size + block_info.block_size; ++i)
 374  E :      EXPECT_FALSE(shadow_->IsAccessible(buffer + i));
 375    :  
 376    :    // Ensure that the buffer trailer is accessible and correctly tagged.
 377  E :    for (; i < kBufferSize; ++i) {
 378  E :      EXPECT_EQ(kBufferTrailerValue, buffer[i]);
 379  E :      EXPECT_TRUE(shadow_->IsAccessible(buffer + i));
 380  E :    }
 381    :  
 382  E :    is_initialized = true;
 383  E :    return true;
 384  E :  }
 385    :  
 386    :  bool FakeAsanBlock::TestBlockMetadata() {
 387    :    if (!is_initialized)
 388    :      return false;
 389    :  
 390    :    // Ensure that the block header is valid. BlockGetHeaderFromBody takes
 391    :    // care of checking the magic number in the signature of the block.
 392    :    BlockHeader* block_header = block_info.header;
 393    :    EXPECT_NE(static_cast<BlockHeader*>(NULL), block_header);
 394    :    BlockInfo block_info = {};
 395    :    EXPECT_TRUE(BlockInfoFromMemory(block_header, &block_info));
 396    :    const uint8_t* cursor = buffer_align_begin;
 397    :    EXPECT_EQ(::GetCurrentThreadId(), block_info.trailer->alloc_tid);
 398    :    EXPECT_TRUE(block_header->alloc_stack != NULL);
 399    :    EXPECT_EQ(agent::asan::ALLOCATED_BLOCK, block_header->state);
 400    :    EXPECT_TRUE(shadow_->IsBlockStartByte(cursor++));
 401    :    for (; cursor < block_info.RawBody(); ++cursor)
 402    :      EXPECT_TRUE(shadow_->IsLeftRedzone(cursor));
 403    :    const uint8_t* aligned_trailer_begin =
 404    :        reinterpret_cast<const uint8_t*>(common::AlignUp(
 405    :            reinterpret_cast<size_t>(block_info.body) + block_info.body_size,
 406    :            agent::asan::kShadowRatio));
 407    :    for (const uint8_t* pos = aligned_trailer_begin;
 408    :         pos < buffer_align_begin + block_info.block_size; ++pos) {
 409    :      EXPECT_TRUE(shadow_->IsRightRedzone(pos));
 410    :    }
 411    :  
 412    :    return true;
 413    :  }
 414    :  
 415  E :  bool FakeAsanBlock::MarkBlockAsQuarantinedImpl(bool flood_filled) {
 416  E :    if (!is_initialized)
 417  i :      return false;
 418    :  
 419  E :    EXPECT_NE(static_cast<BlockHeader*>(NULL), block_info.header);
 420  E :    EXPECT_TRUE(block_info.header->free_stack == NULL);
 421  E :    EXPECT_TRUE(block_info.trailer != NULL);
 422  E :    EXPECT_EQ(0U, block_info.trailer->free_tid);
 423    :  
 424  E :    shadow_->MarkAsFreed(block_info.body, block_info.body_size);
 425  E :    StackCapture stack;
 426  E :    stack.InitFromStack();
 427  E :    block_info.header->free_stack = stack_cache->SaveStackTrace(stack);
 428  E :    block_info.trailer->free_tid = ::GetCurrentThreadId();
 429  E :    block_info.trailer->free_ticks = ::GetTickCount();
 430    :  
 431  E :    if (flood_filled) {
 432  E :      block_info.header->state = agent::asan::QUARANTINED_FLOODED_BLOCK;
 433  E :      ::memset(block_info.body, agent::asan::kBlockFloodFillByte,
 434    :               block_info.body_size);
 435  E :    } else {
 436  E :      block_info.header->state = agent::asan::QUARANTINED_BLOCK;
 437    :    }
 438    :  
 439  E :    BlockSetChecksum(block_info);
 440    :  
 441  E :    size_t i = 0;
 442    :    // Ensure that the buffer header is accessible and correctly tagged.
 443  E :    for (; i < buffer_header_size; ++i) {
 444  E :      EXPECT_EQ(kBufferHeaderValue, buffer[i]);
 445  E :      EXPECT_TRUE(shadow_->IsAccessible(buffer + i));
 446  E :    }
 447    :    // Ensure that the whole block isn't accessible.
 448  E :    for (; i < buffer_header_size + block_info.block_size; ++i)
 449  E :      EXPECT_FALSE(shadow_->IsAccessible(buffer + i));
 450    :  
 451    :    // Ensure that the buffer trailer is accessible and correctly tagged.
 452  E :    for (; i < kBufferSize; ++i) {
 453  E :      EXPECT_EQ(kBufferTrailerValue, buffer[i]);
 454  E :      EXPECT_TRUE(shadow_->IsAccessible(buffer + i));
 455  E :    }
 456  E :    return true;
 457  E :  }
 458    :  
 459  E :  bool FakeAsanBlock::MarkBlockAsQuarantined() {
 460  E :    return MarkBlockAsQuarantinedImpl(false);
 461  E :  }
 462    :  
 463  E :  bool FakeAsanBlock::MarkBlockAsQuarantinedFlooded() {
 464  E :    return MarkBlockAsQuarantinedImpl(true);
 465  E :  }
 466    :  
 467    :  namespace {
 468    :  
 469    :  #define RTL_CAPTURE_CONTEXT(context, expected_eip) {  \
 470    :    /* Save caller save registers. */  \
 471    :    __asm push eax  \
 472    :    __asm push ecx  \
 473    :    __asm push edx  \
 474    :    /* Call Capture context. */  \
 475    :    __asm push context  \
 476    :    __asm call dword ptr[RtlCaptureContext]  \
 477    :    /* Restore caller save registers. */  \
 478    :    __asm pop edx  \
 479    :    __asm pop ecx  \
 480    :    __asm pop eax  \
 481    :    /* Restore registers which are stomped by RtlCaptureContext. */  \
 482    :    __asm push eax  \
 483    :    __asm pushfd  \
 484    :    __asm mov eax, context  \
 485    :    __asm mov dword ptr[eax + CONTEXT.Ebp], ebp  \
 486    :    __asm mov dword ptr[eax + CONTEXT.Esp], esp  \
 487    :    /* NOTE: we need to add 8 bytes because EAX + EFLAGS are on the stack. */  \
 488    :    __asm add dword ptr[eax + CONTEXT.Esp], 8  \
 489    :    __asm mov dword ptr[eax + CONTEXT.Eip], offset expected_eip  \
 490    :    __asm popfd  \
 491    :    __asm pop eax  \
 492    :  }
 493    :  
 494    :  // Check whether 2 contexts are equal.
 495    :  // @param c1 The first context to check.
 496    :  // @param c2 The second context to check.
 497    :  void ExpectEqualContexts(const CONTEXT& c1,
 498    :                           const CONTEXT& c2,
 499  E :                           bool ignore_flags) {
 500    :    // Segment registers.
 501  E :    EXPECT_EQ(static_cast<WORD>(c1.SegGs), static_cast<WORD>(c2.SegGs));
 502  E :    EXPECT_EQ(static_cast<WORD>(c1.SegFs), static_cast<WORD>(c2.SegFs));
 503  E :    EXPECT_EQ(static_cast<WORD>(c1.SegEs), static_cast<WORD>(c2.SegEs));
 504  E :    EXPECT_EQ(static_cast<WORD>(c1.SegDs), static_cast<WORD>(c2.SegDs));
 505    :  
 506    :    // General registers.
 507  E :    EXPECT_EQ(c1.Edi, c2.Edi);
 508  E :    EXPECT_EQ(c1.Esi, c2.Esi);
 509  E :    EXPECT_EQ(c1.Ebx, c2.Ebx);
 510  E :    EXPECT_EQ(c1.Edx, c2.Edx);
 511  E :    EXPECT_EQ(c1.Ecx, c2.Ecx);
 512  E :    EXPECT_EQ(c1.Eax, c2.Eax);
 513    :  
 514    :    // "Control" registers.
 515  E :    EXPECT_EQ(c1.Ebp, c2.Ebp);
 516  E :    EXPECT_EQ(c1.Eip, c2.Eip);
 517  E :    EXPECT_EQ(static_cast<WORD>(c1.SegCs), static_cast<WORD>(c2.SegCs));
 518  E :    if (!ignore_flags)
 519  E :      EXPECT_EQ(c1.EFlags, c2.EFlags);
 520  E :    EXPECT_EQ(c1.Esp, c2.Esp);
 521  E :    EXPECT_EQ(static_cast<WORD>(c1.SegSs), static_cast<WORD>(c2.SegSs));
 522  E :  }
 523    :  
 524    :  }  // namespace
 525    :  
 526    :  MemoryAccessorTester::MemoryAccessorTester()
 527  E :      : expected_error_type_(agent::asan::UNKNOWN_BAD_ACCESS),
 528  E :        memory_error_detected_(false),
 529  E :        ignore_flags_(false) {
 530  E :    EXPECT_EQ(static_cast<MemoryAccessorTester*>(NULL), instance_);
 531    :  
 532  E :    Initialize();
 533  E :    instance_ = this;
 534  E :  }
 535    :  
 536    :  MemoryAccessorTester::MemoryAccessorTester(IgnoreFlags /* ignore_flags */)
 537  E :      : expected_error_type_(agent::asan::UNKNOWN_BAD_ACCESS),
 538  E :        memory_error_detected_(false),
 539  E :        ignore_flags_(true) {
 540  E :    EXPECT_EQ(static_cast<MemoryAccessorTester*>(NULL), instance_);
 541    :  
 542  E :    Initialize();
 543  E :    instance_ = this;
 544  E :  }
 545    :  
 546  E :  MemoryAccessorTester::~MemoryAccessorTester() {
 547  E :    EXPECT_EQ(this, instance_);
 548  E :    instance_ = NULL;
 549  E :  }
 550    :  
 551  E :  void MemoryAccessorTester::Initialize() {
 552  E :    ::memset(&context_before_hook_, 0xCD, sizeof(context_before_hook_));
 553  E :    ::memset(&context_after_hook_, 0xCE, sizeof(context_after_hook_));
 554  E :    ::memset(&error_context_, 0xCF, sizeof(error_context_));
 555  E :    ::memset(&last_error_info_, 0, sizeof(last_error_info_));
 556  E :  }
 557    :  
 558    :  namespace {
 559    :  
 560    :  void CheckAccessAndCaptureContexts(
 561  i :      CONTEXT* before, CONTEXT* after, void* location) {
 562    :    __asm {
 563  i :      pushad
 564  i :      pushfd
 565    :  
 566    :      // Avoid undefined behavior by forcing values.
 567  i :      mov eax, 0x01234567
 568  i :      mov ebx, 0x70123456
 569  i :      mov ecx, 0x12345678
 570  i :      mov edx, 0x56701234
 571  i :      mov esi, 0xCCAACCAA
 572  i :      mov edi, 0xAACCAACC
 573    :  
 574  i :      RTL_CAPTURE_CONTEXT(before, check_access_expected_eip)
 575    :  
 576    :      // Push EDX as we're required to do by the custom calling convention.
 577  i :      push edx
 578    :      // Ptr is the pointer to check.
 579  i :      mov edx, location
 580    :      // Call through.
 581  i :      call dword ptr[check_access_fn + 0]
 582    :   check_access_expected_eip:
 583    :  
 584  i :      RTL_CAPTURE_CONTEXT(after, check_access_expected_eip)
 585    :  
 586  i :      popfd
 587  i :      popad
 588    :    }
 589  i :  }
 590    :  
 591    :  }  // namespace
 592    :  
 593    :  void MemoryAccessorTester::CheckAccessAndCompareContexts(
 594  E :      FARPROC access_fn, void* ptr) {
 595  E :    memory_error_detected_ = false;
 596    :  
 597  E :    check_access_fn = access_fn;
 598    :  
 599  E :    CheckAccessAndCaptureContexts(
 600    :        &context_before_hook_, &context_after_hook_, ptr);
 601    :  
 602  E :    ExpectEqualContexts(context_before_hook_,
 603    :                        context_after_hook_,
 604    :                        ignore_flags_);
 605  E :    if (memory_error_detected_) {
 606  E :      ExpectEqualContexts(context_before_hook_,
 607    :                          error_context_,
 608    :                          ignore_flags_);
 609    :    }
 610    :  
 611  E :    check_access_fn = NULL;
 612  E :  }
 613    :  
 614    :  namespace {
 615    :  
 616    :  void CheckSpecialAccess(CONTEXT* before, CONTEXT* after,
 617  i :                          void* dst, void* src, int len) {
 618    :    __asm {
 619  i :      pushad
 620  i :      pushfd
 621    :  
 622    :      // Override the direction flag.
 623  i :      cld
 624  i :      cmp direction_flag_forward, 0
 625  i :      jne skip_reverse_direction
 626  i :      std
 627    :   skip_reverse_direction:
 628    :  
 629    :      // Avoid undefined behavior by forcing values.
 630  i :      mov eax, 0x01234567
 631  i :      mov ebx, 0x70123456
 632  i :      mov edx, 0x56701234
 633    :  
 634    :      // Setup registers used by the special instruction.
 635  i :      mov ecx, len
 636  i :      mov esi, src
 637  i :      mov edi, dst
 638    :  
 639  i :      RTL_CAPTURE_CONTEXT(before, special_access_expected_eip)
 640    :  
 641    :      // Call through.
 642  i :      call dword ptr[check_access_fn + 0]
 643    :   special_access_expected_eip:
 644    :  
 645  i :      RTL_CAPTURE_CONTEXT(after, special_access_expected_eip)
 646    :  
 647  i :      popfd
 648  i :      popad
 649    :    }
 650  i :  }
 651    :  
 652    :  }  // namespace
 653    :  
 654    :  void MemoryAccessorTester::CheckSpecialAccessAndCompareContexts(
 655    :      FARPROC access_fn, StringOperationDirection direction,
 656  E :      void* dst, void* src, int len) {
 657  E :    memory_error_detected_ = false;
 658    :  
 659  E :    direction_flag_forward = (direction == DIRECTION_FORWARD);
 660  E :    check_access_fn = access_fn;
 661    :  
 662  E :    CheckSpecialAccess(
 663    :        &context_before_hook_, &context_after_hook_, dst, src, len);
 664    :  
 665  E :    ExpectEqualContexts(context_before_hook_,
 666    :                        context_after_hook_,
 667    :                        ignore_flags_);
 668  E :    if (memory_error_detected_) {
 669  E :      ExpectEqualContexts(context_before_hook_,
 670    :                          error_context_,
 671    :                          ignore_flags_);
 672    :    }
 673    :  
 674  E :    check_access_fn = NULL;
 675  E :  }
 676    :  
 677  E :  void MemoryAccessorTester::AsanErrorCallbackImpl(AsanErrorInfo* error_info) {
 678    :    // TODO(sebmarchand): Stash the error info in a fixture-static variable and
 679    :    // assert on specific conditions after the fact.
 680  E :    EXPECT_NE(reinterpret_cast<AsanErrorInfo*>(NULL), error_info);
 681  E :    EXPECT_NE(agent::asan::UNKNOWN_BAD_ACCESS, error_info->error_type);
 682    :  
 683  E :    EXPECT_EQ(expected_error_type_, error_info->error_type);
 684  E :    if (error_info->error_type >= agent::asan::USE_AFTER_FREE) {
 685    :      // We should at least have the stack trace of the allocation of this block.
 686  E :      EXPECT_GT(error_info->block_info.alloc_stack_size, 0U);
 687  E :      EXPECT_NE(0U, error_info->block_info.alloc_tid);
 688  E :      if (error_info->error_type == agent::asan::USE_AFTER_FREE ||
 689    :        error_info->error_type == agent::asan::DOUBLE_FREE) {
 690  E :        EXPECT_GT(error_info->block_info.free_stack_size, 0U);
 691  E :        EXPECT_NE(0U, error_info->block_info.free_tid);
 692  E :      } else {
 693  E :        EXPECT_EQ(error_info->block_info.free_stack_size, 0U);
 694  E :        EXPECT_EQ(0U, error_info->block_info.free_tid);
 695    :      }
 696    :    }
 697    :  
 698  E :    if (error_info->error_type == agent::asan::HEAP_BUFFER_OVERFLOW) {
 699  E :      EXPECT_TRUE(strstr(error_info->shadow_info, "beyond") != NULL);
 700  E :    } else if (error_info->error_type == agent::asan::HEAP_BUFFER_UNDERFLOW) {
 701  E :      EXPECT_TRUE(strstr(error_info->shadow_info, "before") != NULL);
 702    :    }
 703    :  
 704  E :    memory_error_detected_ = true;
 705  E :    last_error_info_ = *error_info;
 706    :  
 707    :    // Copy the corrupt range's information.
 708  E :    if (error_info->heap_is_corrupt) {
 709  E :      EXPECT_GE(1U, error_info->corrupt_range_count);
 710  E :      for (size_t i = 0; i < error_info->corrupt_range_count; ++i) {
 711  E :        last_corrupt_ranges_.push_back(CorruptRangeInfo());
 712  E :        CorruptRangeInfo* range_info = &last_corrupt_ranges_.back();
 713  E :        range_info->first = error_info->corrupt_ranges[i];
 714  E :        AsanBlockInfoVector* block_infos = &range_info->second;
 715  E :        for (size_t j = 0; j < range_info->first.block_info_count; ++j) {
 716  E :          agent::asan::AsanBlockInfo block_info = range_info->first.block_info[j];
 717  E :          for (size_t k = 0;
 718  E :               k < range_info->first.block_info[j].alloc_stack_size;
 719  E :               ++k) {
 720  E :            block_info.alloc_stack[k] =
 721    :                range_info->first.block_info[j].alloc_stack[k];
 722  E :          }
 723  E :          for (size_t k = 0;
 724  E :               k < range_info->first.block_info[j].free_stack_size;
 725  i :               ++k) {
 726  i :            block_info.free_stack[k] =
 727    :                range_info->first.block_info[j].free_stack[k];
 728  i :          }
 729  E :          block_infos->push_back(block_info);
 730  E :        }
 731  E :      }
 732    :    }
 733    :  
 734  E :    error_context_ = error_info->context;
 735  E :  }
 736    :  
 737  E :  void MemoryAccessorTester::AsanErrorCallback(AsanErrorInfo* error_info) {
 738  E :    ASSERT_NE(reinterpret_cast<MemoryAccessorTester*>(NULL), instance_);
 739    :  
 740  E :    instance_->AsanErrorCallbackImpl(error_info);
 741  E :  }
 742    :  
 743    :  void MemoryAccessorTester::AssertMemoryErrorIsDetected(
 744  E :    FARPROC access_fn, void* ptr, BadAccessKind bad_access_type) {
 745  E :    expected_error_type_ = bad_access_type;
 746  E :    CheckAccessAndCompareContexts(access_fn, ptr);
 747  E :    ASSERT_TRUE(memory_error_detected_);
 748  E :  }
 749    :  
 750    :  void MemoryAccessorTester::ExpectSpecialMemoryErrorIsDetected(
 751    :      FARPROC access_fn,
 752    :      StringOperationDirection direction,
 753    :      bool expect_error,
 754    :      void* dst,
 755    :      void* src,
 756    :      int32_t length,
 757  E :      BadAccessKind bad_access_type) {
 758  E :    DCHECK(dst != NULL);
 759  E :    DCHECK(src != NULL);
 760  E :    ASSERT_TRUE(check_access_fn == NULL);
 761    :  
 762  E :    expected_error_type_ = bad_access_type;
 763    :  
 764    :    // Perform memory accesses inside the range.
 765  E :    ASSERT_NO_FATAL_FAILURE(
 766    :        CheckSpecialAccessAndCompareContexts(
 767  E :            access_fn, direction, dst, src, length));
 768    :  
 769  E :    EXPECT_EQ(expect_error, memory_error_detected_);
 770  E :    check_access_fn = NULL;
 771  E :  }
 772    :  
 773    :  TestMemoryInterceptors::TestMemoryInterceptors()
 774  E :      : heap_(NULL), src_(NULL), dst_(NULL) {
 775  E :  }
 776    :  
 777  E :  void TestMemoryInterceptors::SetUp() {
 778  E :    testing::TestWithAsanLogger::SetUp();
 779    :  
 780    :    // Make sure the logging routes to our instance.
 781  E :    AppendToLoggerEnv(base::StringPrintf("syzyasan_rtl_unittests.exe,%u",
 782    :                                          ::GetCurrentProcessId()));
 783    :  
 784  E :    asan_runtime_.SetUp(std::wstring());
 785    :  
 786    :    // Heap checking on error is expensive, so turn it down here.
 787  E :    asan_runtime_.params().check_heap_on_failure = false;
 788    :  
 789  E :    agent::asan::SetUpRtl(&asan_runtime_);
 790    :  
 791  E :    asan_runtime_.SetErrorCallBack(
 792    :        base::Bind(testing::MemoryAccessorTester::AsanErrorCallback));
 793  E :    heap_ = asan_HeapCreate(0, 0, 0);
 794  E :    ASSERT_TRUE(heap_ != NULL);
 795    :  
 796  E :    src_ = reinterpret_cast<byte*>(asan_HeapAlloc(heap_, 0, kAllocSize));
 797  E :    dst_ = reinterpret_cast<byte*>(asan_HeapAlloc(heap_, 0, kAllocSize));
 798  E :    ASSERT_TRUE(src_ && dst_);
 799    :  
 800    :    // String instructions may compare memory contents and bail early on
 801    :    // differences, so fill the buffers to make sure the checks go the full
 802    :    // distance.
 803  E :    ::memset(src_, 0xFF, kAllocSize);
 804  E :    ::memset(dst_, 0xFF, kAllocSize);
 805  E :  }
 806    :  
 807  E :  void TestMemoryInterceptors::TearDown() {
 808  E :    if (heap_ != NULL) {
 809  E :      asan_HeapFree(heap_, 0, src_);
 810  E :      asan_HeapFree(heap_, 0, dst_);
 811    :  
 812  E :      asan_HeapDestroy(heap_);
 813  E :      heap_ = NULL;
 814    :    }
 815  E :    agent::asan::TearDownRtl();
 816  E :    asan_runtime_.TearDown();
 817  E :    testing::TestWithAsanLogger::TearDown();
 818  E :  }
 819    :  
 820    :  void TestMemoryInterceptors::TestValidAccess(
 821  E :      const InterceptFunction* fns, size_t num_fns) {
 822  E :    for (size_t i = 0; i < num_fns; ++i) {
 823  E :      const InterceptFunction& fn = fns[i];
 824    :  
 825  E :      MemoryAccessorTester tester;
 826  E :      tester.CheckAccessAndCompareContexts(
 827    :          reinterpret_cast<FARPROC>(fn.function), src_);
 828    :  
 829  E :      ASSERT_FALSE(tester.memory_error_detected());
 830  E :    }
 831  E :  }
 832    :  
 833    :  void TestMemoryInterceptors::TestValidAccessIgnoreFlags(
 834  E :      const InterceptFunction* fns, size_t num_fns) {
 835  E :    for (size_t i = 0; i < num_fns; ++i) {
 836  E :      const InterceptFunction& fn = fns[i];
 837    :  
 838  E :      MemoryAccessorTester tester(MemoryAccessorTester::IGNORE_FLAGS);
 839  E :      tester.CheckAccessAndCompareContexts(
 840    :          reinterpret_cast<FARPROC>(fn.function), src_);
 841    :  
 842  E :      ASSERT_FALSE(tester.memory_error_detected());
 843  E :    }
 844  E :  }
 845    :  
 846    :  void TestMemoryInterceptors::TestOverrunAccess(
 847  E :      const InterceptFunction* fns, size_t num_fns) {
 848  E :    for (size_t i = 0; i < num_fns; ++i) {
 849  E :      const InterceptFunction& fn = fns[i];
 850    :  
 851  E :      MemoryAccessorTester tester;
 852  E :      tester.AssertMemoryErrorIsDetected(
 853    :          reinterpret_cast<FARPROC>(fn.function),
 854    :          src_ + kAllocSize,
 855    :          MemoryAccessorTester::BadAccessKind::HEAP_BUFFER_OVERFLOW);
 856    :  
 857  E :      ASSERT_TRUE(tester.memory_error_detected());
 858  E :    }
 859  E :  }
 860    :  
 861    :  void TestMemoryInterceptors::TestOverrunAccessIgnoreFlags(
 862  E :      const InterceptFunction* fns, size_t num_fns) {
 863  E :    for (size_t i = 0; i < num_fns; ++i) {
 864  E :      const InterceptFunction& fn = fns[i];
 865    :  
 866  E :      MemoryAccessorTester tester(MemoryAccessorTester::IGNORE_FLAGS);
 867  E :      tester.AssertMemoryErrorIsDetected(
 868    :          reinterpret_cast<FARPROC>(fn.function),
 869    :          src_ + kAllocSize,
 870    :          MemoryAccessorTester::BadAccessKind::HEAP_BUFFER_OVERFLOW);
 871    :  
 872  E :      ASSERT_TRUE(tester.memory_error_detected());
 873  E :    }
 874  E :  }
 875    :  
 876    :  void TestMemoryInterceptors::TestUnderrunAccess(
 877  E :      const InterceptFunction* fns, size_t num_fns) {
 878  E :    for (size_t i = 0; i < num_fns; ++i) {
 879  E :      const InterceptFunction& fn = fns[i];
 880    :  
 881    :      // TODO(someone): the 32 byte access checker does not fire on 32 byte
 882    :      //     underrun. I guess the checkers test a single shadow byte at most
 883    :      //     whereas it'd be more correct for access checkers to test as many
 884    :      //     shadow bytes as is appropriate for the range of memory they touch.
 885  E :      MemoryAccessorTester tester;
 886  E :      tester.AssertMemoryErrorIsDetected(
 887    :          reinterpret_cast<FARPROC>(fn.function),
 888    :          src_ - 8,
 889    :          MemoryAccessorTester::BadAccessKind::HEAP_BUFFER_UNDERFLOW);
 890    :  
 891  E :      ASSERT_TRUE(tester.memory_error_detected());
 892  E :    }
 893  E :  }
 894    :  
 895    :  void TestMemoryInterceptors::TestUnderrunAccessIgnoreFlags(
 896  E :      const InterceptFunction* fns, size_t num_fns) {
 897  E :    for (size_t i = 0; i < num_fns; ++i) {
 898  E :      const InterceptFunction& fn = fns[i];
 899    :  
 900    :      // TODO(someone): the 32 byte access checker does not fire on 32 byte
 901    :      //     underrun. I guess the checkers test a single shadow byte at most
 902    :      //     whereas it'd be more correct for access checkers to test as many
 903    :      //     shadow bytes as is appropriate for the range of memory they touch.
 904  E :      MemoryAccessorTester tester(MemoryAccessorTester::IGNORE_FLAGS);
 905  E :      tester.AssertMemoryErrorIsDetected(
 906    :          reinterpret_cast<FARPROC>(fn.function),
 907    :          src_ - 8,
 908    :          MemoryAccessorTester::BadAccessKind::HEAP_BUFFER_UNDERFLOW);
 909    :  
 910  E :      ASSERT_TRUE(tester.memory_error_detected());
 911  E :    }
 912  E :  }
 913    :  
 914    :  void TestMemoryInterceptors::TestStringValidAccess(
 915  E :      const StringInterceptFunction* fns, size_t num_fns) {
 916  E :    for (size_t i = 0; i < num_fns; ++i) {
 917  E :      const StringInterceptFunction& fn = fns[i];
 918    :  
 919  E :      MemoryAccessorTester tester;
 920  E :      tester.CheckSpecialAccessAndCompareContexts(
 921    :          reinterpret_cast<FARPROC>(fn.function),
 922    :          MemoryAccessorTester::DIRECTION_FORWARD,
 923    :          dst_, src_, kAllocSize / fn.size);
 924  E :      ASSERT_FALSE(tester.memory_error_detected());
 925    :  
 926  E :      tester.CheckSpecialAccessAndCompareContexts(
 927    :          reinterpret_cast<FARPROC>(fn.function),
 928    :          MemoryAccessorTester::DIRECTION_BACKWARD,
 929    :          dst_ + kAllocSize - fn.size, src_ + kAllocSize - fn.size,
 930    :          kAllocSize / fn.size);
 931    :  
 932  E :      ASSERT_FALSE(tester.memory_error_detected());
 933  E :    }
 934  E :  }
 935    :  
 936    :  void TestMemoryInterceptors::TestStringOverrunAccess(
 937  E :      const StringInterceptFunction* fns, size_t num_fns) {
 938  E :    for (size_t i = 0; i < num_fns; ++i) {
 939  E :      const StringInterceptFunction& fn = fns[i];
 940    :  
 941  E :      MemoryAccessorTester tester;
 942  E :      size_t oob_len = 0;
 943  E :      byte* oob_dst = NULL;
 944  E :      byte* oob_src = NULL;
 945    :  
 946    :      // Half the string function intercepts are for rep-prefixed instructions,
 947    :      // which count on "ecx", and the other half is for non-prefixed
 948    :      // instructions that always perform a single access.
 949    :      // Compute appropriate pointers for both variants, forwards.
 950  E :      if (fn.uses_counter) {
 951  E :        oob_len = kAllocSize / fn.size;
 952  E :        oob_dst = dst_ + fn.size;
 953  E :        oob_src = src_ + fn.size;
 954  E :      } else {
 955  E :        oob_len = 1;
 956  E :        oob_dst = dst_ + kAllocSize;
 957  E :        oob_src = src_ + kAllocSize;
 958    :      }
 959    :  
 960  E :      ASSERT_NE(agent::asan::ASAN_UNKNOWN_ACCESS, fn.dst_access_mode);
 961    :      // Overflow on dst forwards.
 962  E :      tester.ExpectSpecialMemoryErrorIsDetected(
 963    :          reinterpret_cast<FARPROC>(fn.function),
 964    :          MemoryAccessorTester::DIRECTION_FORWARD, true,
 965    :          oob_dst, src_, oob_len,
 966    :          MemoryAccessorTester::BadAccessKind::HEAP_BUFFER_OVERFLOW);
 967    :  
 968  E :      if (fn.src_access_mode != agent::asan::ASAN_UNKNOWN_ACCESS) {
 969    :        // Overflow on src forwards.
 970  E :        tester.ExpectSpecialMemoryErrorIsDetected(
 971    :            reinterpret_cast<FARPROC>(fn.function),
 972    :            MemoryAccessorTester::DIRECTION_FORWARD, true,
 973    :            dst_, oob_src, oob_len,
 974    :            MemoryAccessorTester::BadAccessKind::HEAP_BUFFER_OVERFLOW);
 975    :      }
 976    :  
 977    :      // Compute appropriate pointers for both variants, backwards.
 978  E :      if (fn.uses_counter) {
 979  E :        oob_len = kAllocSize / fn.size;
 980  E :      } else {
 981  E :        oob_len = 1;
 982    :      }
 983    :  
 984  E :      oob_dst = dst_ + kAllocSize;
 985  E :      oob_src = src_ + kAllocSize;
 986    :  
 987  E :      ASSERT_NE(agent::asan::ASAN_UNKNOWN_ACCESS, fn.dst_access_mode);
 988    :      // Overflow on dst backwards.
 989  E :      tester.ExpectSpecialMemoryErrorIsDetected(
 990    :          reinterpret_cast<FARPROC>(fn.function),
 991    :          MemoryAccessorTester::DIRECTION_BACKWARD, true,
 992    :          oob_dst, src_ + kAllocSize - fn.size, oob_len,
 993    :          MemoryAccessorTester::BadAccessKind::HEAP_BUFFER_OVERFLOW);
 994    :  
 995  E :      if (fn.src_access_mode != agent::asan::ASAN_UNKNOWN_ACCESS) {
 996    :        // Overflow on src backwards.
 997  E :        tester.ExpectSpecialMemoryErrorIsDetected(
 998    :            reinterpret_cast<FARPROC>(fn.function),
 999    :            MemoryAccessorTester::DIRECTION_BACKWARD, true,
1000    :            dst_ + kAllocSize - fn.size, oob_dst, oob_len,
1001    :            MemoryAccessorTester::BadAccessKind::HEAP_BUFFER_OVERFLOW);
1002    :      }
1003  E :    }
1004  E :  }
1005    :  
1006  E :  bool IsAccessible(void* address) {
1007  E :    return testing::TestAccess(address, false);
1008  E :  }
1009    :  
1010  E :  bool IsNotAccessible(void* address) {
1011  E :    return testing::TestAccess(address, true);
1012  E :  }
1013    :  
1014    :  DebugShadow::Metadata::Metadata()
1015    :      : address(nullptr), size(0),
1016    :        marker(agent::asan::kHeapAddressableMarker) {
1017    :  }
1018    :  
1019    :  DebugShadow::Metadata::Metadata(
1020    :      const void* address, size_t size, ShadowMarker marker)
1021    :      : address(address), size(size), marker(marker) {
1022    :    stack_capture.InitFromStack();
1023    :  }
1024    :  
1025    :  DebugShadow::Metadata::Metadata(const Metadata& rhs)
1026    :      : address(rhs.address), size(rhs.size), marker(rhs.marker) {
1027    :    if (rhs.stack_capture.num_frames() > 0) {
1028    :      stack_capture.InitFromExistingStack(rhs.stack_capture);
1029    :    }
1030    :  }
1031    :  
1032    :  DebugShadow::Metadata& DebugShadow::Metadata::operator=(const Metadata& rhs) {
1033    :    address = rhs.address;
1034    :    size = rhs.size;
1035    :    marker = rhs.marker;
1036    :    if (rhs.stack_capture.num_frames() > 0) {
1037    :      stack_capture.InitFromExistingStack(rhs.stack_capture);
1038    :    }
1039    :    return *this;
1040    :  }
1041    :  
1042    :  void DebugShadow::SetShadowMemory(
1043    :      const void* address, size_t length, ShadowMarker marker) {
1044    :    ClearIntersection(address, length);
1045    :    if (marker != agent::asan::kHeapAddressableMarker) {
1046    :      Range range(reinterpret_cast<uintptr_t>(address), length);
1047    :      Metadata data(address, length, marker);
1048    :  
1049    :      ShadowAddressSpace::RangeMapIter it;
1050    :      CHECK(shadow_address_space_.Insert(range, data, &it));
1051    :  
1052    :      // If this is memory being returned to a reserved pool, then potentially
1053    :      // merge with neighboring such ranges. This keeps the address space as
1054    :      // human legible as possible.
1055    :      if (marker == agent::asan::kAsanReservedMarker) {
1056    :        auto it1 = it;
1057    :        auto it2 = it;
1058    :        bool merge = false;
1059    :        Metadata data = it->second;
1060    :  
1061    :        // Check to see if there's a range to the left, and if it needs to be
1062    :        // merged.
1063    :        if (it != shadow_address_space_.begin()) {
1064    :          it1--;
1065    :          if (it1->first.end() == it->first.start() &&
1066    :              it1->second.marker == it->second.marker) {
1067    :            merge = true;
1068    :            if (it1->second.size >= data.size)
1069    :              data = it1->second;
1070    :          } else {
1071    :            ++it1;
1072    :          }
1073    :        }
1074    :  
1075    :        // Check to see if there's a range to the right, and if it needs to be
1076    :        // merged.
1077    :        ++it2;
1078    :        if (it2 != shadow_address_space_.end()) {
1079    :          if (it->first.end() == it2->first.start() &&
1080    :              it->second.marker == it2->second.marker) {
1081    :            merge = true;
1082    :            if (it2->second.size > data.size)
1083    :              data = it2->second;
1084    :          } else {
1085    :            --it2;
1086    :          }
1087    :        } else {
1088    :          --it2;
1089    :        }
1090    :  
1091    :        if (merge) {
1092    :          Range range(it1->first.start(),
1093    :                      it2->first.end() - it1->first.start());
1094    :          CHECK(shadow_address_space_.SubsumeInsert(range, data));
1095    :        }
1096    :      }
1097    :    }
1098    :  }
1099    :  
1100    :  void DebugShadow::GetPointerAndSizeImpl(
1101    :      void const** self, size_t* size) const {
1102    :    DCHECK_NE(static_cast<void**>(nullptr), self);
1103    :    DCHECK_NE(static_cast<size_t*>(nullptr), size);
1104    :    *self = this;
1105    :    *size = sizeof(*this);
1106    :  }
1107    :  
1108    :  void DebugShadow::ClearIntersection(const void* addr, size_t size) {
1109    :    uintptr_t start = reinterpret_cast<uintptr_t>(addr);
1110    :  
1111    :    auto range = Range(reinterpret_cast<uintptr_t>(addr), size);
1112    :    ShadowAddressSpace::RangeMapIterPair iter_pair =
1113    :        shadow_address_space_.FindIntersecting(range);
1114    :  
1115    :    bool reinsert_head_range = false;
1116    :    Range head_range;
1117    :    Metadata head_data;
1118    :  
1119    :    bool reinsert_tail_range = false;
1120    :    Range tail_range;
1121    :    Metadata tail_data;
1122    :  
1123    :    // If the range is non-empty then remember the portion of the head and tail
1124    :    // ranges to be reinserted, if any.
1125    :    if (iter_pair.first != iter_pair.second) {
1126    :      auto it = iter_pair.first;
1127    :      if (it->first.start() < start) {
1128    :        reinsert_head_range = true;
1129    :        head_range = Range(
1130    :            it->first.start(),
1131    :            start - it->first.start());
1132    :        head_data = it->second;
1133    :      }
1134    :  
1135    :      it = iter_pair.second;
1136    :      --it;
1137    :      if (start + size < it->first.end()) {
1138    :        reinsert_tail_range = true;
1139    :        tail_range = Range(
1140    :            range.end(),
1141    :            it->first.end() - range.end());
1142    :        tail_data = it->second;
1143    :      }
1144    :    }
1145    :  
1146    :    // Delete the entire range.
1147    :    shadow_address_space_.Remove(iter_pair);
1148    :    if (reinsert_head_range)
1149    :      CHECK(shadow_address_space_.Insert(head_range, head_data));
1150    :    if (reinsert_tail_range)
1151    :      CHECK(shadow_address_space_.Insert(tail_range, tail_data));
1152    :  }
1153    :  
1154    :  }  // namespace testing

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