1*673dc3d4SNico Weber // RUN: %clang_cl_asan /Od /MT -o %t %s
2*673dc3d4SNico Weber // RUN: %env_asan_opts=windows_hook_rtl_allocators=true %run %t 2>&1 | FileCheck %s
3*673dc3d4SNico Weber // UNSUPPORTED: asan-64-bits
4*673dc3d4SNico Weber #include <cassert>
5*673dc3d4SNico Weber #include <iostream>
6*673dc3d4SNico Weber #include <windows.h>
7*673dc3d4SNico Weber 
main()8*673dc3d4SNico Weber int main() {
9*673dc3d4SNico Weber   void *ptr = malloc(0);
10*673dc3d4SNico Weber   if (ptr)
11*673dc3d4SNico Weber     std::cerr << "allocated!\n";
12*673dc3d4SNico Weber   ((char *)ptr)[0] = '\xff'; //check this 'allocate 1 instead of 0' hack hasn't changed
13*673dc3d4SNico Weber 
14*673dc3d4SNico Weber   free(ptr);
15*673dc3d4SNico Weber 
16*673dc3d4SNico Weber   /*
17*673dc3d4SNico Weber         HeapAlloc hack for our asan interceptor is to change 0
18*673dc3d4SNico Weber         sized allocations to size 1 to avoid weird inconsistencies
19*673dc3d4SNico Weber         between how realloc and heaprealloc handle 0 size allocations.
20*673dc3d4SNico Weber 
21*673dc3d4SNico Weber         Note this test relies on these instructions being intercepted.
22*673dc3d4SNico Weber         Without ASAN HeapRealloc on line 27 would return a ptr whose
23*673dc3d4SNico Weber         HeapSize would be 0. This test makes sure that the underlying behavior
24*673dc3d4SNico Weber         of our hack hasn't changed underneath us.
25*673dc3d4SNico Weber 
26*673dc3d4SNico Weber         We can get rid of the test (or change it to test for the correct
27*673dc3d4SNico Weber         behavior) once we fix the interceptor or write a different allocator
28*673dc3d4SNico Weber         to handle 0 sized allocations properly by default.
29*673dc3d4SNico Weber 
30*673dc3d4SNico Weber     */
31*673dc3d4SNico Weber   ptr = HeapAlloc(GetProcessHeap(), 0, 0);
32*673dc3d4SNico Weber   if (!ptr)
33*673dc3d4SNico Weber     return 1;
34*673dc3d4SNico Weber   void *ptr2 = HeapReAlloc(GetProcessHeap(), 0, ptr, 0);
35*673dc3d4SNico Weber   if (!ptr2)
36*673dc3d4SNico Weber     return 1;
37*673dc3d4SNico Weber   size_t heapsize = HeapSize(GetProcessHeap(), 0, ptr2);
38*673dc3d4SNico Weber   if (heapsize != 1) { // will be 0 without ASAN turned on
39*673dc3d4SNico Weber     std::cerr << "HeapAlloc size failure! " << heapsize << " != 1\n";
40*673dc3d4SNico Weber     return 1;
41*673dc3d4SNico Weber   }
42*673dc3d4SNico Weber   void *ptr3 = HeapReAlloc(GetProcessHeap(), 0, ptr2, 3);
43*673dc3d4SNico Weber   if (!ptr3)
44*673dc3d4SNico Weber     return 1;
45*673dc3d4SNico Weber   heapsize = HeapSize(GetProcessHeap(), 0, ptr3);
46*673dc3d4SNico Weber 
47*673dc3d4SNico Weber   if (heapsize != 3) {
48*673dc3d4SNico Weber     std::cerr << "HeapAlloc size failure! " << heapsize << " != 3\n";
49*673dc3d4SNico Weber     return 1;
50*673dc3d4SNico Weber   }
51*673dc3d4SNico Weber   HeapFree(GetProcessHeap(), 0, ptr3);
52*673dc3d4SNico Weber   return 0;
53*673dc3d4SNico Weber }
54*673dc3d4SNico Weber 
55*673dc3d4SNico Weber // CHECK: allocated!
56*673dc3d4SNico Weber // CHECK-NOT: heap-buffer-overflow
57*673dc3d4SNico Weber // CHECK-NOT: AddressSanitizer
58*673dc3d4SNico Weber // CHECK-NOT: HeapAlloc size failure!