1*673dc3d4SNico Weber #include "sanitizer\allocator_interface.h"
2*673dc3d4SNico Weber #include <cassert>
3*673dc3d4SNico Weber #include <stdio.h>
4*673dc3d4SNico Weber #include <windows.h>
5*673dc3d4SNico Weber 
6*673dc3d4SNico Weber // RUN: %clang_cl_asan %s -o%t
7*673dc3d4SNico Weber // RUN: %env_asan_opts=windows_hook_rtl_allocators=true %run %t 2>&1 | FileCheck %s
8*673dc3d4SNico Weber // UNSUPPORTED: asan-64-bits
9*673dc3d4SNico Weber 
10*673dc3d4SNico Weber using AllocateFunctionPtr = PVOID(__stdcall *)(PVOID, ULONG, SIZE_T);
11*673dc3d4SNico Weber using ReAllocateFunctionPtr = PVOID(__stdcall *)(PVOID, ULONG, PVOID, SIZE_T);
12*673dc3d4SNico Weber 
13*673dc3d4SNico Weber using FreeFunctionPtr = PVOID(__stdcall *)(PVOID, ULONG, PVOID);
14*673dc3d4SNico Weber 
main()15*673dc3d4SNico Weber int main() {
16*673dc3d4SNico Weber   HMODULE NtDllHandle = GetModuleHandle("ntdll.dll");
17*673dc3d4SNico Weber   if (!NtDllHandle) {
18*673dc3d4SNico Weber     puts("Couldn't load ntdll??");
19*673dc3d4SNico Weber     return -1;
20*673dc3d4SNico Weber   }
21*673dc3d4SNico Weber 
22*673dc3d4SNico Weber   auto RtlAllocateHeap_ptr = (AllocateFunctionPtr)GetProcAddress(NtDllHandle, "RtlAllocateHeap");
23*673dc3d4SNico Weber   if (RtlAllocateHeap_ptr == 0) {
24*673dc3d4SNico Weber     puts("Couldn't find RtlAllocateHeap");
25*673dc3d4SNico Weber     return -1;
26*673dc3d4SNico Weber   }
27*673dc3d4SNico Weber 
28*673dc3d4SNico Weber   auto RtlReAllocateHeap_ptr = (ReAllocateFunctionPtr)GetProcAddress(NtDllHandle, "RtlReAllocateHeap");
29*673dc3d4SNico Weber   if (RtlReAllocateHeap_ptr == 0) {
30*673dc3d4SNico Weber     puts("Couldn't find RtlReAllocateHeap");
31*673dc3d4SNico Weber     return -1;
32*673dc3d4SNico Weber   }
33*673dc3d4SNico Weber 
34*673dc3d4SNico Weber   //owned by rtl
35*673dc3d4SNico Weber   void *alloc = RtlAllocateHeap_ptr(GetProcessHeap(),
36*673dc3d4SNico Weber                                     HEAP_GENERATE_EXCEPTIONS | HEAP_ZERO_MEMORY, 100);
37*673dc3d4SNico Weber   assert(alloc);
38*673dc3d4SNico Weber   for (int i = 0; i < 100; i++) {
39*673dc3d4SNico Weber     assert(((char *)alloc)[i] == 0);
40*673dc3d4SNico Weber     ((char *)alloc)[i] = '\xcc';
41*673dc3d4SNico Weber   }
42*673dc3d4SNico Weber 
43*673dc3d4SNico Weber   // still owned by rtl
44*673dc3d4SNico Weber   alloc = RtlReAllocateHeap_ptr(GetProcessHeap(),
45*673dc3d4SNico Weber                                 HEAP_GENERATE_EXCEPTIONS | HEAP_ZERO_MEMORY, alloc, 500);
46*673dc3d4SNico Weber   assert(alloc && !__sanitizer_get_ownership(alloc) && HeapValidate(GetProcessHeap(), 0, alloc));
47*673dc3d4SNico Weber   for (int i = 0; i < 100; i++) {
48*673dc3d4SNico Weber     assert(((char *)alloc)[i] == '\xcc');
49*673dc3d4SNico Weber   }
50*673dc3d4SNico Weber   for (int i = 100; i < 500; i++) {
51*673dc3d4SNico Weber     assert(((char *)alloc)[i] == 0);
52*673dc3d4SNico Weber     ((char *)alloc)[i] = '\xcc';
53*673dc3d4SNico Weber   }
54*673dc3d4SNico Weber 
55*673dc3d4SNico Weber   //convert to asan owned
56*673dc3d4SNico Weber   void *realloc = RtlReAllocateHeap_ptr(GetProcessHeap(),
57*673dc3d4SNico Weber                                         HEAP_ZERO_MEMORY, alloc, 600);
58*673dc3d4SNico Weber   alloc = nullptr;
59*673dc3d4SNico Weber   assert(realloc && __sanitizer_get_ownership(realloc));
60*673dc3d4SNico Weber 
61*673dc3d4SNico Weber   for (int i = 0; i < 500; i++) {
62*673dc3d4SNico Weber     assert(((char *)realloc)[i] == '\xcc');
63*673dc3d4SNico Weber   }
64*673dc3d4SNico Weber   for (int i = 500; i < 600; i++) {
65*673dc3d4SNico Weber     assert(((char *)realloc)[i] == 0);
66*673dc3d4SNico Weber     ((char *)realloc)[i] = '\xcc';
67*673dc3d4SNico Weber   }
68*673dc3d4SNico Weber   realloc = RtlReAllocateHeap_ptr(GetProcessHeap(),
69*673dc3d4SNico Weber                                   HEAP_ZERO_MEMORY, realloc, 2048);
70*673dc3d4SNico Weber   assert(realloc && __sanitizer_get_ownership(realloc));
71*673dc3d4SNico Weber 
72*673dc3d4SNico Weber   for (int i = 0; i < 600; i++) {
73*673dc3d4SNico Weber     assert(((char *)realloc)[i] == '\xcc');
74*673dc3d4SNico Weber   }
75*673dc3d4SNico Weber   for (int i = 600; i < 2048; i++) {
76*673dc3d4SNico Weber     assert(((char *)realloc)[i] == 0);
77*673dc3d4SNico Weber     ((char *)realloc)[i] = '\xcc';
78*673dc3d4SNico Weber   }
79*673dc3d4SNico Weber   //convert back to rtl owned;
80*673dc3d4SNico Weber   alloc = RtlReAllocateHeap_ptr(GetProcessHeap(),
81*673dc3d4SNico Weber                                 HEAP_ZERO_MEMORY | HEAP_GENERATE_EXCEPTIONS, realloc, 100);
82*673dc3d4SNico Weber   assert(alloc && !__sanitizer_get_ownership(alloc) && HeapValidate(GetProcessHeap(), 0, alloc));
83*673dc3d4SNico Weber   for (int i = 0; i < 100; i++) {
84*673dc3d4SNico Weber     assert(((char *)alloc)[i] == '\xcc');
85*673dc3d4SNico Weber     ((char *)alloc)[i] = 0;
86*673dc3d4SNico Weber   }
87*673dc3d4SNico Weber 
88*673dc3d4SNico Weber   auto usable_size = HeapSize(GetProcessHeap(), 0, alloc);
89*673dc3d4SNico Weber   for (int i = 100; i < usable_size; i++) {
90*673dc3d4SNico Weber     assert(((char *)alloc)[i] == 0);
91*673dc3d4SNico Weber   }
92*673dc3d4SNico Weber 
93*673dc3d4SNico Weber   printf("Success\n");
94*673dc3d4SNico Weber }
95*673dc3d4SNico Weber 
96*673dc3d4SNico Weber // CHECK-NOT: Assertion failed:
97*673dc3d4SNico Weber // CHECK-NOT: AddressSanitizer
98*673dc3d4SNico Weber // CHECK: Success