1 // RUN: %clang_cl_asan -LD /Od -DDLL %s -Fe%t.dll
2 // RUN: %clang_cl /Od -DEXE %s -Fe%te.exe
3 // RUN: %env_asan_opts=windows_hook_rtl_allocators=true not %run %te.exe %t.dll 2>&1 | FileCheck %s
4 // REQUIRES: asan-dynamic-runtime
5 // REQUIRES: asan-32-bits
6 // REQUIRES: asan-rtl-heap-interception
7 
8 #include <cassert>
9 #include <stdio.h>
10 #include <windows.h>
11 
12 extern "C" {
13 #if defined(EXE)
14 using AllocateFunctionPtr = PVOID(__stdcall *)(PVOID, ULONG, SIZE_T);
15 using FreeFunctionPtr = PVOID(__stdcall *)(PVOID, ULONG, PVOID);
16 
main(int argc,char ** argv)17 int main(int argc, char **argv) {
18   HMODULE NtDllHandle = GetModuleHandle("ntdll.dll");
19   if (!NtDllHandle) {
20     puts("Couldn't load ntdll??");
21     return -1;
22   }
23 
24   auto RtlAllocateHeap_ptr =
25       (AllocateFunctionPtr)GetProcAddress(NtDllHandle, "RtlAllocateHeap");
26   if (RtlAllocateHeap_ptr == 0) {
27     puts("Couldn't RtlAllocateHeap");
28     return -1;
29   }
30 
31   auto RtlFreeHeap_ptr =
32       (FreeFunctionPtr)GetProcAddress(NtDllHandle, "RtlFreeHeap");
33   if (RtlFreeHeap_ptr == 0) {
34     puts("Couldn't get RtlFreeHeap");
35     return -1;
36   }
37 
38   char *buffer;
39   buffer = (char *)RtlAllocateHeap_ptr(GetProcessHeap(), 0, 32);
40 
41   HMODULE lib = LoadLibraryA(argv[1]);
42   assert(lib != INVALID_HANDLE_VALUE);
43   assert(0 != FreeLibrary(lib));
44 
45   if (!RtlFreeHeap_ptr(GetProcessHeap(), 0, buffer)) {
46     puts("Couldn't RtlFreeHeap");
47     return -1;
48   }
49   // Because this pointer was allocated pre-hooking,
50   // this will dump as a nested bug. Asan attempts to free
51   // the pointer and AV's, so the ASAN exception handler
52   // will dump as a 'nested bug'.
53   RtlFreeHeap_ptr(GetProcessHeap(), 0, buffer);
54 }
55 
56 #elif defined(DLL)
57 // This global is registered at startup.
58 
59 BOOL WINAPI DllMain(HMODULE, DWORD reason, LPVOID) {
60   fprintf(stderr, "in DLL(reason=%d)\n", (int)reason);
61   fflush(0);
62   return TRUE;
63 }
64 
65 // CHECK: in DLL(reason=1)
66 // CHECK: in DLL(reason=0)
67 // CHECK: AddressSanitizer: nested bug in the same thread, aborting.
68 
69 #else
70 #error oops!
71 #endif
72 }
73