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

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
90.0%3233590.C++test

Line-by-line coverage:

   1    :  // Copyright 2012 Google Inc. All Rights Reserved.
   2    :  //
   3    :  // Licensed under the Apache License, Version 2.0 (the "License");
   4    :  // you may not use this file except in compliance with the License.
   5    :  // You may obtain a copy of the License at
   6    :  //
   7    :  //     http://www.apache.org/licenses/LICENSE-2.0
   8    :  //
   9    :  // Unless required by applicable law or agreed to in writing, software
  10    :  // distributed under the License is distributed on an "AS IS" BASIS,
  11    :  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12    :  // See the License for the specific language governing permissions and
  13    :  // limitations under the License.
  14    :  #include <windows.h>
  15    :  
  16    :  #include "gtest/gtest.h"
  17    :  #include "syzygy/agent/asan/asan_heap.h"
  18    :  #include "syzygy/agent/asan/asan_runtime.h"
  19    :  #include "syzygy/agent/asan/asan_shadow.h"
  20    :  #include "syzygy/agent/asan/unittest_util.h"
  21    :  #include "syzygy/core/unittest_util.h"
  22    :  
  23    :  namespace agent {
  24    :  namespace asan {
  25    :  
  26    :  namespace {
  27    :  
  28    :  // The access check function invoked by the below.
  29    :  FARPROC check_access_fn = NULL;
  30    :  // A flag used in asan callback to ensure that a memory error has been detected.
  31    :  bool memory_error_detected = false;
  32    :  // A pointer to a context to ensure that we're able to restore the context when
  33    :  // an asan error is found.
  34    :  CONTEXT* context_before_hook = NULL;
  35    :  // This will be used in the asan callback to ensure that we detect the right
  36    :  // error.
  37    :  HeapProxy::BadAccessKind expected_error_type = HeapProxy::UNKNOWN_BAD_ACCESS;
  38    :  // A flag to override the direction flag on special instruction checker.
  39    :  bool direction_flag_forward = true;
  40    :  // An arbitrary size for the buffer we allocate in the different unittests.
  41    :  const size_t kAllocSize = 13;
  42    :  
  43    :  // Shorthand for discussing all the asan runtime functions.
  44    :  #define ASAN_RTL_FUNCTIONS(F)  \
  45    :      F(HANDLE, HeapCreate,  \
  46    :        (DWORD options, SIZE_T initial_size, SIZE_T maximum_size))  \
  47    :      F(BOOL, HeapDestroy,  \
  48    :        (HANDLE heap))  \
  49    :      F(LPVOID, HeapAlloc,  \
  50    :        (HANDLE heap, DWORD flags, SIZE_T bytes))  \
  51    :      F(LPVOID, HeapReAlloc,  \
  52    :        (HANDLE heap, DWORD flags, LPVOID mem, SIZE_T bytes))  \
  53    :      F(BOOL, HeapFree,  \
  54    :        (HANDLE heap, DWORD flags, LPVOID mem))  \
  55    :      F(SIZE_T, HeapSize,  \
  56    :        (HANDLE heap, DWORD flags, LPCVOID mem))  \
  57    :      F(BOOL, HeapValidate,  \
  58    :        (HANDLE heap, DWORD flags, LPCVOID mem))  \
  59    :      F(SIZE_T, HeapCompact,  \
  60    :        (HANDLE heap, DWORD flags))  \
  61    :      F(BOOL, HeapLock, (HANDLE heap))  \
  62    :      F(BOOL, HeapUnlock, (HANDLE heap))  \
  63    :      F(BOOL, HeapWalk,  \
  64    :        (HANDLE heap, LPPROCESS_HEAP_ENTRY entry))  \
  65    :      F(BOOL, HeapSetInformation,  \
  66    :        (HANDLE heap, HEAP_INFORMATION_CLASS info_class,  \
  67    :         PVOID info, SIZE_T info_length))  \
  68    :      F(BOOL, HeapQueryInformation,  \
  69    :        (HANDLE heap, HEAP_INFORMATION_CLASS info_class,  \
  70    :         PVOID info, SIZE_T info_length, PSIZE_T return_length))  \
  71    :      F(void, SetCallBack,  \
  72    :        (void (*callback)(CONTEXT* context, AsanErrorInfo* error_info)))  \
  73    :  
  74    :  #define DECLARE_ASAN_FUNCTION_PTR(ret, name, args) \
  75    :      typedef ret (WINAPI* name##FunctionPtr)args;
  76    :  
  77    :  ASAN_RTL_FUNCTIONS(DECLARE_ASAN_FUNCTION_PTR)
  78    :  
  79    :  #undef DECLARE_ASAN_FUNCTION_PTR
  80    :  
  81    :  class AsanRtlTest : public testing::TestWithAsanLogger {
  82    :   public:
  83    :    AsanRtlTest() : asan_rtl_(NULL), heap_(NULL),
  84    :      memory_src_(NULL), memory_dst_(NULL),
  85  E :      memory_length_(0), memory_size_(0) {
  86  E :    }
  87    :  
  88  E :    void SetUp() OVERRIDE {
  89  E :      testing::TestWithAsanLogger::SetUp();
  90    :  
  91    :      // Load the ASAN runtime library.
  92  E :      base::FilePath asan_rtl_path = testing::GetExeRelativePath(L"asan_rtl.dll");
  93  E :      asan_rtl_ = ::LoadLibrary(asan_rtl_path.value().c_str());
  94  E :      ASSERT_TRUE(asan_rtl_ != NULL);
  95    :  
  96    :      // Load all the functions and assert that we find them.
  97    :  #define LOAD_ASAN_FUNCTION(ret, name, args)  \
  98    :      name##Function = reinterpret_cast<name##FunctionPtr>(  \
  99    :          ::GetProcAddress(asan_rtl_, "asan_" #name));  \
 100    :      ASSERT_TRUE(name##Function != NULL);
 101    :  
 102  E :      ASAN_RTL_FUNCTIONS(LOAD_ASAN_FUNCTION)
 103    :  
 104    :  #undef LOAD_ASAN_FUNCTION
 105    :  
 106  E :      heap_ = HeapCreateFunction(0, 0, 0);
 107  E :      ASSERT_TRUE(heap_ != NULL);
 108  E :    }
 109    :  
 110  E :    void TearDown() OVERRIDE {
 111  E :      if (heap_ != NULL) {
 112  E :        HeapDestroyFunction(heap_);
 113  E :        heap_ = NULL;
 114    :      }
 115    :  
 116  E :      if (asan_rtl_ != NULL) {
 117  E :        ::FreeLibrary(asan_rtl_);
 118  E :        asan_rtl_ = NULL;
 119    :      }
 120    :  
 121  E :      testing::TestWithAsanLogger::TearDown();
 122  E :    }
 123    :  
 124    :   protected:
 125    :    void AllocMemoryBuffers(int32 length, int32 element_size);
 126    :    void FreeMemoryBuffers();
 127    :  
 128    :    // The ASAN runtime module to test.
 129    :    HMODULE asan_rtl_;
 130    :  
 131    :    // Scratch heap handle valid from SetUp to TearDown.
 132    :    HANDLE heap_;
 133    :  
 134    :    // Memory buffers used to test special instructions.
 135    :    void* memory_src_;
 136    :    void* memory_dst_;
 137    :    int32 memory_length_;
 138    :    int32 memory_size_;
 139    :  
 140    :    // Declare the function pointers.
 141    :  #define DECLARE_FUNCTION_PTR_VARIABLE(ret, name, args)  \
 142    :      static name##FunctionPtr AsanRtlTest::name##Function;
 143    :  
 144    :    ASAN_RTL_FUNCTIONS(DECLARE_FUNCTION_PTR_VARIABLE)
 145    :  
 146    :  #undef DECLARE_FUNCTION_PTR_VARIABLE
 147    :  };
 148    :  
 149    :  // Define the function pointers.
 150    :  #define DEFINE_FUNCTION_PTR_VARIABLE(ret, name, args)  \
 151    :      name##FunctionPtr AsanRtlTest::name##Function;
 152    :  
 153    :    ASAN_RTL_FUNCTIONS(DEFINE_FUNCTION_PTR_VARIABLE)
 154    :  
 155    :  #undef DEFINE_FUNCTION_PTR_VARIABLE
 156    :  
 157    :  #define RTL_CAPTURE_CONTEXT(context, expected_eip) {  \
 158    :    /* Save caller save registers. */  \
 159    :    __asm push eax  \
 160    :    __asm push ecx  \
 161    :    __asm push edx  \
 162    :    /* Call Capture context. */  \
 163    :    __asm push context  \
 164    :    __asm call dword ptr[RtlCaptureContext]  \
 165    :    /* Restore caller save registers. */  \
 166    :    __asm pop edx  \
 167    :    __asm pop ecx  \
 168    :    __asm pop eax  \
 169    :    /* Restore registers which are stomped by RtlCaptureContext. */  \
 170    :    __asm push eax  \
 171    :    __asm pushfd  \
 172    :    __asm mov eax, context  \
 173    :    __asm mov dword ptr[eax + CONTEXT.Ebp], ebp  \
 174    :    __asm mov dword ptr[eax + CONTEXT.Esp], esp  \
 175    :    /* NOTE: we need to add 8 bytes because EAX + EFLAGS are on the stack. */  \
 176    :    __asm add dword ptr[eax + CONTEXT.Esp], 8  \
 177    :    __asm mov dword ptr[eax + CONTEXT.Eip], offset expected_eip  \
 178    :    __asm popfd  \
 179    :    __asm pop eax  \
 180    :  }
 181    :  
 182    :  // Check if the sections of 2 context are equals.
 183    :  // @param c1 The first context to check.
 184    :  // @param c2 The second context to check.
 185    :  // @param flags The sections to compare.
 186  E :  void ExpectEqualContexts(const CONTEXT& c1, const CONTEXT& c2, DWORD flags) {
 187  E :    if ((flags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS) {
 188  E :      EXPECT_EQ(c1.SegGs, c2.SegGs);
 189  E :      EXPECT_EQ(c1.SegFs, c2.SegFs);
 190  E :      EXPECT_EQ(c1.SegEs, c2.SegEs);
 191  E :      EXPECT_EQ(c1.SegDs, c2.SegDs);
 192    :    }
 193    :  
 194  E :    if ((flags & CONTEXT_INTEGER) == CONTEXT_INTEGER) {
 195  E :      EXPECT_EQ(c1.Edi, c2.Edi);
 196  E :      EXPECT_EQ(c1.Esi, c2.Esi);
 197  E :      EXPECT_EQ(c1.Ebx, c2.Ebx);
 198  E :      EXPECT_EQ(c1.Edx, c2.Edx);
 199  E :      EXPECT_EQ(c1.Ecx, c2.Ecx);
 200  E :      EXPECT_EQ(c1.Eax, c2.Eax);
 201    :    }
 202    :  
 203  E :    if ((flags & CONTEXT_CONTROL) == CONTEXT_CONTROL) {
 204  E :      EXPECT_EQ(c1.Ebp, c2.Ebp);
 205  E :      EXPECT_EQ(c1.Eip, c2.Eip);
 206  E :      EXPECT_EQ(c1.SegCs, c2.SegCs);
 207  E :      EXPECT_EQ(c1.EFlags, c2.EFlags);
 208  E :      EXPECT_EQ(c1.Esp, c2.Esp);
 209  E :      EXPECT_EQ(c1.SegSs, c2.SegSs);
 210    :    }
 211  E :  }
 212    :  
 213    :  void CheckAccessAndCaptureContexts(
 214  i :      CONTEXT* before, CONTEXT* after, void* location) {
 215    :    __asm {
 216  i :      pushad
 217  i :      pushfd
 218    :  
 219    :      // Avoid undefined behavior by forcing values.
 220  i :      mov eax, 0x01234567
 221  i :      mov ebx, 0x70123456
 222  i :      mov ecx, 0x12345678
 223  i :      mov edx, 0x56701234
 224  i :      mov esi, 0xCCAACCAA
 225  i :      mov edi, 0xAACCAACC
 226    :  
 227  i :      RTL_CAPTURE_CONTEXT(before, check_access_expected_eip)
 228    :  
 229    :      // Push EDX as we're required to do by the custom calling convention.
 230  i :      push edx
 231    :      // Ptr is the pointer to check.
 232  i :      mov edx, location
 233    :      // Call through.
 234  i :      call dword ptr[check_access_fn + 0]
 235    :  check_access_expected_eip:
 236    :  
 237  i :      RTL_CAPTURE_CONTEXT(after, check_access_expected_eip)
 238    :  
 239  i :      popfd
 240  i :      popad
 241    :    }
 242  i :  }
 243    :  
 244  E :  void CheckAccessAndCompareContexts(void* ptr) {
 245  E :    CONTEXT before = {};
 246  E :    CONTEXT after = {};
 247    :  
 248  E :    context_before_hook = &before;
 249  E :    CheckAccessAndCaptureContexts(&before, &after, ptr);
 250    :  
 251  E :    ExpectEqualContexts(before, after, CONTEXT_FULL);
 252    :  
 253  E :    context_before_hook = NULL;
 254  E :  }
 255    :  
 256    :  void CheckSpecialAccess(CONTEXT* before, CONTEXT* after,
 257  i :                          void* dst, void* src, int len) {
 258    :    __asm {
 259  i :      pushad
 260  i :      pushfd
 261    :  
 262    :      // Override the direction flag.
 263  i :      cld
 264  i :      cmp direction_flag_forward, 0
 265  i :      jne skip_reverse_direction
 266  i :      std
 267    :  skip_reverse_direction:
 268    :  
 269    :      // Avoid undefined behavior by forcing values.
 270  i :      mov eax, 0x01234567
 271  i :      mov ebx, 0x70123456
 272  i :      mov edx, 0x56701234
 273    :  
 274    :      // Setup registers used by the special instruction.
 275  i :      mov ecx, len
 276  i :      mov esi, src
 277  i :      mov edi, dst
 278    :  
 279  i :      RTL_CAPTURE_CONTEXT(before, special_access_expected_eip)
 280    :  
 281    :      // Call through.
 282  i :      call dword ptr[check_access_fn + 0]
 283    :  special_access_expected_eip:
 284    :  
 285  i :      RTL_CAPTURE_CONTEXT(after, special_access_expected_eip)
 286    :  
 287  i :      popfd
 288  i :      popad
 289    :    }
 290  i :  }
 291    :  
 292  E :  void CheckSpecialAccessAndCompareContexts(void* dst, void* src, int len) {
 293  E :    CONTEXT before = {};
 294  E :    CONTEXT after = {};
 295    :  
 296  E :    context_before_hook = &before;
 297    :  
 298  E :    CheckSpecialAccess(&before, &after, dst, src, len);
 299    :  
 300  E :    ExpectEqualContexts(before, after, CONTEXT_FULL);
 301    :  
 302  E :    context_before_hook = NULL;
 303  E :  }
 304    :  
 305  E :  void AsanErrorCallback(CONTEXT* context, AsanErrorInfo* error_info) {
 306    :    // TODO(sebmarchand): Stash the error info in a fixture-static variable and
 307    :    // assert on specific conditions after the fact.
 308  E :    EXPECT_TRUE(context != NULL);
 309  E :    EXPECT_TRUE(context_before_hook != NULL);
 310  E :    EXPECT_NE(HeapProxy::UNKNOWN_BAD_ACCESS, error_info->error_type);
 311    :  
 312  E :    EXPECT_EQ(expected_error_type, error_info->error_type);
 313  E :    if (error_info->error_type != HeapProxy::WILD_ACCESS) {
 314    :      // We should at least have the stack trace of the allocation of this block.
 315  E :      EXPECT_GT(error_info->alloc_stack_size, 0U);
 316  E :      EXPECT_NE(0U, error_info->alloc_tid);
 317  E :      if (error_info->error_type == HeapProxy::USE_AFTER_FREE) {
 318  E :        EXPECT_GT(error_info->free_stack_size, 0U);
 319  E :        EXPECT_NE(0U, error_info->free_tid);
 320  E :      } else {
 321  E :        EXPECT_EQ(error_info->free_stack_size, 0U);
 322  E :        EXPECT_EQ(0U, error_info->free_tid);
 323    :      }
 324    :    }
 325    :  
 326  E :    if (error_info->error_type == HeapProxy::HEAP_BUFFER_OVERFLOW) {
 327  E :      EXPECT_TRUE(strstr(error_info->shadow_info, "beyond") != NULL);
 328  E :    } else if (error_info->error_type == HeapProxy::HEAP_BUFFER_UNDERFLOW) {
 329  E :      EXPECT_TRUE(strstr(error_info->shadow_info, "before") != NULL);
 330    :    }
 331    :  
 332  E :    memory_error_detected = true;
 333    :    ExpectEqualContexts(*context_before_hook,
 334    :                        *context,
 335  E :                        CONTEXT_INTEGER | CONTEXT_CONTROL);
 336  E :  }
 337    :  
 338    :  void AsanErrorCallbackWithoutComparingContext(CONTEXT* context,
 339  E :                                                AsanErrorInfo* error_info) {
 340  E :    memory_error_detected = true;
 341  E :  }
 342    :  
 343    :  void AssertMemoryErrorIsDetected(void* ptr,
 344  E :                                   HeapProxy::BadAccessKind bad_access_type) {
 345  E :    expected_error_type = bad_access_type;
 346  E :    memory_error_detected = false;
 347  E :    CheckAccessAndCompareContexts(ptr);
 348  E :    ASSERT_TRUE(memory_error_detected);
 349  E :  }
 350    :  
 351    :  void ExpectSpecialMemoryErrorIsDetected(bool expected,
 352    :      void* dst, void* src, int32 length,
 353  E :      HeapProxy::BadAccessKind bad_access_type) {
 354  E :    DCHECK(dst != NULL);
 355  E :    DCHECK(src != NULL);
 356  E :    ASSERT_TRUE(check_access_fn != NULL);
 357  E :    expected_error_type = bad_access_type;
 358    :  
 359    :    // Setup the callback to detect invalid accesses.
 360  E :    memory_error_detected = false;
 361    :  
 362    :    // Perform memory accesses inside the range.
 363    :    ASSERT_NO_FATAL_FAILURE(
 364  E :        CheckSpecialAccessAndCompareContexts(dst, src, length));
 365    :  
 366  E :    EXPECT_EQ(expected, memory_error_detected);
 367  E :  }
 368    :  
 369    :  }  // namespace
 370    :  
 371  E :  TEST_F(AsanRtlTest, AsanCheckGoodAccess) {
 372    :    check_access_fn =
 373  E :        ::GetProcAddress(asan_rtl_, "asan_check_4_byte_read_access");
 374  E :    ASSERT_TRUE(check_access_fn != NULL);
 375    :  
 376    :    // Run through access checking an allocation that's larger than our
 377    :    // block size (8), but not a multiple thereof to exercise all paths
 378    :    // in the access check function (save for the failure path).
 379    :    uint8* mem = reinterpret_cast<uint8*>(
 380  E :        HeapAllocFunction(heap_, 0, kAllocSize));
 381  E :    ASSERT_TRUE(mem != NULL);
 382    :  
 383  E :    for (size_t i = 0; i < kAllocSize; ++i) {
 384  E :      ASSERT_NO_FATAL_FAILURE(CheckAccessAndCompareContexts(mem + i));
 385  E :    }
 386    :  
 387  E :    ASSERT_TRUE(HeapFreeFunction(heap_, 0, mem));
 388  E :  }
 389    :  
 390  E :  TEST_F(AsanRtlTest, AsanCheckHeapBufferOverflow) {
 391    :    check_access_fn =
 392  E :        ::GetProcAddress(asan_rtl_, "asan_check_4_byte_read_access");
 393  E :    ASSERT_TRUE(check_access_fn != NULL);
 394    :  
 395    :    uint8* mem = reinterpret_cast<uint8*>(
 396  E :        HeapAllocFunction(heap_, 0, kAllocSize));
 397  E :    ASSERT_TRUE(mem != NULL);
 398    :  
 399  E :    SetCallBackFunction(&AsanErrorCallback);
 400    :    AssertMemoryErrorIsDetected(mem + kAllocSize,
 401  E :                                HeapProxy::HEAP_BUFFER_OVERFLOW);
 402  E :    EXPECT_TRUE(HeapFreeFunction(heap_, 0, mem));
 403  E :    EXPECT_TRUE(LogContains("previously allocated here"));
 404  E :    EXPECT_TRUE(LogContains(HeapProxy::kHeapBufferOverFlow));
 405  E :  }
 406    :  
 407  E :  TEST_F(AsanRtlTest, AsanCheckHeapBufferUnderflow) {
 408    :    check_access_fn =
 409  E :        ::GetProcAddress(asan_rtl_, "asan_check_4_byte_read_access");
 410  E :    ASSERT_TRUE(check_access_fn != NULL);
 411    :  
 412  E :    const size_t kAllocSize = 13;
 413    :    uint8* mem = reinterpret_cast<uint8*>(
 414  E :        HeapAllocFunction(heap_, 0, kAllocSize));
 415  E :    ASSERT_TRUE(mem != NULL);
 416    :  
 417  E :    SetCallBackFunction(&AsanErrorCallback);
 418  E :    AssertMemoryErrorIsDetected(mem - 1, HeapProxy::HEAP_BUFFER_UNDERFLOW);
 419  E :    EXPECT_TRUE(HeapFreeFunction(heap_, 0, mem));
 420  E :    EXPECT_TRUE(LogContains("previously allocated here"));
 421  E :    EXPECT_TRUE(LogContains(HeapProxy::kHeapBufferUnderFlow));
 422  E :  }
 423    :  
 424  E :  TEST_F(AsanRtlTest, AsanCheckUseAfterFree) {
 425    :    check_access_fn =
 426  E :        ::GetProcAddress(asan_rtl_, "asan_check_4_byte_read_access");
 427  E :    ASSERT_TRUE(check_access_fn != NULL);
 428    :  
 429  E :    const size_t kAllocSize = 13;
 430    :    uint8* mem = reinterpret_cast<uint8*>(
 431  E :        HeapAllocFunction(heap_, 0, kAllocSize));
 432  E :    ASSERT_TRUE(mem != NULL);
 433    :  
 434  E :    SetCallBackFunction(&AsanErrorCallback);
 435  E :    EXPECT_TRUE(HeapFreeFunction(heap_, 0, mem));
 436  E :    AssertMemoryErrorIsDetected(mem, HeapProxy::USE_AFTER_FREE);
 437  E :    EXPECT_TRUE(LogContains("previously allocated here"));
 438  E :    EXPECT_TRUE(LogContains("freed here"));
 439  E :    EXPECT_TRUE(LogContains(HeapProxy::kHeapUseAfterFree));
 440  E :  }
 441    :  
 442  E :  TEST_F(AsanRtlTest, AsanCheckDoubleFree) {
 443    :    check_access_fn =
 444  E :        ::GetProcAddress(asan_rtl_, "asan_check_4_byte_read_access");
 445  E :    ASSERT_TRUE(check_access_fn != NULL);
 446    :  
 447  E :    const size_t kAllocSize = 13;
 448    :    uint8* mem = reinterpret_cast<uint8*>(
 449  E :        HeapAllocFunction(heap_, 0, kAllocSize));
 450  E :    ASSERT_TRUE(mem != NULL);
 451    :  
 452  E :    CONTEXT context_before_error = {};
 453  E :    context_before_hook = &context_before_error;
 454  E :    SetCallBackFunction(&AsanErrorCallbackWithoutComparingContext);
 455  E :    EXPECT_TRUE(HeapFreeFunction(heap_, 0, mem));
 456  E :    EXPECT_FALSE(HeapFreeFunction(heap_, 0, mem));
 457  E :    EXPECT_TRUE(memory_error_detected);
 458  E :    EXPECT_TRUE(LogContains(HeapProxy::kAttemptingDoubleFree));
 459  E :    EXPECT_TRUE(LogContains("previously allocated here"));
 460  E :    EXPECT_TRUE(LogContains("freed here"));
 461  E :  }
 462    :  
 463  E :  TEST_F(AsanRtlTest, AsanCheckWildAccess) {
 464    :    check_access_fn =
 465  E :        ::GetProcAddress(asan_rtl_, "asan_check_4_byte_read_access");
 466  E :    ASSERT_TRUE(check_access_fn != NULL);
 467    :  
 468  E :    SetCallBackFunction(&AsanErrorCallback);
 469    :    AssertMemoryErrorIsDetected(reinterpret_cast<void*>(0x80000000),
 470  E :                                HeapProxy::WILD_ACCESS);
 471  E :    EXPECT_TRUE(LogContains(HeapProxy::kWildAccess));
 472  E :  }
 473    :  
 474  E :  void AsanRtlTest::AllocMemoryBuffers(int32 length, int32 element_size) {
 475  E :    DCHECK(memory_src_ == NULL);
 476  E :    DCHECK(memory_dst_ == NULL);
 477  E :    DCHECK(memory_length_ == 0);
 478  E :    DCHECK(memory_size_ == 0);
 479    :  
 480    :    // Keep track of memory size.
 481  E :    memory_length_ = length;
 482  E :    memory_size_ = length * element_size;
 483    :  
 484    :    // Allocate memory space.
 485  E :    memory_src_ = HeapAllocFunction(heap_, 0, memory_size_);
 486  E :    ASSERT_TRUE(memory_src_ != NULL);
 487  E :    memory_dst_ = HeapAllocFunction(heap_, 0, memory_size_);
 488  E :    ASSERT_TRUE(memory_dst_ != NULL);
 489    :  
 490    :    // Initialize memory.
 491  E :    memset(memory_src_, 0, memory_size_);
 492  E :    memset(memory_dst_, 0, memory_size_);
 493  E :  }
 494    :  
 495  E :  void AsanRtlTest::FreeMemoryBuffers() {
 496  E :    DCHECK(memory_src_ != NULL);
 497  E :    DCHECK(memory_dst_ != NULL);
 498    :  
 499  E :    ASSERT_TRUE(HeapFreeFunction(heap_, 0, memory_src_));
 500  E :    ASSERT_TRUE(HeapFreeFunction(heap_, 0, memory_dst_));
 501    :  
 502  E :    memory_length_ = 0;
 503  E :    memory_size_ = 0;
 504  E :    memory_src_ = NULL;
 505  E :    memory_dst_ = NULL;
 506  E :  }
 507    :  
 508  E :  TEST_F(AsanRtlTest, AsanSingleSpecial1byteInstructionCheckGoodAccess) {
 509    :    static const char* function_names[] = {
 510    :        "asan_check_1_byte_movs_access",
 511    :        "asan_check_1_byte_cmps_access",
 512    :        "asan_check_1_byte_stos_access"
 513    :    };
 514    :  
 515    :    // Setup the callback to detect invalid accesses.
 516  E :    SetCallBackFunction(&AsanErrorCallback);
 517    :  
 518    :    // Allocate memory space.
 519  E :    AllocMemoryBuffers(kAllocSize, sizeof(uint8));
 520  E :    uint8* src = reinterpret_cast<uint8*>(memory_src_);
 521  E :    uint8* dst = reinterpret_cast<uint8*>(memory_dst_);
 522    :  
 523    :    // Validate memory accesses.
 524  E :    for (int32 function = 0; function < arraysize(function_names); ++function) {
 525    :      check_access_fn =
 526  E :          ::GetProcAddress(asan_rtl_, function_names[function]);
 527  E :      ASSERT_TRUE(check_access_fn != NULL);
 528    :  
 529  E :      for (int32 i = 0; i < memory_length_; ++i)
 530    :        ExpectSpecialMemoryErrorIsDetected(false, &dst[i], &src[i], 0xDEADDEAD,
 531  E :                                           HeapProxy::UNKNOWN_BAD_ACCESS);
 532  E :    }
 533    :  
 534  E :    FreeMemoryBuffers();
 535  E :  }
 536    :  
 537  E :  TEST_F(AsanRtlTest, AsanSingleSpecial2byteInstructionCheckGoodAccess) {
 538    :    static const char* function_names[] = {
 539    :        "asan_check_2_byte_movs_access",
 540    :        "asan_check_2_byte_cmps_access",
 541    :        "asan_check_2_byte_stos_access"
 542    :    };
 543    :  
 544    :    // Setup the callback to detect invalid accesses.
 545  E :    SetCallBackFunction(&AsanErrorCallback);
 546    :  
 547    :    // Allocate memory space.
 548  E :    AllocMemoryBuffers(kAllocSize, sizeof(uint16));
 549  E :    uint16* src = reinterpret_cast<uint16*>(memory_src_);
 550  E :    uint16* dst = reinterpret_cast<uint16*>(memory_dst_);
 551    :  
 552    :    // Validate memory accesses.
 553  E :    for (int32 function = 0; function < arraysize(function_names); ++function) {
 554    :      check_access_fn =
 555  E :          ::GetProcAddress(asan_rtl_, function_names[function]);
 556  E :      ASSERT_TRUE(check_access_fn != NULL);
 557    :  
 558  E :      for (int32 i = 0; i < memory_length_; ++i)
 559    :        ExpectSpecialMemoryErrorIsDetected(false, &dst[i], &src[i], 0xDEADDEAD,
 560  E :                                           HeapProxy::UNKNOWN_BAD_ACCESS);
 561  E :    }
 562    :  
 563  E :    FreeMemoryBuffers();
 564  E :  }
 565    :  
 566  E :  TEST_F(AsanRtlTest, AsanSingleSpecial4byteInstructionCheckGoodAccess) {
 567    :    static const char* function_names[] = {
 568    :        "asan_check_4_byte_movs_access",
 569    :        "asan_check_4_byte_cmps_access",
 570    :        "asan_check_4_byte_stos_access"
 571    :    };
 572    :  
 573    :    // Setup the callback to detect invalid accesses.
 574  E :    SetCallBackFunction(&AsanErrorCallback);
 575    :  
 576    :    // Allocate memory space.
 577  E :    AllocMemoryBuffers(kAllocSize, sizeof(uint32));
 578  E :    uint32* src = reinterpret_cast<uint32*>(memory_src_);
 579  E :    uint32* dst = reinterpret_cast<uint32*>(memory_dst_);
 580    :  
 581    :    // Validate memory accesses.
 582  E :    for (int32 function = 0; function < arraysize(function_names); ++function) {
 583    :      check_access_fn =
 584  E :          ::GetProcAddress(asan_rtl_, function_names[function]);
 585  E :      ASSERT_TRUE(check_access_fn != NULL);
 586    :  
 587  E :      for (int32 i = 0; i < memory_length_; ++i)
 588    :        ExpectSpecialMemoryErrorIsDetected(false, &dst[i], &src[i], 0xDEADDEAD,
 589  E :                                           HeapProxy::UNKNOWN_BAD_ACCESS);
 590  E :    }
 591    :  
 592  E :    FreeMemoryBuffers();
 593  E :  }
 594    :  
 595  E :  TEST_F(AsanRtlTest, AsanSingleSpecialInstructionCheckBadAccess) {
 596    :    static const char* function_names[] = {
 597    :        "asan_check_1_byte_movs_access",
 598    :        "asan_check_1_byte_cmps_access",
 599    :        "asan_check_2_byte_movs_access",
 600    :        "asan_check_2_byte_cmps_access",
 601    :        "asan_check_4_byte_movs_access",
 602    :        "asan_check_4_byte_cmps_access"
 603    :    };
 604    :  
 605    :    // Setup the callback to detect invalid accesses.
 606  E :    SetCallBackFunction(&AsanErrorCallback);
 607    :  
 608    :    // Allocate memory space.
 609  E :    AllocMemoryBuffers(kAllocSize, sizeof(uint32));
 610  E :    uint32* src = reinterpret_cast<uint32*>(memory_src_);
 611  E :    uint32* dst = reinterpret_cast<uint32*>(memory_dst_);
 612    :  
 613    :    // Validate memory accesses.
 614  E :    for (int32 function = 0; function < arraysize(function_names); ++function) {
 615    :      check_access_fn =
 616  E :          ::GetProcAddress(asan_rtl_, function_names[function]);
 617  E :      ASSERT_TRUE(check_access_fn != NULL);
 618    :  
 619    :      ExpectSpecialMemoryErrorIsDetected(true, &dst[0], &src[-1], 0xDEADDEAD,
 620  E :                                         HeapProxy::HEAP_BUFFER_UNDERFLOW);
 621    :      ExpectSpecialMemoryErrorIsDetected(true, &dst[-1], &src[0], 0xDEADDEAD,
 622  E :                                         HeapProxy::HEAP_BUFFER_UNDERFLOW);
 623    :  
 624    :      ExpectSpecialMemoryErrorIsDetected(true, &dst[0], &src[memory_length_],
 625  E :          0xDEADDEAD, HeapProxy::HEAP_BUFFER_OVERFLOW);
 626    :      ExpectSpecialMemoryErrorIsDetected(true, &dst[memory_length_], &src[0],
 627  E :          0xDEADDEAD, HeapProxy::HEAP_BUFFER_OVERFLOW);
 628  E :    }
 629    :  
 630  E :    FreeMemoryBuffers();
 631  E :  }
 632    :  
 633  E :  TEST_F(AsanRtlTest, AsanSingleStoInstructionCheckBadAccess) {
 634    :    static const char* function_names[] = {
 635    :        "asan_check_1_byte_stos_access",
 636    :        "asan_check_2_byte_stos_access",
 637    :        "asan_check_4_byte_stos_access"
 638    :    };
 639    :  
 640    :    // Setup the callback to detect invalid accesses.
 641  E :    SetCallBackFunction(&AsanErrorCallback);
 642    :  
 643    :    // Allocate memory space.
 644  E :    AllocMemoryBuffers(kAllocSize, sizeof(uint32));
 645  E :    uint32* src = reinterpret_cast<uint32*>(memory_src_);
 646  E :    uint32* dst = reinterpret_cast<uint32*>(memory_dst_);
 647    :  
 648    :    // Validate memory accesses.
 649  E :    for (int32 function = 0; function < arraysize(function_names); ++function) {
 650    :      check_access_fn =
 651  E :          ::GetProcAddress(asan_rtl_, function_names[function]);
 652  E :      ASSERT_TRUE(check_access_fn != NULL);
 653    :  
 654    :      ExpectSpecialMemoryErrorIsDetected(false, &dst[0], &src[-1], 0xDEAD,
 655  E :          HeapProxy::HEAP_BUFFER_UNDERFLOW);
 656    :      ExpectSpecialMemoryErrorIsDetected(true, &dst[-1], &src[0], 0xDEAD,
 657  E :          HeapProxy::HEAP_BUFFER_UNDERFLOW);
 658    :  
 659    :      ExpectSpecialMemoryErrorIsDetected(false, &dst[0], &src[memory_length_],
 660  E :          0xDEADDEAD, HeapProxy::HEAP_BUFFER_OVERFLOW);
 661    :      ExpectSpecialMemoryErrorIsDetected(true, &dst[memory_length_], &src[0],
 662  E :          0xDEADDEAD, HeapProxy::HEAP_BUFFER_OVERFLOW);
 663  E :    }
 664    :  
 665  E :    FreeMemoryBuffers();
 666  E :  }
 667    :  
 668  E :  TEST_F(AsanRtlTest, AsanPrefixedSpecialInstructionCheckGoodAccess) {
 669    :    static const char* function_names[] = {
 670    :        "asan_check_repz_4_byte_movs_access",
 671    :        "asan_check_repz_4_byte_cmps_access",
 672    :        "asan_check_repz_4_byte_stos_access"
 673    :    };
 674    :  
 675    :    // Setup the callback to detect invalid accesses.
 676  E :    SetCallBackFunction(&AsanErrorCallback);
 677    :  
 678    :    // Allocate memory space.
 679  E :    AllocMemoryBuffers(kAllocSize, sizeof(uint32));
 680  E :    uint32* src = reinterpret_cast<uint32*>(memory_src_);
 681  E :    uint32* dst = reinterpret_cast<uint32*>(memory_dst_);
 682    :  
 683    :    // Validate memory accesses.
 684  E :    for (int32 function = 0; function < arraysize(function_names); ++function) {
 685    :      check_access_fn =
 686  E :          ::GetProcAddress(asan_rtl_, function_names[function]);
 687  E :      ASSERT_TRUE(check_access_fn != NULL);
 688    :  
 689    :      ExpectSpecialMemoryErrorIsDetected(false, &dst[0], &src[0], memory_length_,
 690  E :                                         HeapProxy::UNKNOWN_BAD_ACCESS);
 691  E :    }
 692    :  
 693  E :    FreeMemoryBuffers();
 694  E :  }
 695    :  
 696  E :  TEST_F(AsanRtlTest, AsanPrefixedSpecialInstructionCheckBadAccess) {
 697    :    static const char* function_names[] = {
 698    :        "asan_check_repz_4_byte_movs_access",
 699    :        "asan_check_repz_4_byte_cmps_access",
 700    :        "asan_check_repz_4_byte_stos_access"
 701    :    };
 702    :  
 703    :    // Setup the callback to detect invalid accesses.
 704  E :    SetCallBackFunction(&AsanErrorCallback);
 705    :  
 706    :    // Allocate memory space.
 707  E :    AllocMemoryBuffers(kAllocSize, sizeof(uint32));
 708  E :    uint32* src = reinterpret_cast<uint32*>(memory_src_);
 709  E :    uint32* dst = reinterpret_cast<uint32*>(memory_dst_);
 710    :  
 711    :    // Validate memory accesses.
 712  E :    for (int32 function = 0; function < arraysize(function_names); ++function) {
 713    :      check_access_fn =
 714  E :          ::GetProcAddress(asan_rtl_, function_names[function]);
 715  E :      ASSERT_TRUE(check_access_fn != NULL);
 716    :  
 717    :      ExpectSpecialMemoryErrorIsDetected(true, &dst[0], &src[0],
 718  E :          memory_length_ + 1, HeapProxy::HEAP_BUFFER_OVERFLOW);
 719    :      ExpectSpecialMemoryErrorIsDetected(true, &dst[-1], &src[-1],
 720  E :          memory_length_, HeapProxy::HEAP_BUFFER_UNDERFLOW);
 721    :      ExpectSpecialMemoryErrorIsDetected(true, &dst[-1], &src[0],
 722  E :          memory_length_, HeapProxy::HEAP_BUFFER_UNDERFLOW);
 723  E :    }
 724    :  
 725  E :    FreeMemoryBuffers();
 726  E :  }
 727    :  
 728  E :  TEST_F(AsanRtlTest, AsanDirectionSpecialInstructionCheckGoodAccess) {
 729    :    static const char* function_names[] = {
 730    :        "asan_check_repz_4_byte_movs_access",
 731    :        "asan_check_repz_4_byte_cmps_access",
 732    :        "asan_check_repz_4_byte_stos_access"
 733    :    };
 734    :  
 735    :    // Setup the callback to detect invalid accesses.
 736  E :    SetCallBackFunction(&AsanErrorCallback);
 737    :  
 738    :    // Force direction flag to backward.
 739  E :    direction_flag_forward = false;
 740    :  
 741    :    // Allocate memory space.
 742  E :    AllocMemoryBuffers(kAllocSize, sizeof(uint32));
 743  E :    uint32* src = reinterpret_cast<uint32*>(memory_src_);
 744  E :    uint32* dst = reinterpret_cast<uint32*>(memory_dst_);
 745    :  
 746    :    // Validate memory accesses.
 747  E :    for (int32 function = 0; function < arraysize(function_names); ++function) {
 748    :      check_access_fn =
 749  E :          ::GetProcAddress(asan_rtl_, function_names[function]);
 750  E :      ASSERT_TRUE(check_access_fn != NULL);
 751    :  
 752    :      ExpectSpecialMemoryErrorIsDetected(false, &dst[memory_length_ - 1],
 753    :          &src[memory_length_ - 1], memory_length_,
 754  E :          HeapProxy::UNKNOWN_BAD_ACCESS);
 755  E :    }
 756    :  
 757    :    // Reset direction flag to forward.
 758  E :    direction_flag_forward = true;
 759    :  
 760  E :    FreeMemoryBuffers();
 761  E :  }
 762    :  
 763  E :  TEST_F(AsanRtlTest, AsanSpecialInstructionCheckZeroAccess) {
 764    :    static const char* function_names[] = {
 765    :        "asan_check_repz_1_byte_movs_access",
 766    :        "asan_check_repz_1_byte_cmps_access",
 767    :        "asan_check_repz_1_byte_stos_access",
 768    :        "asan_check_repz_2_byte_movs_access",
 769    :        "asan_check_repz_2_byte_cmps_access",
 770    :        "asan_check_repz_2_byte_stos_access",
 771    :        "asan_check_repz_4_byte_movs_access",
 772    :        "asan_check_repz_4_byte_cmps_access",
 773    :        "asan_check_repz_4_byte_stos_access"
 774    :    };
 775    :  
 776    :    // Setup the callback to detect invalid accesses.
 777  E :    SetCallBackFunction(&AsanErrorCallback);
 778    :  
 779    :    // Allocate memory space.
 780  E :    AllocMemoryBuffers(kAllocSize, sizeof(uint32));
 781  E :    uint32* src = reinterpret_cast<uint32*>(memory_src_);
 782  E :    uint32* dst = reinterpret_cast<uint32*>(memory_dst_);
 783    :  
 784    :    // Validate memory accesses.
 785  E :    for (int32 function = 0; function < arraysize(function_names); ++function) {
 786    :      check_access_fn =
 787  E :          ::GetProcAddress(asan_rtl_, function_names[function]);
 788  E :      ASSERT_TRUE(check_access_fn != NULL);
 789    :  
 790    :      // A prefixed instruction with a count of zero do not have side effects.
 791    :      ExpectSpecialMemoryErrorIsDetected(false, &dst[-1], &src[-1], 0,
 792  E :                                         HeapProxy::UNKNOWN_BAD_ACCESS);
 793  E :    }
 794    :  
 795  E :    FreeMemoryBuffers();
 796  E :  }
 797    :  
 798  E :  TEST_F(AsanRtlTest, AsanSpecialInstructionCheckShortcutAccess) {
 799    :    static const char* function_names[] = {
 800    :        "asan_check_repz_1_byte_cmps_access",
 801    :        "asan_check_repz_2_byte_cmps_access",
 802    :        "asan_check_repz_4_byte_cmps_access",
 803    :    };
 804    :  
 805    :    // Setup the callback to detect invalid accesses.
 806  E :    SetCallBackFunction(&AsanErrorCallback);
 807    :  
 808    :    // Allocate memory space.
 809  E :    AllocMemoryBuffers(kAllocSize, sizeof(uint32));
 810  E :    uint32* src = reinterpret_cast<uint32*>(memory_src_);
 811  E :    uint32* dst = reinterpret_cast<uint32*>(memory_dst_);
 812    :  
 813  E :    src[1] = 0x12345667;
 814    :  
 815    :    // Validate memory accesses.
 816  E :    for (int32 function = 0; function < arraysize(function_names); ++function) {
 817    :      check_access_fn =
 818  E :          ::GetProcAddress(asan_rtl_, function_names[function]);
 819  E :      ASSERT_TRUE(check_access_fn != NULL);
 820    :  
 821    :      // Compare instruction stop their execution when values differ.
 822    :      ExpectSpecialMemoryErrorIsDetected(false, &dst[0], &src[0],
 823  E :          memory_length_ + 1, HeapProxy::UNKNOWN_BAD_ACCESS);
 824  E :    }
 825    :  
 826  E :    FreeMemoryBuffers();
 827  E :  }
 828    :  
 829    :  } // namespace asan
 830    :  } // namespace agent

Coverage information generated Thu Jul 04 09:34:53 2013.