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

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
79.7%1061330.C++source

Line-by-line coverage:

   1    :  // Copyright 2012 Google Inc.
   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 "base/logging.h"
  17    :  #include "base/memory/scoped_ptr.h"
  18    :  #include "syzygy/agent/asan/asan_heap.h"
  19    :  #include "syzygy/agent/asan/asan_shadow.h"
  20    :  
  21    :  extern "C" {
  22    :  
  23    :  using agent::asan::HeapProxy;
  24    :  
  25  E :  static HANDLE process_heap = GetProcessHeap();
  26    :  
  27    :  HANDLE WINAPI asan_HeapCreate(DWORD options,
  28    :                                SIZE_T initial_size,
  29  E :                                SIZE_T maximum_size) {
  30  E :    scoped_ptr<HeapProxy> proxy(new HeapProxy());
  31  E :    if (!proxy->Create(options, initial_size, maximum_size))
  32  i :      proxy.reset();
  33    :  
  34  E :    return HeapProxy::ToHandle(proxy.release());
  35  E :  }
  36    :  
  37  E :  BOOL WINAPI asan_HeapDestroy(HANDLE heap) {
  38  E :    if (heap == process_heap)
  39  i :      return ::HeapDestroy(heap);
  40    :  
  41  E :    HeapProxy* proxy = HeapProxy::FromHandle(heap);
  42  E :    if (!proxy)
  43  i :      return FALSE;
  44    :  
  45  E :    if (proxy->Destroy()) {
  46  E :      delete proxy;
  47  E :      return TRUE;
  48    :    }
  49    :  
  50  i :    return FALSE;
  51  E :  }
  52    :  
  53    :  LPVOID WINAPI asan_HeapAlloc(HANDLE heap,
  54    :                               DWORD flags,
  55  E :                               SIZE_T bytes) {
  56  E :    if (heap == process_heap)
  57  i :      return ::HeapAlloc(heap, flags, bytes);
  58    :  
  59  E :    HeapProxy* proxy = HeapProxy::FromHandle(heap);
  60  E :    if (!proxy)
  61  i :      return NULL;
  62    :  
  63  E :    return proxy->Alloc(flags, bytes);
  64  E :  }
  65    :  
  66    :  LPVOID WINAPI asan_HeapReAlloc(HANDLE heap,
  67    :                                 DWORD flags,
  68    :                                 LPVOID mem,
  69  E :                                 SIZE_T bytes) {
  70  E :    if (heap == process_heap)
  71  i :      return ::HeapReAlloc(heap, flags, mem, bytes);
  72    :  
  73  E :    HeapProxy* proxy = HeapProxy::FromHandle(heap);
  74  E :    if (!proxy)
  75  i :      return NULL;
  76    :  
  77  E :    return proxy->ReAlloc(flags, mem, bytes);
  78  E :  }
  79    :  
  80    :  BOOL WINAPI asan_HeapFree(HANDLE heap,
  81    :                            DWORD flags,
  82  E :                            LPVOID mem) {
  83  E :    if (heap == process_heap)
  84  i :      return ::HeapFree(heap, flags, mem);
  85    :  
  86  E :    HeapProxy* proxy = HeapProxy::FromHandle(heap);
  87  E :    if (!proxy)
  88  i :      return FALSE;
  89    :  
  90  E :    return proxy->Free(flags, mem);
  91  E :  }
  92    :  
  93    :  SIZE_T WINAPI asan_HeapSize(HANDLE heap,
  94    :                              DWORD flags,
  95  E :                              LPCVOID mem) {
  96  E :    if (heap == process_heap)
  97  i :      return ::HeapSize(heap, flags, mem);
  98    :  
  99  E :    HeapProxy* proxy = HeapProxy::FromHandle(heap);
 100  E :    if (!proxy)
 101  i :      return -1;
 102    :  
 103  E :    return proxy->Size(flags, mem);
 104  E :  }
 105    :  
 106    :  BOOL WINAPI asan_HeapValidate(HANDLE heap,
 107    :                                DWORD flags,
 108  E :                                LPCVOID mem) {
 109  E :    if (heap == process_heap)
 110  i :      return ::HeapValidate(heap, flags, mem);
 111    :  
 112  E :    HeapProxy* proxy = HeapProxy::FromHandle(heap);
 113  E :    if (!proxy)
 114  i :      return FALSE;
 115    :  
 116  E :    return proxy->Validate(flags, mem);
 117  E :  }
 118    :  
 119    :  SIZE_T WINAPI asan_HeapCompact(HANDLE heap,
 120  E :                                 DWORD flags) {
 121  E :    if (heap == process_heap)
 122  i :      return ::HeapCompact(heap, flags);
 123    :  
 124  E :    HeapProxy* proxy = HeapProxy::FromHandle(heap);
 125  E :    if (!proxy)
 126  i :      return 0;
 127    :  
 128  E :    return proxy->Compact(flags);
 129  E :  }
 130    :  
 131  E :  BOOL WINAPI asan_HeapLock(HANDLE heap) {
 132  E :    if (heap == process_heap)
 133  i :      return ::HeapLock(heap);
 134    :  
 135  E :    HeapProxy* proxy = HeapProxy::FromHandle(heap);
 136  E :    if (!proxy)
 137  i :      return FALSE;
 138    :  
 139  E :    return proxy->Lock();
 140  E :  }
 141    :  
 142  E :  BOOL WINAPI asan_HeapUnlock(HANDLE heap) {
 143  E :    if (heap == process_heap)
 144  i :      return ::HeapUnlock(heap);
 145    :  
 146  E :    HeapProxy* proxy = HeapProxy::FromHandle(heap);
 147  E :    if (!proxy)
 148  i :      return FALSE;
 149    :  
 150  E :    return proxy->Unlock();
 151  E :  }
 152    :  
 153    :  BOOL WINAPI asan_HeapWalk(HANDLE heap,
 154  E :                            LPPROCESS_HEAP_ENTRY entry) {
 155  E :    if (heap == process_heap)
 156  i :      return ::HeapWalk(heap, entry);
 157    :  
 158  E :    HeapProxy* proxy = HeapProxy::FromHandle(heap);
 159  E :    if (!proxy)
 160  i :      return FALSE;
 161    :  
 162  E :    return proxy->Walk(entry);
 163  E :  }
 164    :  
 165    :  BOOL WINAPI asan_HeapSetInformation(
 166    :      HANDLE heap, HEAP_INFORMATION_CLASS info_class,
 167  E :      PVOID info, SIZE_T info_length) {
 168  E :    if (heap == process_heap)
 169  i :      return ::HeapSetInformation(heap, info_class, info, info_length);
 170    :  
 171  E :    HeapProxy* proxy = HeapProxy::FromHandle(heap);
 172  E :    if (!proxy)
 173  i :      return FALSE;
 174    :  
 175  E :    return proxy->SetInformation(info_class, info, info_length);
 176  E :  }
 177    :  
 178    :  BOOL WINAPI asan_HeapQueryInformation(
 179    :      HANDLE heap, HEAP_INFORMATION_CLASS info_class,
 180  E :      PVOID info, SIZE_T info_length, PSIZE_T return_length) {
 181  E :    if (heap == process_heap) {
 182    :      return ::HeapQueryInformation(heap,
 183    :                                    info_class,
 184    :                                    info,
 185    :                                    info_length,
 186  i :                                    return_length);
 187    :    }
 188    :  
 189  E :    HeapProxy* proxy = HeapProxy::FromHandle(heap);
 190  E :    if (!proxy)
 191  i :      return FALSE;
 192    :  
 193    :    bool ret = proxy->QueryInformation(info_class,
 194    :                                       info,
 195    :                                       info_length,
 196  E :                                       return_length);
 197  E :    return ret == true;
 198  E :  }
 199    :  
 200    :  }  // extern "C"
 201    :  
 202    :  namespace agent {
 203    :  namespace asan {
 204    :  
 205  E :  void __cdecl CheckAccessSlow(const uint8* location) {
 206  E :    if (!Shadow::IsAccessible(location)) {
 207  i :      LOG(FATAL) << "Invalid write access to location "
 208    :                 << reinterpret_cast<const void*>(location);
 209    :    }
 210  E :  }
 211    :  
 212    :  }  // namespace asan
 213    :  }  // namespace agent
 214    :  
 215    :  // On entry, eax is the byte to check, e.g. the last byte accessed.
 216    :  // On stack above the return address we have the saved values of eax.
 217  E :  extern "C" __declspec(naked) void asan_check_access() {
 218    :    __asm {
 219    :      // Save the flags and save eax for the slow case.
 220  E :      pushfd
 221  E :      push eax
 222    :  
 223    :      // Check for zero shadow - fast case.
 224  E :      shr eax, 3
 225  E :      mov al, byte ptr[eax + agent::asan::Shadow::shadow_]
 226  E :      test al, 0xFF
 227    :  
 228    :      // Uh-oh - non-zero shadow byte means we go to the slow case.
 229  E :      jne non_zero_shadow
 230    :  
 231    :      // Drop the slow path's copy of the address.
 232  E :      add esp, 4
 233    :      // Restore flags and original eax.
 234  E :      popfd
 235  E :      mov eax, DWORD PTR[esp + 4]
 236  E :      ret 4
 237    :  
 238    :   non_zero_shadow:
 239    :      // Save ecx/edx, they're caller-save.
 240  E :      push edx
 241  E :      push ecx
 242    :      // Push the address to check.
 243  E :      push dword ptr[esp + 8]
 244  E :      call agent::asan::CheckAccessSlow
 245  E :      add esp, 4
 246    :  
 247    :      // Restore everything.
 248  E :      pop ecx
 249  E :      pop edx
 250  E :      add esp, 4
 251  E :      popfd
 252  E :      mov eax, DWORD PTR[esp + 4]
 253  E :      ret 4
 254    :    }
 255    :  }

Coverage information generated Thu Sep 06 11:30:46 2012.