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

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
82.3%3444180.C++source

Line-by-line coverage:

   1    :  // Copyright 2012 Google Inc. All Rights Reserved.
   2    :  //
   3    :  // Licensed under the Apache License, Version 2.0 (the "License");
   4    :  // you may not use this file except in compliance with the License.
   5    :  // You may obtain a copy of the License at
   6    :  //
   7    :  //     http://www.apache.org/licenses/LICENSE-2.0
   8    :  //
   9    :  // Unless required by applicable law or agreed to in writing, software
  10    :  // distributed under the License is distributed on an "AS IS" BASIS,
  11    :  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12    :  // See the License for the specific language governing permissions and
  13    :  // limitations under the License.
  14    :  
  15    :  #include "syzygy/agent/asan/asan_rtl_impl.h"
  16    :  
  17    :  #include "base/bind.h"
  18    :  #include "base/callback.h"
  19    :  #include "base/logging.h"
  20    :  #include "base/debug/alias.h"
  21    :  #include "syzygy/agent/asan/asan_heap.h"
  22    :  #include "syzygy/agent/asan/asan_runtime.h"
  23    :  #include "syzygy/agent/asan/asan_shadow.h"
  24    :  #include "syzygy/agent/asan/stack_capture.h"
  25    :  #include "syzygy/agent/common/scoped_last_error_keeper.h"
  26    :  
  27    :  namespace {
  28    :  
  29    :  using agent::asan::AsanErrorInfo;
  30    :  using agent::asan::AsanRuntime;
  31    :  using agent::asan::HeapProxy;
  32    :  
  33    :  HANDLE process_heap = NULL;
  34    :  
  35    :  // The asan runtime manager.
  36    :  AsanRuntime* asan_runtime = NULL;
  37    :  
  38    :  // A callback that will be used in the functions interceptors once the call
  39    :  // to the intercepted function has been done. This is for testing purposes
  40    :  // only.
  41    :  InterceptorTailCallback interceptor_tail_callback = NULL;
  42    :  
  43    :  }  // namespace
  44    :  
  45    :  namespace agent {
  46    :  namespace asan {
  47    :  
  48  E :  void SetUpRtl(AsanRuntime* runtime) {
  49  E :    DCHECK(runtime != NULL);
  50  E :    asan_runtime = runtime;
  51  E :    process_heap = GetProcessHeap();
  52  E :  }
  53    :  
  54  E :  void TearDownRtl() {
  55  E :    process_heap = NULL;
  56  E :  }
  57    :  
  58    :  // Contents of the registers before calling the ASAN memory check function.
  59    :  #pragma pack(push, 1)
  60    :  struct AsanContext {
  61    :    DWORD original_edi;
  62    :    DWORD original_esi;
  63    :    DWORD original_ebp;
  64    :    DWORD original_esp;
  65    :    DWORD original_ebx;
  66    :    DWORD original_edx;
  67    :    DWORD original_ecx;
  68    :    DWORD original_eax;
  69    :    DWORD original_eflags;
  70    :    DWORD original_eip;
  71    :  };
  72    :  #pragma pack(pop)
  73    :  
  74    :  // Report a bad access to the memory.
  75    :  // @param location The memory address of the access.
  76    :  // @param access_mode The mode of the access.
  77    :  // @param access_size The size of the access.
  78    :  // @param asan_context The context of the access.
  79    :  void ReportBadMemoryAccess(void* location,
  80    :                             HeapProxy::AccessMode access_mode,
  81    :                             size_t access_size,
  82  E :                             struct AsanContext* asan_context) {
  83    :    // Capture the context and restore the value of the register as before calling
  84    :    // the asan hook.
  85    :  
  86    :    // Save the last error value so this function will be able to restore it.
  87  E :    agent::common::ScopedLastErrorKeeper scoped_last_error_keeper;
  88    :  
  89    :    // We keep a structure with all the useful information about this bad access
  90    :    // on the stack.
  91  E :    AsanErrorInfo bad_access_info = {};
  92    :  
  93    :    // We need to call ::RtlCaptureContext if we want SegSS and SegCS to be
  94    :    // properly set.
  95  E :    ::RtlCaptureContext(&bad_access_info.context);
  96  E :    bad_access_info.context.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL;
  97    :  
  98    :    // Restore the original value of the registers.
  99  E :    bad_access_info.context.Eip = asan_context->original_eip;
 100  E :    bad_access_info.context.Eax = asan_context->original_eax;
 101  E :    bad_access_info.context.Ecx = asan_context->original_ecx;
 102  E :    bad_access_info.context.Edx = asan_context->original_edx;
 103  E :    bad_access_info.context.Ebx = asan_context->original_ebx;
 104  E :    bad_access_info.context.Ebp = asan_context->original_ebp;
 105  E :    bad_access_info.context.Esp = asan_context->original_esp;
 106  E :    bad_access_info.context.Esi = asan_context->original_esi;
 107  E :    bad_access_info.context.Edi = asan_context->original_edi;
 108  E :    bad_access_info.context.EFlags = asan_context->original_eflags;
 109    :  
 110  E :    StackCapture stack;
 111  E :    stack.InitFromStack();
 112    :    // We need to compute a relative stack id so that for the same stack trace
 113    :    // we'll get the same value every time even if the modules are loaded at a
 114    :    // different base address.
 115  E :    stack.set_stack_id(stack.ComputeRelativeStackId());
 116    :  
 117    :    // Check if we can ignore this error.
 118  E :    if (asan_runtime->ShouldIgnoreError(stack.stack_id()))
 119  i :      return;
 120    :  
 121  E :    bad_access_info.crash_stack_id = stack.stack_id();
 122  E :    bad_access_info.location = location;
 123  E :    bad_access_info.access_mode = access_mode;
 124  E :    bad_access_info.access_size = access_size;
 125  E :    bad_access_info.alloc_stack_size = 0U;
 126  E :    bad_access_info.alloc_tid = 0U;
 127  E :    bad_access_info.error_type = HeapProxy::UNKNOWN_BAD_ACCESS;
 128  E :    bad_access_info.free_stack_size = 0U;
 129  E :    bad_access_info.free_tid = 0U;
 130  E :    bad_access_info.microseconds_since_free = 0U;
 131    :  
 132    :    // Make sure this structure is not optimized out.
 133  E :    base::debug::Alias(&bad_access_info);
 134    :  
 135  E :    asan_runtime->GetBadAccessInformation(&bad_access_info);
 136    :  
 137    :    // Report this error.
 138  E :    asan_runtime->OnError(&bad_access_info);
 139  E :  }
 140    :  
 141    :  // Check if the memory location is accessible and report an error on bad memory
 142    :  // accesses.
 143    :  // @param location The memory address of the access.
 144    :  // @param access_mode The mode of the access.
 145    :  // @param access_size The size of the access.
 146    :  // @param context The registers context of the access.
 147    :  void CheckMemoryAccess(void* location,
 148    :                         HeapProxy::AccessMode access_mode,
 149    :                         size_t access_size,
 150  E :                         AsanContext* context) {
 151  E :    if (!agent::asan::Shadow::IsAccessible(location))
 152  E :      ReportBadMemoryAccess(location, access_mode, access_size, context);
 153  E :  }
 154    :  
 155    :  // Check if the memory accesses done by a string instructions are valid.
 156    :  // @param dst The destination memory address of the access.
 157    :  // @param dst_access_mode The destination mode of the access.
 158    :  // @param src The source memory address of the access.
 159    :  // @param src_access_mode The source mode of the access.
 160    :  // @param length The number of memory accesses.
 161    :  // @param access_size The size of each the access in byte.
 162    :  // @param increment The increment to move dst/src after each access.
 163    :  // @param compare Flag to activate shortcut of the execution on difference.
 164    :  // @param context The registers context of the access.
 165    :  void CheckStringsMemoryAccesses(
 166    :      uint8* dst, HeapProxy::AccessMode dst_access_mode,
 167    :      uint8* src, HeapProxy::AccessMode src_access_mode,
 168    :      uint32 length, size_t access_size, int32 increment, bool compare,
 169  E :      AsanContext* context) {
 170  E :    int32 offset = 0;
 171    :  
 172  E :    for (uint32 i = 0; i < length; ++i) {
 173    :      // Check next memory location at src[offset].
 174  E :      if (src_access_mode != HeapProxy::ASAN_UNKNOWN_ACCESS)
 175  E :        CheckMemoryAccess(&src[offset], src_access_mode, access_size, context);
 176    :  
 177    :      // Check next memory location at dst[offset].
 178  E :      if (dst_access_mode != HeapProxy::ASAN_UNKNOWN_ACCESS)
 179  E :        CheckMemoryAccess(&dst[offset], dst_access_mode, access_size, context);
 180    :  
 181    :      // For CMPS instructions, we shortcut the execution of prefix REPZ when
 182    :      // memory contents differ.
 183  E :      if (compare) {
 184  E :        uint32 src_content = 0;
 185  E :        uint32 dst_content = 0;
 186  E :        switch (access_size) {
 187    :        case 4:
 188  E :          src_content = *reinterpret_cast<uint32*>(&src[offset]);
 189  E :          dst_content = *reinterpret_cast<uint32*>(&dst[offset]);
 190  E :          break;
 191    :        case 2:
 192  E :          src_content = *reinterpret_cast<uint16*>(&src[offset]);
 193  E :          dst_content = *reinterpret_cast<uint16*>(&dst[offset]);
 194  E :          break;
 195    :        case 1:
 196  E :          src_content = *reinterpret_cast<uint8*>(&src[offset]);
 197  E :          dst_content = *reinterpret_cast<uint8*>(&dst[offset]);
 198  E :          break;
 199    :        default:
 200  i :          NOTREACHED() << "Unexpected access_size.";
 201    :          break;
 202    :        }
 203    :  
 204  E :        if (src_content != dst_content)
 205  E :          return;
 206    :      }
 207    :  
 208    :      // Increments offset of dst/src to the next memory location.
 209  E :      offset += increment;
 210  E :    }
 211  E :  }
 212    :  
 213    :  }  // namespace asan
 214    :  }  // namespace agent
 215    :  
 216    :  // This is a trick for efficient saving/restoring part of the flags register.
 217    :  // see http://blog.freearrow.com/archives/396
 218    :  // Flags (bits 16-31) probably need a pipeline flush on update (POPFD). Thus,
 219    :  // using LAHF/SAHF instead gives better performance.
 220    :  //   PUSHFD/POPFD: 23.314684 ticks
 221    :  //   LAHF/SAHF:     8.838665 ticks
 222    :  
 223    :  // This macro starts by saving EAX onto the stack and then loads the value of
 224    :  // the flags into it.
 225    :  #define ASAN_SAVE_EFLAGS  \
 226    :      __asm push eax  \
 227    :      __asm lahf  \
 228    :      __asm seto al
 229    :  
 230    :  // This macro restores the flags, their previous value is assumed to be in EAX
 231    :  // and we expect to have the previous value of EAX on the top of the stack.
 232    :  // AL is set to 1 if the overflow flag was set before the call to our hook, 0
 233    :  // otherwise. We add 0x7f to it so it'll restore the flag. Then we restore the
 234    :  // low bytes of the flags and EAX.
 235    :  #define ASAN_RESTORE_EFLAGS  \
 236    :      __asm add al, 0x7f  \
 237    :      __asm sahf  \
 238    :      __asm pop eax
 239    :  
 240    :  // This is the common part of the fast path shared between the different
 241    :  // implementations of the hooks, this does the following:
 242    :  //     - Saves the memory location in EDX for the slow path.
 243    :  //     - Checks if the address we're trying to access is signed, if so this mean
 244    :  //         that this is an access to the upper region of the memory (over the
 245    :  //         2GB limit) and we should report this as an invalid wild access.
 246    :  //     - Checks for zero shadow for this memory location. We use the cmp
 247    :  //         instruction so it'll set the sign flag if the upper bit of the shadow
 248    :  //         value of this memory location is set to 1.
 249    :  //     - If the shadow byte is not equal to zero then it jumps to the slow path.
 250    :  //     - Otherwise it removes the memory location from the top of the stack.
 251    :  #define ASAN_FAST_PATH  \
 252    :      __asm push edx  \
 253    :      __asm sar edx, 3  \
 254    :      __asm js report_failure  \
 255    :      __asm movzx edx, BYTE PTR[edx + agent::asan::Shadow::shadow_]  \
 256    :      __asm cmp dl, 0  \
 257    :      __asm jnz check_access_slow  \
 258    :      __asm add esp, 4
 259    :  
 260    :  // This is the common part of the slow path shared between the different
 261    :  // implementations of the hooks. The memory location is expected to be on top of
 262    :  // the stack and the shadow value for it is assumed to be in DL at this point.
 263    :  // This also relies on the fact that the shadow non accessible byte mask has its
 264    :  // upper bit set to 1 and that we jump to this macro after doing a
 265    :  // "cmp shadow_byte, 0", so the sign flag would be set to 1 if the value isn't
 266    :  // accessible.
 267    :  // We inline the Shadow::IsAccessible function for performance reasons.
 268    :  // This function does the following:
 269    :  //     - Checks if this byte is accessible and jump to the error path if it's
 270    :  //       not.
 271    :  //     - Removes the memory location from the top of the stack.
 272    :  #define ASAN_SLOW_PATH  \
 273    :      __asm js report_failure  \
 274    :      __asm mov dh, BYTE PTR[esp]  \
 275    :      __asm and dh, 7  \
 276    :      __asm cmp dh, dl  \
 277    :      __asm jae report_failure  \
 278    :      __asm add esp, 4
 279    :  
 280    :  // This is the error path. It expects to have the previous value of EDX at
 281    :  // [ESP + 4] and the address of the faulty instruction at [ESP].
 282    :  // This macro take cares of saving and restoring the flags.
 283    :  #define ASAN_ERROR_PATH(access_size, access_mode_value)  \
 284    :      /* Restore original value of EDX, and put memory location on stack. */  \
 285    :      __asm xchg edx, DWORD PTR[esp + 4]  \
 286    :      /* Create an ASAN registers context on the stack. */  \
 287    :      __asm pushfd  \
 288    :      __asm pushad  \
 289    :      /* Fix the original value of ESP in the ASAN registers context. */  \
 290    :      /* Removing 12 bytes (e.g. EFLAGS / EIP / Original EDX). */  \
 291    :      __asm add DWORD PTR[esp + 12], 12  \
 292    :      /* Push ARG4: the address of ASAN context on stack. */  \
 293    :      __asm push esp  \
 294    :      /* Push ARG3: the access size. */  \
 295    :      __asm push access_size  \
 296    :      /* Push ARG2: the access type. */  \
 297    :      __asm push access_mode_value  \
 298    :      /* Push ARG1: the memory location. */  \
 299    :      __asm push DWORD PTR[esp + 52]  \
 300    :      __asm call agent::asan::ReportBadMemoryAccess  \
 301    :      /* Remove 4 x ARG on stack. */  \
 302    :      __asm add esp, 16  \
 303    :      /* Restore original registers. */  \
 304    :      __asm popad  \
 305    :      __asm popfd  \
 306    :      /* Return and remove memory location on stack. */  \
 307    :      __asm ret 4
 308    :  
 309    :  // Generates the asan check access functions. The name of the generated method
 310    :  // will be asan_check_(@p access_size)_byte_(@p access_mode_str)().
 311    :  // @param access_size The size of the access (in byte).
 312    :  // @param access_mode_str The string representing the access mode (read_access
 313    :  //     or write_access).
 314    :  // @param access_mode_value The internal value representing this kind of access.
 315    :  // @note Calling this function doesn't alter any register.
 316    :  #define ASAN_CHECK_FUNCTION(access_size, access_mode_str, access_mode_value)  \
 317    :    extern "C" __declspec(naked)  \
 318    :        void asan_check_ ## access_size ## _byte_ ## access_mode_str ## () {  \
 319    :      __asm {  \
 320    :        /* Save the EFLAGS. */  \
 321    :        ASAN_SAVE_EFLAGS  \
 322    :        ASAN_FAST_PATH  \
 323    :        /* Restore original EDX. */  \
 324    :        __asm mov edx, DWORD PTR[esp + 8]  \
 325    :        /* Restore the EFLAGS. */  \
 326    :        ASAN_RESTORE_EFLAGS  \
 327    :        __asm ret 4  \
 328    :      __asm check_access_slow:  \
 329    :        ASAN_SLOW_PATH  \
 330    :        /* Restore original EDX. */  \
 331    :        __asm mov edx, DWORD PTR[esp + 8]  \
 332    :        /* Restore the EFLAGS. */  \
 333    :        ASAN_RESTORE_EFLAGS  \
 334    :        __asm ret 4  \
 335    :      __asm report_failure:  \
 336    :        /* Restore memory location in EDX. */  \
 337    :        __asm pop edx  \
 338    :        /* Restore the EFLAGS. */  \
 339    :        ASAN_RESTORE_EFLAGS  \
 340    :        ASAN_ERROR_PATH(access_size, access_mode_value)  \
 341    :      }  \
 342    :    }
 343    :  
 344    :  // Generates a variant of the asan check access functions that don't save the
 345    :  // flags. The name of the generated method will be
 346    :  // asan_check_(@p access_size)_byte_(@p access_mode_str)_no_flags().
 347    :  // @param access_size The size of the access (in byte).
 348    :  // @param access_mode_str The string representing the access mode (read_access
 349    :  //     or write_access).
 350    :  // @param access_mode_value The internal value representing this kind of access.
 351    :  // @note Calling this function may alter the EFLAGS register only.
 352    :  #define ASAN_CHECK_FUNCTION_NO_FLAGS(access_size,  \
 353    :                                       access_mode_str,  \
 354    :                                       access_mode_value)  \
 355    :    extern "C" __declspec(naked)  \
 356    :        void asan_check_ ## access_size ## _byte_ ## access_mode_str ##  \
 357    :            _no_flags() {  \
 358    :      __asm {  \
 359    :        ASAN_FAST_PATH  \
 360    :        /* Restore original EDX. */  \
 361    :        __asm mov edx, DWORD PTR[esp + 4]  \
 362    :        __asm ret 4  \
 363    :      __asm check_access_slow:  \
 364    :        ASAN_SLOW_PATH  \
 365    :        /* Restore original EDX. */  \
 366    :        __asm mov edx, DWORD PTR[esp + 4]  \
 367    :        __asm ret 4  \
 368    :      __asm report_failure:  \
 369    :        /* Restore memory location in EDX. */  \
 370    :        __asm pop edx  \
 371    :        ASAN_ERROR_PATH(access_size, access_mode_value)  \
 372    :      }  \
 373    :    }
 374    :  
 375    :  // Redefine some enums to make them accessible in the inlined assembly.
 376    :  // @{
 377    :  enum AccessMode {
 378    :    AsanReadAccess = HeapProxy::ASAN_READ_ACCESS,
 379    :    AsanWriteAccess = HeapProxy::ASAN_WRITE_ACCESS,
 380    :    AsanUnknownAccess = HeapProxy::ASAN_UNKNOWN_ACCESS,
 381    :  };
 382    :  // @}
 383    :  
 384    :  // The slow path rely on the fact that the shadow memory non accessible byte
 385    :  // mask have its upper bit set to 1..
 386    :  COMPILE_ASSERT(
 387    :      (agent::asan::Shadow::kHeapNonAccessibleByteMask & (1 << 7)) != 0,
 388    :          asan_shadow_mask_upper_bit_is_0);
 389    :  
 390  i :  ASAN_CHECK_FUNCTION(1, read_access, AsanReadAccess)
 391  i :  ASAN_CHECK_FUNCTION(2, read_access, AsanReadAccess)
 392  i :  ASAN_CHECK_FUNCTION(4, read_access, AsanReadAccess)
 393  i :  ASAN_CHECK_FUNCTION(8, read_access, AsanReadAccess)
 394  i :  ASAN_CHECK_FUNCTION(10, read_access, AsanReadAccess)
 395  i :  ASAN_CHECK_FUNCTION(16, read_access, AsanReadAccess)
 396  i :  ASAN_CHECK_FUNCTION(32, read_access, AsanReadAccess)
 397  i :  ASAN_CHECK_FUNCTION(1, write_access, AsanWriteAccess)
 398  i :  ASAN_CHECK_FUNCTION(2, write_access, AsanWriteAccess)
 399  i :  ASAN_CHECK_FUNCTION(4, write_access, AsanWriteAccess)
 400  i :  ASAN_CHECK_FUNCTION(8, write_access, AsanWriteAccess)
 401  i :  ASAN_CHECK_FUNCTION(10, write_access, AsanWriteAccess)
 402  i :  ASAN_CHECK_FUNCTION(16, write_access, AsanWriteAccess)
 403  i :  ASAN_CHECK_FUNCTION(32, write_access, AsanWriteAccess)
 404    :  
 405    :  #undef ASAN_CHECK_FUNCTION
 406    :  
 407  i :  ASAN_CHECK_FUNCTION_NO_FLAGS(1, read_access, AsanReadAccess)
 408  i :  ASAN_CHECK_FUNCTION_NO_FLAGS(2, read_access, AsanReadAccess)
 409  i :  ASAN_CHECK_FUNCTION_NO_FLAGS(4, read_access, AsanReadAccess)
 410  i :  ASAN_CHECK_FUNCTION_NO_FLAGS(8, read_access, AsanReadAccess)
 411  i :  ASAN_CHECK_FUNCTION_NO_FLAGS(10, read_access, AsanReadAccess)
 412  i :  ASAN_CHECK_FUNCTION_NO_FLAGS(16, read_access, AsanReadAccess)
 413  i :  ASAN_CHECK_FUNCTION_NO_FLAGS(32, read_access, AsanReadAccess)
 414  i :  ASAN_CHECK_FUNCTION_NO_FLAGS(1, write_access, AsanWriteAccess)
 415  i :  ASAN_CHECK_FUNCTION_NO_FLAGS(2, write_access, AsanWriteAccess)
 416  i :  ASAN_CHECK_FUNCTION_NO_FLAGS(4, write_access, AsanWriteAccess)
 417  i :  ASAN_CHECK_FUNCTION_NO_FLAGS(8, write_access, AsanWriteAccess)
 418  i :  ASAN_CHECK_FUNCTION_NO_FLAGS(10, write_access, AsanWriteAccess)
 419  i :  ASAN_CHECK_FUNCTION_NO_FLAGS(16, write_access, AsanWriteAccess)
 420  i :  ASAN_CHECK_FUNCTION_NO_FLAGS(32, write_access, AsanWriteAccess)
 421    :  
 422    :  #undef ASAN_CHECK_FUNCTION_NO_FLAGS
 423    :  #undef ASAN_SAVE_EFLAGS
 424    :  #undef ASAN_RESTORE_EFLAGS
 425    :  #undef ASAN_FAST_PATH
 426    :  #undef ASAN_SLOW_PATH
 427    :  #undef ASAN_ERROR_PATH
 428    :  
 429    :  // Generates the asan check access functions for a string instruction.
 430    :  // The name of the generated method will be
 431    :  // asan_check_(@p prefix)(@p access_size)_byte_(@p inst)_access().
 432    :  // @param inst The instruction mnemonic.
 433    :  // @param prefix The prefix of the instruction (repz or nothing).
 434    :  // @param counter The number of times the instruction must be executed (ECX). It
 435    :  //     may be a register or a constant.
 436    :  // @param dst_mode The memory access mode for destination (EDI).
 437    :  // @param src_mode The memory access mode for destination (ESI).
 438    :  // @param access_size The size of the access (in byte).
 439    :  // @param compare A flag to enable shortcut execution by comparing memory
 440    :  //     contents.
 441    :  #define ASAN_CHECK_STRINGS(func, prefix, counter, dst_mode, src_mode, \
 442    :      access_size, compare)  \
 443    :    extern "C" __declspec(naked)  \
 444    :    void asan_check ## prefix ## access_size ## _byte_ ## func ## _access() {  \
 445    :      __asm {  \
 446    :        /* Prologue, save context. */  \
 447    :        __asm pushfd  \
 448    :        __asm pushad  \
 449    :        /* Fix the original value of ESP in the ASAN registers context. */  \
 450    :        /* Removing 8 bytes (e.g.EFLAGS / EIP was on stack). */  \
 451    :        __asm add DWORD PTR[esp + 12], 8  \
 452    :        /* Setup increment in EBX (depends on direction flag in EFLAGS). */  \
 453    :        __asm mov ebx, access_size  \
 454    :        __asm pushfd  \
 455    :        __asm pop eax  \
 456    :        __asm test eax, 0x400  \
 457    :        __asm jz skip_neg_direction  \
 458    :        __asm neg ebx  \
 459    :      __asm skip_neg_direction:  \
 460    :        /* By standard calling convention, direction flag must be forward. */  \
 461    :        __asm cld  \
 462    :        /* Push ARG(context), the ASAN registers context. */  \
 463    :        __asm push esp  \
 464    :        /* Push ARG(compare), shortcut when memory contents differ. */  \
 465    :        __asm push compare  \
 466    :        /* Push ARG(increment), increment for EDI/EDI. */  \
 467    :        __asm push ebx  \
 468    :        /* Push ARG(access_size), the access size. */  \
 469    :        __asm push access_size  \
 470    :        /* Push ARG(length), the number of memory accesses. */  \
 471    :        __asm push counter  \
 472    :        /* Push ARG(src_access_mode), source access type. */  \
 473    :        __asm push src_mode \
 474    :        /* Push ARG(src), the source pointer. */  \
 475    :        __asm push esi  \
 476    :        /* Push ARG(dst_access_mode), destination access type. */  \
 477    :        __asm push dst_mode \
 478    :        /* Push ARG(dst), the destination pointer. */  \
 479    :        __asm push edi  \
 480    :        /* Call the generic check strings function. */  \
 481    :        __asm call agent::asan::CheckStringsMemoryAccesses  \
 482    :        __asm add esp, 36  \
 483    :        /* Epilogue, restore context. */  \
 484    :        __asm popad  \
 485    :        __asm popfd  \
 486    :        __asm ret  \
 487    :      }  \
 488    :    }
 489    :  
 490  i :  ASAN_CHECK_STRINGS(cmps, _repz_, ecx, AsanReadAccess, AsanReadAccess, 4, 1)
 491  i :  ASAN_CHECK_STRINGS(cmps, _repz_, ecx, AsanReadAccess, AsanReadAccess, 2, 1)
 492  i :  ASAN_CHECK_STRINGS(cmps, _repz_, ecx, AsanReadAccess, AsanReadAccess, 1, 1)
 493  i :  ASAN_CHECK_STRINGS(cmps, _, 1, AsanReadAccess, AsanReadAccess, 4, 1)
 494  i :  ASAN_CHECK_STRINGS(cmps, _, 1, AsanReadAccess, AsanReadAccess, 2, 1)
 495  i :  ASAN_CHECK_STRINGS(cmps, _, 1, AsanReadAccess, AsanReadAccess, 1, 1)
 496    :  
 497  i :  ASAN_CHECK_STRINGS(movs, _repz_, ecx, AsanWriteAccess, AsanReadAccess, 4, 0)
 498  i :  ASAN_CHECK_STRINGS(movs, _repz_, ecx, AsanWriteAccess, AsanReadAccess, 2, 0)
 499  i :  ASAN_CHECK_STRINGS(movs, _repz_, ecx, AsanWriteAccess, AsanReadAccess, 1, 0)
 500  i :  ASAN_CHECK_STRINGS(movs, _, 1, AsanWriteAccess, AsanReadAccess, 4, 0)
 501  i :  ASAN_CHECK_STRINGS(movs, _, 1, AsanWriteAccess, AsanReadAccess, 2, 0)
 502  i :  ASAN_CHECK_STRINGS(movs, _, 1, AsanWriteAccess, AsanReadAccess, 1, 0)
 503    :  
 504  i :  ASAN_CHECK_STRINGS(stos, _repz_, ecx, AsanWriteAccess, AsanUnknownAccess, 4, 0)
 505  i :  ASAN_CHECK_STRINGS(stos, _repz_, ecx, AsanWriteAccess, AsanUnknownAccess, 2, 0)
 506  i :  ASAN_CHECK_STRINGS(stos, _repz_, ecx, AsanWriteAccess, AsanUnknownAccess, 1, 0)
 507  i :  ASAN_CHECK_STRINGS(stos, _, 1, AsanWriteAccess, AsanUnknownAccess, 4, 0)
 508  i :  ASAN_CHECK_STRINGS(stos, _, 1, AsanWriteAccess, AsanUnknownAccess, 2, 0)
 509  i :  ASAN_CHECK_STRINGS(stos, _, 1, AsanWriteAccess, AsanUnknownAccess, 1, 0)
 510    :  
 511    :  #undef ASAN_CHECK_STRINGS
 512    :  
 513    :  namespace {
 514    :  
 515    :  void ContextToAsanContext(const CONTEXT& context,
 516  E :                            agent::asan::AsanContext* asan_context) {
 517  E :    DCHECK(asan_context != NULL);
 518  E :    asan_context->original_eax = context.Eax;
 519  E :    asan_context->original_ebp = context.Ebp;
 520  E :    asan_context->original_ebx = context.Ebx;
 521  E :    asan_context->original_ecx = context.Ecx;
 522  E :    asan_context->original_edi = context.Edi;
 523  E :    asan_context->original_edx = context.Edx;
 524  E :    asan_context->original_eflags = context.EFlags;
 525  E :    asan_context->original_eip = context.Eip;
 526  E :    asan_context->original_esi = context.Esi;
 527  E :    asan_context->original_esp = context.Esp;
 528  E :  }
 529    :  
 530    :  // Report an invalid access to @p location.
 531    :  // @param location The memory address of the access.
 532    :  // @param access_mode The mode of the access.
 533  E :  void ReportBadAccess(const uint8* location, HeapProxy::AccessMode access_mode) {
 534  E :    agent::asan::AsanContext asan_context = {};
 535  E :    CONTEXT context = {};
 536  E :    ::RtlCaptureContext(&context);
 537  E :    ContextToAsanContext(context, &asan_context);
 538    :    ReportBadMemoryAccess(const_cast<uint8*>(location),
 539    :                          access_mode,
 540    :                          1U,
 541  E :                          &asan_context);
 542  E :  }
 543    :  
 544    :  // Test that a memory range is accessible. Report an error if it's not.
 545    :  // @param memory The pointer to the beginning of the memory range that we want
 546    :  //     to check.
 547    :  // @param size The size of the memory range that we want to check.
 548    :  // @param access_mode The access mode.
 549    :  void TestMemoryRange(const uint8* memory,
 550    :                       size_t size,
 551  E :                       HeapProxy::AccessMode access_mode) {
 552  E :    if (size == 0U)
 553  E :      return;
 554    :    // TODO(sebmarchand): This approach is pretty limited because it only check
 555    :    //     if the first and the last elements are accessible. Once we have the
 556    :    //     plumbing in place we should benchmark a check that looks at each
 557    :    //     address to be touched (via the shadow memory, 8 bytes at a time).
 558    :    if (!agent::asan::Shadow::IsAccessible(memory) ||
 559  E :        !agent::asan::Shadow::IsAccessible(memory + size - 1)) {
 560  E :      const uint8* location = NULL;
 561  E :      if (!agent::asan::Shadow::IsAccessible(memory))
 562  E :        location = memory;
 563  E :      else
 564  E :        location = memory + size - 1;
 565  E :      ReportBadAccess(location, access_mode);
 566    :    }
 567  E :  }
 568    :  
 569    :  // Helper function to test if the memory range of a given structure is
 570    :  // accessible.
 571    :  // @tparam T the type of the structure to be tested.
 572    :  // @param structure A pointer to this structure.
 573    :  // @param access mode The access mode.
 574    :  template <typename T>
 575  E :  void TestStructure(const T* structure, HeapProxy::AccessMode access_mode) {
 576    :    TestMemoryRange(reinterpret_cast<const uint8*>(structure),
 577    :                    sizeof(T),
 578  E :                    access_mode);
 579  E :  }
 580    :  
 581    :  }  // namespace
 582    :  
 583    :  extern "C" {
 584    :  
 585    :  HANDLE WINAPI asan_HeapCreate(DWORD options,
 586    :                                SIZE_T initial_size,
 587  E :                                SIZE_T maximum_size) {
 588  E :    DCHECK(asan_runtime != NULL);
 589  E :    scoped_ptr<HeapProxy> proxy(new HeapProxy());
 590  E :    if (!proxy->Create(options, initial_size, maximum_size))
 591  E :      return NULL;
 592    :  
 593  E :    asan_runtime->AddHeap(proxy.get());
 594    :  
 595  E :    return HeapProxy::ToHandle(proxy.release());
 596  E :  }
 597    :  
 598  E :  BOOL WINAPI asan_HeapDestroy(HANDLE heap) {
 599  E :    DCHECK(process_heap != NULL);
 600  E :    if (heap == process_heap)
 601  i :      return ::HeapDestroy(heap);
 602    :  
 603  E :    HeapProxy* proxy = HeapProxy::FromHandle(heap);
 604  E :    if (!proxy)
 605  i :      return FALSE;
 606    :  
 607  E :    asan_runtime->RemoveHeap(proxy);
 608    :  
 609  E :    if (proxy->Destroy()) {
 610  E :      delete proxy;
 611  E :      return TRUE;
 612    :    }
 613    :  
 614  i :    return FALSE;
 615  E :  }
 616    :  
 617    :  LPVOID WINAPI asan_HeapAlloc(HANDLE heap,
 618    :                               DWORD flags,
 619  E :                               SIZE_T bytes) {
 620  E :    DCHECK(process_heap != NULL);
 621  E :    if (heap == process_heap)
 622  i :      return ::HeapAlloc(heap, flags, bytes);
 623    :  
 624  E :    HeapProxy* proxy = HeapProxy::FromHandle(heap);
 625  E :    if (!proxy)
 626  i :      return NULL;
 627    :  
 628  E :    return proxy->Alloc(flags, bytes);
 629  E :  }
 630    :  
 631    :  LPVOID WINAPI asan_HeapReAlloc(HANDLE heap,
 632    :                                 DWORD flags,
 633    :                                 LPVOID mem,
 634  E :                                 SIZE_T bytes) {
 635  E :    DCHECK(process_heap != NULL);
 636  E :    if (heap == process_heap)
 637  i :      return ::HeapReAlloc(heap, flags, mem, bytes);
 638    :  
 639  E :    HeapProxy* proxy = HeapProxy::FromHandle(heap);
 640  E :    if (!proxy)
 641  i :      return NULL;
 642    :  
 643  E :    return proxy->ReAlloc(flags, mem, bytes);
 644  E :  }
 645    :  
 646    :  BOOL WINAPI asan_HeapFree(HANDLE heap,
 647    :                            DWORD flags,
 648  E :                            LPVOID mem) {
 649  E :    DCHECK(process_heap != NULL);
 650  E :    if (heap == process_heap)
 651  i :      return ::HeapFree(heap, flags, mem);
 652    :  
 653  E :    HeapProxy* proxy = HeapProxy::FromHandle(heap);
 654  E :    if (!proxy)
 655  i :      return FALSE;
 656    :  
 657  E :    if (!proxy->Free(flags, mem)) {
 658  E :      AsanErrorInfo error_info = {};
 659  E :      ::RtlCaptureContext(&error_info.context);
 660  E :      error_info.location = mem;
 661  E :      error_info.error_type = HeapProxy::DOUBLE_FREE;
 662  E :      proxy->GetBadAccessInformation(&error_info);
 663  E :      agent::asan::StackCapture stack;
 664  E :      stack.InitFromStack();
 665  E :      error_info.crash_stack_id = stack.ComputeRelativeStackId();
 666  E :      asan_runtime->OnError(&error_info);
 667  E :      return false;
 668    :    }
 669    :  
 670  E :    return true;
 671  E :  }
 672    :  
 673    :  SIZE_T WINAPI asan_HeapSize(HANDLE heap,
 674    :                              DWORD flags,
 675  E :                              LPCVOID mem) {
 676  E :    DCHECK(process_heap != NULL);
 677  E :    if (heap == process_heap)
 678  i :      return ::HeapSize(heap, flags, mem);
 679    :  
 680  E :    HeapProxy* proxy = HeapProxy::FromHandle(heap);
 681  E :    if (!proxy)
 682  i :      return static_cast<SIZE_T>(-1);
 683    :  
 684  E :    return proxy->Size(flags, mem);
 685  E :  }
 686    :  
 687    :  BOOL WINAPI asan_HeapValidate(HANDLE heap,
 688    :                                DWORD flags,
 689  E :                                LPCVOID mem) {
 690  E :    DCHECK(process_heap != NULL);
 691  E :    if (heap == process_heap)
 692  i :      return ::HeapValidate(heap, flags, mem);
 693    :  
 694  E :    HeapProxy* proxy = HeapProxy::FromHandle(heap);
 695  E :    if (!proxy)
 696  i :      return FALSE;
 697    :  
 698  E :    return proxy->Validate(flags, mem);
 699  E :  }
 700    :  
 701    :  SIZE_T WINAPI asan_HeapCompact(HANDLE heap,
 702  E :                                 DWORD flags) {
 703  E :    DCHECK(process_heap != NULL);
 704  E :    if (heap == process_heap)
 705  i :      return ::HeapCompact(heap, flags);
 706    :  
 707  E :    HeapProxy* proxy = HeapProxy::FromHandle(heap);
 708  E :    if (!proxy)
 709  i :      return 0;
 710    :  
 711  E :    return proxy->Compact(flags);
 712  E :  }
 713    :  
 714  E :  BOOL WINAPI asan_HeapLock(HANDLE heap) {
 715  E :    DCHECK(process_heap != NULL);
 716  E :    if (heap == process_heap)
 717  i :      return ::HeapLock(heap);
 718    :  
 719  E :    HeapProxy* proxy = HeapProxy::FromHandle(heap);
 720  E :    if (!proxy)
 721  i :      return FALSE;
 722    :  
 723  E :    return proxy->Lock();
 724  E :  }
 725    :  
 726  E :  BOOL WINAPI asan_HeapUnlock(HANDLE heap) {
 727  E :    DCHECK(process_heap != NULL);
 728  E :    if (heap == process_heap)
 729  i :      return ::HeapUnlock(heap);
 730    :  
 731  E :    HeapProxy* proxy = HeapProxy::FromHandle(heap);
 732  E :    if (!proxy)
 733  i :      return FALSE;
 734    :  
 735  E :    return proxy->Unlock();
 736  E :  }
 737    :  
 738    :  BOOL WINAPI asan_HeapWalk(HANDLE heap,
 739  E :                            LPPROCESS_HEAP_ENTRY entry) {
 740  E :    DCHECK(process_heap != NULL);
 741  E :    if (heap == process_heap)
 742  i :      return ::HeapWalk(heap, entry);
 743    :  
 744  E :    HeapProxy* proxy = HeapProxy::FromHandle(heap);
 745  E :    if (!proxy)
 746  i :      return FALSE;
 747    :  
 748  E :    return proxy->Walk(entry);
 749  E :  }
 750    :  
 751    :  BOOL WINAPI asan_HeapSetInformation(
 752    :      HANDLE heap, HEAP_INFORMATION_CLASS info_class,
 753  E :      PVOID info, SIZE_T info_length) {
 754  E :    DCHECK(process_heap != NULL);
 755  E :    if (heap == NULL || heap == process_heap)
 756  E :      return ::HeapSetInformation(heap, info_class, info, info_length);
 757    :  
 758  E :    HeapProxy* proxy = HeapProxy::FromHandle(heap);
 759  E :    if (!proxy)
 760  i :      return FALSE;
 761    :  
 762  E :    return proxy->SetInformation(info_class, info, info_length);
 763  E :  }
 764    :  
 765    :  BOOL WINAPI asan_HeapQueryInformation(
 766    :      HANDLE heap, HEAP_INFORMATION_CLASS info_class,
 767  E :      PVOID info, SIZE_T info_length, PSIZE_T return_length) {
 768  E :    DCHECK(process_heap != NULL);
 769  E :    if (heap == NULL || heap == process_heap) {
 770    :      return ::HeapQueryInformation(heap,
 771    :                                    info_class,
 772    :                                    info,
 773    :                                    info_length,
 774  i :                                    return_length);
 775    :    }
 776    :  
 777  E :    HeapProxy* proxy = HeapProxy::FromHandle(heap);
 778  E :    if (!proxy)
 779  i :      return FALSE;
 780    :  
 781    :    bool ret = proxy->QueryInformation(info_class,
 782    :                                       info,
 783    :                                       info_length,
 784  E :                                       return_length);
 785  E :    return ret == true;
 786  E :  }
 787    :  
 788  E :  void WINAPI asan_SetCallBack(AsanErrorCallBack callback) {
 789  E :    DCHECK(asan_runtime != NULL);
 790  E :    asan_runtime->SetErrorCallBack(base::Bind(callback));
 791  E :  }
 792    :  
 793    :  void* __cdecl asan_memcpy(unsigned char* destination,
 794    :                            const unsigned char* source,
 795  E :                            size_t num) {
 796  E :    TestMemoryRange(source, num, HeapProxy::ASAN_READ_ACCESS);
 797  E :    TestMemoryRange(destination, num, HeapProxy::ASAN_WRITE_ACCESS);
 798  E :    return memcpy(destination, source, num);
 799  E :  }
 800    :  
 801    :  void* __cdecl asan_memmove(unsigned char* destination,
 802    :                             const unsigned char* source,
 803  E :                             size_t num) {
 804  E :    TestMemoryRange(source, num, HeapProxy::ASAN_READ_ACCESS);
 805  E :    TestMemoryRange(destination, num, HeapProxy::ASAN_WRITE_ACCESS);
 806  E :    return memmove(destination, source, num);
 807  E :  }
 808    :  
 809  E :  void* __cdecl asan_memset(unsigned char* ptr, int value, size_t num) {
 810  E :    TestMemoryRange(ptr, num, HeapProxy::ASAN_WRITE_ACCESS);
 811  E :    return memset(ptr, value, num);
 812  E :  }
 813    :  
 814    :  const void* __cdecl asan_memchr(const unsigned char* ptr,
 815    :                                  int value,
 816  E :                                  size_t num) {
 817  E :    TestMemoryRange(ptr, num, HeapProxy::ASAN_READ_ACCESS);
 818  E :    return memchr(ptr, value, num);
 819  E :  }
 820    :  
 821    :  size_t __cdecl asan_strcspn(const char* str1,
 822  E :                              const char* str2) {
 823  E :    size_t size = 0;
 824  E :    if (!agent::asan::Shadow::GetNullTerminatedArraySize(str1, &size, 0U)) {
 825    :      ReportBadAccess(reinterpret_cast<const uint8*>(str1) + size,
 826  E :                      HeapProxy::ASAN_READ_ACCESS);
 827    :    }
 828  E :    if (!agent::asan::Shadow::GetNullTerminatedArraySize(str2, &size, 0U)) {
 829    :      ReportBadAccess(reinterpret_cast<const uint8*>(str2) + size,
 830  E :                      HeapProxy::ASAN_READ_ACCESS);
 831    :    }
 832  E :    return strcspn(str1, str2);
 833  E :  }
 834    :  
 835  E :  size_t __cdecl asan_strlen(const char* str) {
 836  E :    size_t size = 0;
 837  E :    if (!agent::asan::Shadow::GetNullTerminatedArraySize(str, &size, 0U)) {
 838    :      ReportBadAccess(reinterpret_cast<const uint8*>(str) + size,
 839  E :                      HeapProxy::ASAN_READ_ACCESS);
 840  E :      return strlen(str);
 841    :    }
 842  E :    return size - 1;
 843  E :  }
 844    :  
 845  E :  const char* __cdecl asan_strrchr(const char* str, int character) {
 846  E :    size_t size = 0;
 847  E :    if (!agent::asan::Shadow::GetNullTerminatedArraySize(str, &size, 0U)) {
 848    :      ReportBadAccess(reinterpret_cast<const uint8*>(str) + size,
 849  E :                      HeapProxy::ASAN_READ_ACCESS);
 850    :    }
 851  E :    return strrchr(str, character);
 852  E :  }
 853    :  
 854  E :  int __cdecl asan_strcmp(const char* str1, const char* str2) {
 855  E :    size_t size = 0;
 856  E :    if (!agent::asan::Shadow::GetNullTerminatedArraySize(str1, &size, 0U)) {
 857    :      ReportBadAccess(reinterpret_cast<const uint8*>(str1) + size,
 858  E :                      HeapProxy::ASAN_READ_ACCESS);
 859    :    }
 860  E :    if (!agent::asan::Shadow::GetNullTerminatedArraySize(str2, &size, 0U)) {
 861    :      ReportBadAccess(reinterpret_cast<const uint8*>(str2) + size,
 862  E :                      HeapProxy::ASAN_READ_ACCESS);
 863    :    }
 864  E :    return strcmp(str1, str2);
 865  E :  }
 866    :  
 867  E :  const char* __cdecl asan_strpbrk(const char* str1, const char* str2) {
 868  E :    size_t size = 0;
 869  E :    if (!agent::asan::Shadow::GetNullTerminatedArraySize(str1, &size, 0U)) {
 870    :      ReportBadAccess(reinterpret_cast<const uint8*>(str1) + size,
 871  E :                      HeapProxy::ASAN_READ_ACCESS);
 872    :    }
 873  E :    if (!agent::asan::Shadow::GetNullTerminatedArraySize(str2, &size, 0U)) {
 874    :      ReportBadAccess(reinterpret_cast<const uint8*>(str2) + size,
 875  E :                      HeapProxy::ASAN_READ_ACCESS);
 876    :    }
 877  E :    return strpbrk(str1, str2);
 878  E :  }
 879    :  
 880  E :  const char* __cdecl asan_strstr(const char* str1, const char* str2) {
 881  E :    size_t size = 0;
 882  E :    if (!agent::asan::Shadow::GetNullTerminatedArraySize(str1, &size, 0U)) {
 883    :      ReportBadAccess(reinterpret_cast<const uint8*>(str1) + size,
 884  E :                      HeapProxy::ASAN_READ_ACCESS);
 885    :    }
 886  E :    if (!agent::asan::Shadow::GetNullTerminatedArraySize(str2, &size, 0U)) {
 887    :      ReportBadAccess(reinterpret_cast<const uint8*>(str2) + size,
 888  E :                      HeapProxy::ASAN_READ_ACCESS);
 889    :    }
 890  E :    return strstr(str1, str2);
 891  E :  }
 892    :  
 893  E :  size_t __cdecl asan_strspn(const char* str1, const char* str2) {
 894  E :    size_t size = 0;
 895  E :    if (!agent::asan::Shadow::GetNullTerminatedArraySize(str1, &size, 0U)) {
 896    :      ReportBadAccess(reinterpret_cast<const uint8*>(str1) + size,
 897  E :                      HeapProxy::ASAN_READ_ACCESS);
 898    :    }
 899  E :    if (!agent::asan::Shadow::GetNullTerminatedArraySize(str2, &size, 0U)) {
 900    :      ReportBadAccess(reinterpret_cast<const uint8*>(str2) + size,
 901  E :                      HeapProxy::ASAN_READ_ACCESS);
 902    :    }
 903  E :    return strspn(str1, str2);
 904  E :  }
 905    :  
 906  E :  char* __cdecl asan_strncpy(char* destination, const char* source, size_t num) {
 907  E :    if (num != 0U) {
 908  E :      size_t src_size = 0;
 909    :      if (!agent::asan::Shadow::GetNullTerminatedArraySize(source,
 910    :                                                           &src_size,
 911    :                                                           num) &&
 912  E :          src_size <= num) {
 913    :        ReportBadAccess(reinterpret_cast<const uint8*>(source) + src_size,
 914  E :                        HeapProxy::ASAN_READ_ACCESS);
 915    :      }
 916    :      // We can't use the GetNullTerminatedArraySize function here, as destination
 917    :      // might not be null terminated.
 918    :      TestMemoryRange(reinterpret_cast<const uint8*>(destination),
 919    :                      num,
 920  E :                      HeapProxy::ASAN_WRITE_ACCESS);
 921    :    }
 922  E :    return strncpy(destination, source, num);
 923  E :  }
 924    :  
 925  E :  char* __cdecl asan_strncat(char* destination, const char* source, size_t num) {
 926  E :    if (num != 0U) {
 927  E :      size_t src_size = 0;
 928    :      if (!agent::asan::Shadow::GetNullTerminatedArraySize(source,
 929    :                                                           &src_size,
 930    :                                                           num) &&
 931  E :          src_size <= num) {
 932    :        ReportBadAccess(reinterpret_cast<const uint8*>(source) + src_size,
 933  E :                        HeapProxy::ASAN_READ_ACCESS);
 934    :      }
 935  E :      size_t dst_size = 0;
 936    :      if (!agent::asan::Shadow::GetNullTerminatedArraySize(destination,
 937    :                                                           &dst_size,
 938  E :                                                           0U)) {
 939    :        ReportBadAccess(reinterpret_cast<const uint8*>(destination) + dst_size,
 940  E :                        HeapProxy::ASAN_WRITE_ACCESS);
 941  E :      } else {
 942    :        // Test if we can append the source to the destination.
 943    :        TestMemoryRange(reinterpret_cast<const uint8*>(destination + dst_size),
 944    :                        std::min(num, src_size),
 945  E :                        HeapProxy::ASAN_WRITE_ACCESS);
 946    :      }
 947    :    }
 948  E :    return strncat(destination, source, num);
 949  E :  }
 950    :  
 951  E :  void asan_SetInterceptorCallback(InterceptorTailCallback callback) {
 952  E :    interceptor_tail_callback = callback;
 953  E :  }
 954    :  
 955    :  BOOL WINAPI asan_ReadFile(HANDLE file_handle,
 956    :                            LPVOID buffer,
 957    :                            DWORD bytes_to_read,
 958    :                            LPDWORD bytes_read,
 959  E :                            LPOVERLAPPED overlapped) {
 960    :    // TODO(sebmarchand): Add more checks for the asynchronous calls to this
 961    :    //     function. More details about the asynchronous calls to ReadFile are
 962    :    //     available here: http://support.microsoft.com/kb/156932.
 963    :  
 964    :    // Ensures that the input values are accessible.
 965    :  
 966    :    TestMemoryRange(reinterpret_cast<uint8*>(buffer),
 967    :                    bytes_to_read,
 968  E :                    HeapProxy::ASAN_WRITE_ACCESS);
 969    :  
 970  E :    if (bytes_read != NULL)
 971  E :      TestStructure<DWORD>(bytes_read, HeapProxy::ASAN_WRITE_ACCESS);
 972    :  
 973  E :    if (overlapped != NULL)
 974  E :      TestStructure<OVERLAPPED>(overlapped, HeapProxy::ASAN_READ_ACCESS);
 975    :  
 976    :    BOOL ret = ::ReadFile(file_handle,
 977    :                          buffer,
 978    :                          bytes_to_read,
 979    :                          bytes_read,
 980  E :                          overlapped);
 981    :  
 982    :    // Run the interceptor callback if it has been set.
 983  E :    if (interceptor_tail_callback != NULL)
 984  E :      (*interceptor_tail_callback)();
 985    :  
 986  E :    if (ret == FALSE)
 987  i :      return ret;
 988    :  
 989    :    // Even if the overlapped pointer wasn't NULL it might become invalid after
 990    :    // the call to ReadFile, and so we can't test that this structure is
 991    :    // accessible.
 992    :  
 993  E :    DCHECK_EQ(TRUE, ret);
 994  E :    CHECK(bytes_read == NULL || *bytes_read <= bytes_to_read);
 995    :    TestMemoryRange(reinterpret_cast<uint8*>(buffer),
 996    :                    bytes_to_read,
 997  E :                    HeapProxy::ASAN_WRITE_ACCESS);
 998    :  
 999  E :    if (bytes_read != NULL)
1000  E :      TestStructure<DWORD>(bytes_read, HeapProxy::ASAN_WRITE_ACCESS);
1001    :  
1002  E :    return ret;
1003  E :  }
1004    :  
1005    :  BOOL WINAPI asan_WriteFile(HANDLE file_handle,
1006    :                             LPCVOID buffer,
1007    :                             DWORD bytes_to_write,
1008    :                             LPDWORD bytes_written,
1009  E :                             LPOVERLAPPED overlapped) {
1010    :    // Ensures that the input values are accessible.
1011    :  
1012    :    TestMemoryRange(reinterpret_cast<const uint8*>(buffer),
1013    :                    bytes_to_write,
1014  E :                    HeapProxy::ASAN_READ_ACCESS);
1015    :  
1016  E :    if (bytes_written != NULL)
1017  E :      TestStructure<DWORD>(bytes_written, HeapProxy::ASAN_WRITE_ACCESS);
1018    :  
1019  E :    if (overlapped != NULL)
1020  E :      TestStructure<OVERLAPPED>(overlapped, HeapProxy::ASAN_READ_ACCESS);
1021    :  
1022    :    BOOL ret = ::WriteFile(file_handle,
1023    :                           buffer,
1024    :                           bytes_to_write,
1025    :                           bytes_written,
1026  E :                           overlapped);
1027    :  
1028    :    // Run the interceptor callback if it has been set.
1029  E :    if (interceptor_tail_callback != NULL)
1030  E :      (*interceptor_tail_callback)();
1031    :  
1032  E :    if (ret == FALSE)
1033  i :      return ret;
1034    :  
1035    :    // Even if the overlapped pointer wasn't NULL it might become invalid after
1036    :    // the call to WriteFile, and so we can't test that this structure is
1037    :    // accessible.
1038    :  
1039  E :    DCHECK_EQ(TRUE, ret);
1040  E :    CHECK(bytes_written == NULL || *bytes_written <= bytes_to_write);
1041    :    TestMemoryRange(reinterpret_cast<const uint8*>(buffer),
1042    :                    bytes_to_write,
1043  E :                    HeapProxy::ASAN_READ_ACCESS);
1044    :  
1045  E :    if (bytes_written != NULL)
1046  E :      TestStructure<DWORD>(bytes_written, HeapProxy::ASAN_WRITE_ACCESS);
1047    :  
1048  E :    return ret;
1049  E :  }
1050    :  
1051    :  }  // extern "C"

Coverage information generated Wed Dec 11 11:34:16 2013.