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

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

Coverage information generated Thu Mar 26 16:15:41 2015.