xref: /openbsd-src/gnu/llvm/compiler-rt/lib/interception/tests/interception_win_test.cpp (revision 810390e339a5425391477d5d41c78d7cab2424ac)
1 //===-- interception_win_test.cpp -----------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file is a part of ThreadSanitizer/AddressSanitizer runtime.
10 // Tests for interception_win.h.
11 //
12 //===----------------------------------------------------------------------===//
13 #include "interception/interception.h"
14 
15 #include "gtest/gtest.h"
16 
17 // Too slow for debug build
18 #if !SANITIZER_DEBUG
19 #if SANITIZER_WINDOWS
20 
21 #define WIN32_LEAN_AND_MEAN
22 #include <windows.h>
23 
24 namespace __interception {
25 namespace {
26 
27 enum FunctionPrefixKind {
28   FunctionPrefixNone,
29   FunctionPrefixPadding,
30   FunctionPrefixHotPatch,
31   FunctionPrefixDetour,
32 };
33 
34 typedef bool (*TestOverrideFunction)(uptr, uptr, uptr*);
35 typedef int (*IdentityFunction)(int);
36 
37 #if SANITIZER_WINDOWS64
38 
39 const u8 kIdentityCodeWithPrologue[] = {
40     0x55,                   // push        rbp
41     0x48, 0x89, 0xE5,       // mov         rbp,rsp
42     0x8B, 0xC1,             // mov         eax,ecx
43     0x5D,                   // pop         rbp
44     0xC3,                   // ret
45 };
46 
47 const u8 kIdentityCodeWithPushPop[] = {
48     0x55,                   // push        rbp
49     0x48, 0x89, 0xE5,       // mov         rbp,rsp
50     0x53,                   // push        rbx
51     0x50,                   // push        rax
52     0x58,                   // pop         rax
53     0x8B, 0xC1,             // mov         rax,rcx
54     0x5B,                   // pop         rbx
55     0x5D,                   // pop         rbp
56     0xC3,                   // ret
57 };
58 
59 const u8 kIdentityTwiceOffset = 16;
60 const u8 kIdentityTwice[] = {
61     0x55,                   // push        rbp
62     0x48, 0x89, 0xE5,       // mov         rbp,rsp
63     0x8B, 0xC1,             // mov         eax,ecx
64     0x5D,                   // pop         rbp
65     0xC3,                   // ret
66     0x90, 0x90, 0x90, 0x90,
67     0x90, 0x90, 0x90, 0x90,
68     0x55,                   // push        rbp
69     0x48, 0x89, 0xE5,       // mov         rbp,rsp
70     0x8B, 0xC1,             // mov         eax,ecx
71     0x5D,                   // pop         rbp
72     0xC3,                   // ret
73 };
74 
75 const u8 kIdentityCodeWithMov[] = {
76     0x89, 0xC8,             // mov         eax, ecx
77     0xC3,                   // ret
78 };
79 
80 const u8 kIdentityCodeWithJump[] = {
81     0xE9, 0x04, 0x00, 0x00,
82     0x00,                   // jmp + 4
83     0xCC, 0xCC, 0xCC, 0xCC,
84     0x89, 0xC8,             // mov         eax, ecx
85     0xC3,                   // ret
86 };
87 
88 const u8 kIdentityCodeWithJumpBackwards[] = {
89     0x89, 0xC8,  // mov         eax, ecx
90     0xC3,        // ret
91     0xE9, 0xF8, 0xFF, 0xFF,
92     0xFF,  // jmp - 8
93     0xCC, 0xCC, 0xCC, 0xCC,
94 };
95 const u8 kIdentityCodeWithJumpBackwardsOffset = 3;
96 
97 #    else
98 
99 const u8 kIdentityCodeWithPrologue[] = {
100     0x55,                   // push        ebp
101     0x8B, 0xEC,             // mov         ebp,esp
102     0x8B, 0x45, 0x08,       // mov         eax,dword ptr [ebp + 8]
103     0x5D,                   // pop         ebp
104     0xC3,                   // ret
105 };
106 
107 const u8 kIdentityCodeWithPushPop[] = {
108     0x55,                   // push        ebp
109     0x8B, 0xEC,             // mov         ebp,esp
110     0x53,                   // push        ebx
111     0x50,                   // push        eax
112     0x58,                   // pop         eax
113     0x8B, 0x45, 0x08,       // mov         eax,dword ptr [ebp + 8]
114     0x5B,                   // pop         ebx
115     0x5D,                   // pop         ebp
116     0xC3,                   // ret
117 };
118 
119 const u8 kIdentityTwiceOffset = 8;
120 const u8 kIdentityTwice[] = {
121     0x55,                   // push        ebp
122     0x8B, 0xEC,             // mov         ebp,esp
123     0x8B, 0x45, 0x08,       // mov         eax,dword ptr [ebp + 8]
124     0x5D,                   // pop         ebp
125     0xC3,                   // ret
126     0x55,                   // push        ebp
127     0x8B, 0xEC,             // mov         ebp,esp
128     0x8B, 0x45, 0x08,       // mov         eax,dword ptr [ebp + 8]
129     0x5D,                   // pop         ebp
130     0xC3,                   // ret
131 };
132 
133 const u8 kIdentityCodeWithMov[] = {
134     0x8B, 0x44, 0x24, 0x04, // mov         eax,dword ptr [esp + 4]
135     0xC3,                   // ret
136 };
137 
138 const u8 kIdentityCodeWithJump[] = {
139     0xE9, 0x04, 0x00, 0x00,
140     0x00,                   // jmp + 4
141     0xCC, 0xCC, 0xCC, 0xCC,
142     0x8B, 0x44, 0x24, 0x04, // mov         eax,dword ptr [esp + 4]
143     0xC3,                   // ret
144 };
145 
146 const u8 kIdentityCodeWithJumpBackwards[] = {
147     0x8B, 0x44, 0x24, 0x04,  // mov         eax,dword ptr [esp + 4]
148     0xC3,                    // ret
149     0xE9, 0xF6, 0xFF, 0xFF,
150     0xFF,  // jmp - 10
151     0xCC, 0xCC, 0xCC, 0xCC,
152 };
153 const u8 kIdentityCodeWithJumpBackwardsOffset = 5;
154 
155 #    endif
156 
157 const u8 kPatchableCode1[] = {
158     0xB8, 0x4B, 0x00, 0x00, 0x00,   // mov eax,4B
159     0x33, 0xC9,                     // xor ecx,ecx
160     0xC3,                           // ret
161 };
162 
163 const u8 kPatchableCode2[] = {
164     0x55,                           // push ebp
165     0x8B, 0xEC,                     // mov ebp,esp
166     0x33, 0xC0,                     // xor eax,eax
167     0x5D,                           // pop ebp
168     0xC3,                           // ret
169 };
170 
171 const u8 kPatchableCode3[] = {
172     0x55,                           // push ebp
173     0x8B, 0xEC,                     // mov ebp,esp
174     0x6A, 0x00,                     // push 0
175     0xE8, 0x3D, 0xFF, 0xFF, 0xFF,   // call <func>
176 };
177 
178 const u8 kPatchableCode4[] = {
179     0xE9, 0xCC, 0xCC, 0xCC, 0xCC,   // jmp <label>
180     0x90, 0x90, 0x90, 0x90,
181 };
182 
183 const u8 kPatchableCode5[] = {
184     0x55,                                      // push    ebp
185     0x8b, 0xec,                                // mov     ebp,esp
186     0x8d, 0xa4, 0x24, 0x30, 0xfd, 0xff, 0xff,  // lea     esp,[esp-2D0h]
187     0x54,                                      // push    esp
188 };
189 
190 #if SANITIZER_WINDOWS64
191 u8 kLoadGlobalCode[] = {
192   0x8B, 0x05, 0x00, 0x00, 0x00, 0x00, // mov    eax [rip + global]
193   0xC3,                               // ret
194 };
195 #endif
196 
197 const u8 kUnpatchableCode1[] = {
198     0xC3,                           // ret
199 };
200 
201 const u8 kUnpatchableCode2[] = {
202     0x33, 0xC9,                     // xor ecx,ecx
203     0xC3,                           // ret
204 };
205 
206 const u8 kUnpatchableCode3[] = {
207     0x75, 0xCC,                     // jne <label>
208     0x33, 0xC9,                     // xor ecx,ecx
209     0xC3,                           // ret
210 };
211 
212 const u8 kUnpatchableCode4[] = {
213     0x74, 0xCC,                     // jne <label>
214     0x33, 0xC9,                     // xor ecx,ecx
215     0xC3,                           // ret
216 };
217 
218 const u8 kUnpatchableCode5[] = {
219     0xEB, 0x02,                     // jmp <label>
220     0x33, 0xC9,                     // xor ecx,ecx
221     0xC3,                           // ret
222 };
223 
224 const u8 kUnpatchableCode6[] = {
225     0xE8, 0xCC, 0xCC, 0xCC, 0xCC,   // call <func>
226     0x90, 0x90, 0x90, 0x90,
227 };
228 
229 const u8 kUnpatchableCode7[] = {
230     0x33, 0xc0,                     // xor     eax,eax
231     0x48, 0x85, 0xd2,               // test    rdx,rdx
232     0x74, 0x10,                     // je      +16  (unpatchable)
233 };
234 
235 const u8 kUnpatchableCode8[] = {
236     0x48, 0x8b, 0xc1,               // mov     rax,rcx
237     0x0f, 0xb7, 0x10,               // movzx   edx,word ptr [rax]
238     0x48, 0x83, 0xc0, 0x02,         // add     rax,2
239     0x66, 0x85, 0xd2,               // test    dx,dx
240     0x75, 0xf4,                     // jne     -12  (unpatchable)
241 };
242 
243 const u8 kUnpatchableCode9[] = {
244     0x4c, 0x8b, 0xc1,               // mov     r8,rcx
245     0x8a, 0x01,                     // mov     al,byte ptr [rcx]
246     0x48, 0xff, 0xc1,               // inc     rcx
247     0x84, 0xc0,                     // test    al,al
248     0x75, 0xf7,                     // jne     -9  (unpatchable)
249 };
250 
251 const u8 kPatchableCode6[] = {
252     0x48, 0x89, 0x54, 0x24, 0xBB, // mov QWORD PTR [rsp + 0xBB], rdx
253     0x33, 0xC9,                   // xor ecx,ecx
254     0xC3,                         // ret
255 };
256 
257 const u8 kPatchableCode7[] = {
258     0x4c, 0x89, 0x4c, 0x24, 0xBB,  // mov QWORD PTR [rsp + 0xBB], r9
259     0x33, 0xC9,                   // xor ecx,ecx
260     0xC3,                         // ret
261 };
262 
263 const u8 kPatchableCode8[] = {
264     0x4c, 0x89, 0x44, 0x24, 0xBB, // mov QWORD PTR [rsp + 0xBB], r8
265     0x33, 0xC9,                   // xor ecx,ecx
266     0xC3,                         // ret
267 };
268 
269 const u8 kPatchableCode9[] = {
270     0x8a, 0x01,                     // al,byte ptr [rcx]
271     0x45, 0x33, 0xc0,               // xor     r8d,r8d
272     0x84, 0xc0,                     // test    al,al
273 };
274 
275 const u8 kPatchableCode10[] = {
276     0x45, 0x33, 0xc0,               // xor     r8d,r8d
277     0x41, 0x8b, 0xc0,               // mov     eax,r8d
278     0x48, 0x85, 0xd2,               // test    rdx,rdx
279 };
280 
281 const u8 kPatchableCode11[] = {
282     0x48, 0x83, 0xec, 0x38,         // sub     rsp,38h
283     0x83, 0x64, 0x24, 0x28, 0x00,   // and     dword ptr [rsp+28h],0
284 };
285 
286 // A buffer holding the dynamically generated code under test.
287 u8* ActiveCode;
288 const size_t ActiveCodeLength = 4096;
289 
290 int InterceptorFunction(int x);
291 
292 /// Allocate code memory more than 2GB away from Base.
AllocateCode2GBAway(u8 * Base)293 u8 *AllocateCode2GBAway(u8 *Base) {
294   // Find a 64K aligned location after Base plus 2GB.
295   size_t TwoGB = 0x80000000;
296   size_t AllocGranularity = 0x10000;
297   Base = (u8 *)((((uptr)Base + TwoGB + AllocGranularity)) & ~(AllocGranularity - 1));
298 
299   // Check if that location is free, and if not, loop over regions until we find
300   // one that is.
301   MEMORY_BASIC_INFORMATION mbi = {};
302   while (sizeof(mbi) == VirtualQuery(Base, &mbi, sizeof(mbi))) {
303     if (mbi.State & MEM_FREE) break;
304     Base += mbi.RegionSize;
305   }
306 
307   // Allocate one RWX page at the free location.
308   return (u8 *)::VirtualAlloc(Base, ActiveCodeLength, MEM_COMMIT | MEM_RESERVE,
309                               PAGE_EXECUTE_READWRITE);
310 }
311 
312 template<class T>
LoadActiveCode(const T & code,uptr * entry_point,FunctionPrefixKind prefix_kind=FunctionPrefixNone)313 static void LoadActiveCode(
314     const T &code,
315     uptr *entry_point,
316     FunctionPrefixKind prefix_kind = FunctionPrefixNone) {
317   if (ActiveCode == nullptr) {
318     ActiveCode = AllocateCode2GBAway((u8*)&InterceptorFunction);
319     ASSERT_NE(ActiveCode, nullptr) << "failed to allocate RWX memory 2GB away";
320   }
321 
322   size_t position = 0;
323 
324   // Add padding to avoid memory violation when scanning the prefix.
325   for (int i = 0; i < 16; ++i)
326     ActiveCode[position++] = 0xC3;  // Instruction 'ret'.
327 
328   // Add function padding.
329   size_t padding = 0;
330   if (prefix_kind == FunctionPrefixPadding)
331     padding = 16;
332   else if (prefix_kind == FunctionPrefixDetour ||
333            prefix_kind == FunctionPrefixHotPatch)
334     padding = FIRST_32_SECOND_64(5, 6);
335   // Insert |padding| instructions 'nop'.
336   for (size_t i = 0; i < padding; ++i)
337     ActiveCode[position++] = 0x90;
338 
339   // Keep track of the entry point.
340   *entry_point = (uptr)&ActiveCode[position];
341 
342   // Add the detour instruction (i.e. mov edi, edi)
343   if (prefix_kind == FunctionPrefixDetour) {
344 #if SANITIZER_WINDOWS64
345     // Note that "mov edi,edi" is NOP in 32-bit only, in 64-bit it clears
346     // higher bits of RDI.
347     // Use 66,90H as NOP for Windows64.
348     ActiveCode[position++] = 0x66;
349     ActiveCode[position++] = 0x90;
350 #else
351     // mov edi,edi.
352     ActiveCode[position++] = 0x8B;
353     ActiveCode[position++] = 0xFF;
354 #endif
355 
356   }
357 
358   // Copy the function body.
359   for (size_t i = 0; i < sizeof(T); ++i)
360     ActiveCode[position++] = code[i];
361 }
362 
363 int InterceptorFunctionCalled;
364 IdentityFunction InterceptedRealFunction;
365 
InterceptorFunction(int x)366 int InterceptorFunction(int x) {
367   ++InterceptorFunctionCalled;
368   return InterceptedRealFunction(x);
369 }
370 
371 }  // namespace
372 
373 // Tests for interception_win.h
TEST(Interception,InternalGetProcAddress)374 TEST(Interception, InternalGetProcAddress) {
375   HMODULE ntdll_handle = ::GetModuleHandle("ntdll");
376   ASSERT_NE(nullptr, ntdll_handle);
377   uptr DbgPrint_expected = (uptr)::GetProcAddress(ntdll_handle, "DbgPrint");
378   uptr isdigit_expected = (uptr)::GetProcAddress(ntdll_handle, "isdigit");
379   uptr DbgPrint_adddress = InternalGetProcAddress(ntdll_handle, "DbgPrint");
380   uptr isdigit_address = InternalGetProcAddress(ntdll_handle, "isdigit");
381 
382   EXPECT_EQ(DbgPrint_expected, DbgPrint_adddress);
383   EXPECT_EQ(isdigit_expected, isdigit_address);
384   EXPECT_NE(DbgPrint_adddress, isdigit_address);
385 }
386 
387 template <class T>
TestIdentityFunctionPatching(const T & code,TestOverrideFunction override,FunctionPrefixKind prefix_kind=FunctionPrefixNone,int function_start_offset=0)388 static void TestIdentityFunctionPatching(
389     const T &code, TestOverrideFunction override,
390     FunctionPrefixKind prefix_kind = FunctionPrefixNone,
391     int function_start_offset = 0) {
392   uptr identity_address;
393   LoadActiveCode(code, &identity_address, prefix_kind);
394   identity_address += function_start_offset;
395   IdentityFunction identity = (IdentityFunction)identity_address;
396 
397   // Validate behavior before dynamic patching.
398   InterceptorFunctionCalled = 0;
399   EXPECT_EQ(0, identity(0));
400   EXPECT_EQ(42, identity(42));
401   EXPECT_EQ(0, InterceptorFunctionCalled);
402 
403   // Patch the function.
404   uptr real_identity_address = 0;
405   bool success = override(identity_address,
406                          (uptr)&InterceptorFunction,
407                          &real_identity_address);
408   EXPECT_TRUE(success);
409   EXPECT_NE(0U, real_identity_address);
410   IdentityFunction real_identity = (IdentityFunction)real_identity_address;
411   InterceptedRealFunction = real_identity;
412 
413   // Don't run tests if hooking failed or the real function is not valid.
414   if (!success || !real_identity_address)
415     return;
416 
417   // Calling the redirected function.
418   InterceptorFunctionCalled = 0;
419   EXPECT_EQ(0, identity(0));
420   EXPECT_EQ(42, identity(42));
421   EXPECT_EQ(2, InterceptorFunctionCalled);
422 
423   // Calling the real function.
424   InterceptorFunctionCalled = 0;
425   EXPECT_EQ(0, real_identity(0));
426   EXPECT_EQ(42, real_identity(42));
427   EXPECT_EQ(0, InterceptorFunctionCalled);
428 
429   TestOnlyReleaseTrampolineRegions();
430 }
431 
432 #    if !SANITIZER_WINDOWS64
TEST(Interception,OverrideFunctionWithDetour)433 TEST(Interception, OverrideFunctionWithDetour) {
434   TestOverrideFunction override = OverrideFunctionWithDetour;
435   FunctionPrefixKind prefix = FunctionPrefixDetour;
436   TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix);
437   TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix);
438   TestIdentityFunctionPatching(kIdentityCodeWithMov, override, prefix);
439   TestIdentityFunctionPatching(kIdentityCodeWithJump, override, prefix);
440 }
441 #endif  // !SANITIZER_WINDOWS64
442 
TEST(Interception,OverrideFunctionWithRedirectJump)443 TEST(Interception, OverrideFunctionWithRedirectJump) {
444   TestOverrideFunction override = OverrideFunctionWithRedirectJump;
445   TestIdentityFunctionPatching(kIdentityCodeWithJump, override);
446   TestIdentityFunctionPatching(kIdentityCodeWithJumpBackwards, override,
447                                FunctionPrefixNone,
448                                kIdentityCodeWithJumpBackwardsOffset);
449 }
450 
TEST(Interception,OverrideFunctionWithHotPatch)451 TEST(Interception, OverrideFunctionWithHotPatch) {
452   TestOverrideFunction override = OverrideFunctionWithHotPatch;
453   FunctionPrefixKind prefix = FunctionPrefixHotPatch;
454   TestIdentityFunctionPatching(kIdentityCodeWithMov, override, prefix);
455 }
456 
TEST(Interception,OverrideFunctionWithTrampoline)457 TEST(Interception, OverrideFunctionWithTrampoline) {
458   TestOverrideFunction override = OverrideFunctionWithTrampoline;
459   FunctionPrefixKind prefix = FunctionPrefixNone;
460   TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix);
461   TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix);
462 
463   prefix = FunctionPrefixPadding;
464   TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix);
465   TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix);
466 }
467 
TEST(Interception,OverrideFunction)468 TEST(Interception, OverrideFunction) {
469   TestOverrideFunction override = OverrideFunction;
470   FunctionPrefixKind prefix = FunctionPrefixNone;
471   TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix);
472   TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix);
473   TestIdentityFunctionPatching(kIdentityCodeWithJump, override, prefix);
474 
475   prefix = FunctionPrefixPadding;
476   TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix);
477   TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix);
478   TestIdentityFunctionPatching(kIdentityCodeWithMov, override, prefix);
479   TestIdentityFunctionPatching(kIdentityCodeWithJump, override, prefix);
480 
481   prefix = FunctionPrefixHotPatch;
482   TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix);
483   TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix);
484   TestIdentityFunctionPatching(kIdentityCodeWithMov, override, prefix);
485   TestIdentityFunctionPatching(kIdentityCodeWithJump, override, prefix);
486 
487   prefix = FunctionPrefixDetour;
488   TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix);
489   TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix);
490   TestIdentityFunctionPatching(kIdentityCodeWithMov, override, prefix);
491   TestIdentityFunctionPatching(kIdentityCodeWithJump, override, prefix);
492 }
493 
494 template<class T>
TestIdentityFunctionMultiplePatching(const T & code,TestOverrideFunction override,FunctionPrefixKind prefix_kind=FunctionPrefixNone)495 static void TestIdentityFunctionMultiplePatching(
496     const T &code,
497     TestOverrideFunction override,
498     FunctionPrefixKind prefix_kind = FunctionPrefixNone) {
499   uptr identity_address;
500   LoadActiveCode(code, &identity_address, prefix_kind);
501 
502   // Patch the function.
503   uptr real_identity_address = 0;
504   bool success = override(identity_address,
505                           (uptr)&InterceptorFunction,
506                           &real_identity_address);
507   EXPECT_TRUE(success);
508   EXPECT_NE(0U, real_identity_address);
509 
510   // Re-patching the function should not work.
511   success = override(identity_address,
512                      (uptr)&InterceptorFunction,
513                      &real_identity_address);
514   EXPECT_FALSE(success);
515 
516   TestOnlyReleaseTrampolineRegions();
517 }
518 
TEST(Interception,OverrideFunctionMultiplePatchingIsFailing)519 TEST(Interception, OverrideFunctionMultiplePatchingIsFailing) {
520 #if !SANITIZER_WINDOWS64
521   TestIdentityFunctionMultiplePatching(kIdentityCodeWithPrologue,
522                                        OverrideFunctionWithDetour,
523                                        FunctionPrefixDetour);
524 #endif
525 
526   TestIdentityFunctionMultiplePatching(kIdentityCodeWithMov,
527                                        OverrideFunctionWithHotPatch,
528                                        FunctionPrefixHotPatch);
529 
530   TestIdentityFunctionMultiplePatching(kIdentityCodeWithPushPop,
531                                        OverrideFunctionWithTrampoline,
532                                        FunctionPrefixPadding);
533 }
534 
TEST(Interception,OverrideFunctionTwice)535 TEST(Interception, OverrideFunctionTwice) {
536   uptr identity_address1;
537   LoadActiveCode(kIdentityTwice, &identity_address1);
538   uptr identity_address2 = identity_address1 + kIdentityTwiceOffset;
539   IdentityFunction identity1 = (IdentityFunction)identity_address1;
540   IdentityFunction identity2 = (IdentityFunction)identity_address2;
541 
542   // Patch the two functions.
543   uptr real_identity_address = 0;
544   EXPECT_TRUE(OverrideFunction(identity_address1,
545                                (uptr)&InterceptorFunction,
546                                &real_identity_address));
547   EXPECT_TRUE(OverrideFunction(identity_address2,
548                                (uptr)&InterceptorFunction,
549                                &real_identity_address));
550   IdentityFunction real_identity = (IdentityFunction)real_identity_address;
551   InterceptedRealFunction = real_identity;
552 
553   // Calling the redirected function.
554   InterceptorFunctionCalled = 0;
555   EXPECT_EQ(42, identity1(42));
556   EXPECT_EQ(42, identity2(42));
557   EXPECT_EQ(2, InterceptorFunctionCalled);
558 
559   TestOnlyReleaseTrampolineRegions();
560 }
561 
562 template<class T>
TestFunctionPatching(const T & code,TestOverrideFunction override,FunctionPrefixKind prefix_kind=FunctionPrefixNone)563 static bool TestFunctionPatching(
564     const T &code,
565     TestOverrideFunction override,
566     FunctionPrefixKind prefix_kind = FunctionPrefixNone) {
567   uptr address;
568   LoadActiveCode(code, &address, prefix_kind);
569   uptr unused_real_address = 0;
570   bool result = override(
571       address, (uptr)&InterceptorFunction, &unused_real_address);
572 
573   TestOnlyReleaseTrampolineRegions();
574   return result;
575 }
576 
TEST(Interception,PatchableFunction)577 TEST(Interception, PatchableFunction) {
578   TestOverrideFunction override = OverrideFunction;
579   // Test without function padding.
580   EXPECT_TRUE(TestFunctionPatching(kPatchableCode1, override));
581   EXPECT_TRUE(TestFunctionPatching(kPatchableCode2, override));
582 #if SANITIZER_WINDOWS64
583   EXPECT_FALSE(TestFunctionPatching(kPatchableCode3, override));
584 #else
585   EXPECT_TRUE(TestFunctionPatching(kPatchableCode3, override));
586 #endif
587   EXPECT_TRUE(TestFunctionPatching(kPatchableCode4, override));
588   EXPECT_TRUE(TestFunctionPatching(kPatchableCode5, override));
589 #if SANITIZER_WINDOWS64
590   EXPECT_TRUE(TestFunctionPatching(kLoadGlobalCode, override));
591 #endif
592 
593   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1, override));
594   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode2, override));
595   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3, override));
596   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4, override));
597   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5, override));
598   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6, override));
599 }
600 
601 #if !SANITIZER_WINDOWS64
TEST(Interception,PatchableFunctionWithDetour)602 TEST(Interception, PatchableFunctionWithDetour) {
603   TestOverrideFunction override = OverrideFunctionWithDetour;
604   // Without the prefix, no function can be detoured.
605   EXPECT_FALSE(TestFunctionPatching(kPatchableCode1, override));
606   EXPECT_FALSE(TestFunctionPatching(kPatchableCode2, override));
607   EXPECT_FALSE(TestFunctionPatching(kPatchableCode3, override));
608   EXPECT_FALSE(TestFunctionPatching(kPatchableCode4, override));
609   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1, override));
610   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode2, override));
611   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3, override));
612   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4, override));
613   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5, override));
614   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6, override));
615 
616   // With the prefix, all functions can be detoured.
617   FunctionPrefixKind prefix = FunctionPrefixDetour;
618   EXPECT_TRUE(TestFunctionPatching(kPatchableCode1, override, prefix));
619   EXPECT_TRUE(TestFunctionPatching(kPatchableCode2, override, prefix));
620   EXPECT_TRUE(TestFunctionPatching(kPatchableCode3, override, prefix));
621   EXPECT_TRUE(TestFunctionPatching(kPatchableCode4, override, prefix));
622   EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode1, override, prefix));
623   EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode2, override, prefix));
624   EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode3, override, prefix));
625   EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode4, override, prefix));
626   EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode5, override, prefix));
627   EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode6, override, prefix));
628 }
629 #endif  // !SANITIZER_WINDOWS64
630 
TEST(Interception,PatchableFunctionWithRedirectJump)631 TEST(Interception, PatchableFunctionWithRedirectJump) {
632   TestOverrideFunction override = OverrideFunctionWithRedirectJump;
633   EXPECT_FALSE(TestFunctionPatching(kPatchableCode1, override));
634   EXPECT_FALSE(TestFunctionPatching(kPatchableCode2, override));
635   EXPECT_FALSE(TestFunctionPatching(kPatchableCode3, override));
636   EXPECT_TRUE(TestFunctionPatching(kPatchableCode4, override));
637   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1, override));
638   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode2, override));
639   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3, override));
640   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4, override));
641   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5, override));
642   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6, override));
643 }
644 
TEST(Interception,PatchableFunctionWithHotPatch)645 TEST(Interception, PatchableFunctionWithHotPatch) {
646   TestOverrideFunction override = OverrideFunctionWithHotPatch;
647   FunctionPrefixKind prefix = FunctionPrefixHotPatch;
648 
649   EXPECT_TRUE(TestFunctionPatching(kPatchableCode1, override, prefix));
650   EXPECT_FALSE(TestFunctionPatching(kPatchableCode2, override, prefix));
651   EXPECT_FALSE(TestFunctionPatching(kPatchableCode3, override, prefix));
652   EXPECT_FALSE(TestFunctionPatching(kPatchableCode4, override, prefix));
653 #if SANITIZER_WINDOWS64
654   EXPECT_TRUE(TestFunctionPatching(kPatchableCode6, override, prefix));
655   EXPECT_TRUE(TestFunctionPatching(kPatchableCode7, override, prefix));
656   EXPECT_TRUE(TestFunctionPatching(kPatchableCode8, override, prefix));
657 #endif
658   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1, override, prefix));
659   EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode2, override, prefix));
660   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3, override, prefix));
661   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4, override, prefix));
662   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5, override, prefix));
663   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6, override, prefix));
664 }
665 
TEST(Interception,PatchableFunctionWithTrampoline)666 TEST(Interception, PatchableFunctionWithTrampoline) {
667   TestOverrideFunction override = OverrideFunctionWithTrampoline;
668   FunctionPrefixKind prefix = FunctionPrefixPadding;
669 
670   EXPECT_TRUE(TestFunctionPatching(kPatchableCode1, override, prefix));
671   EXPECT_TRUE(TestFunctionPatching(kPatchableCode2, override, prefix));
672 #if SANITIZER_WINDOWS64
673   EXPECT_FALSE(TestFunctionPatching(kPatchableCode3, override, prefix));
674   EXPECT_TRUE(TestFunctionPatching(kPatchableCode9, override, prefix));
675   EXPECT_TRUE(TestFunctionPatching(kPatchableCode10, override, prefix));
676   EXPECT_TRUE(TestFunctionPatching(kPatchableCode11, override, prefix));
677   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode7, override, prefix));
678   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode8, override, prefix));
679   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode9, override, prefix));
680 #else
681   EXPECT_TRUE(TestFunctionPatching(kPatchableCode3, override, prefix));
682 #endif
683   EXPECT_FALSE(TestFunctionPatching(kPatchableCode4, override, prefix));
684 
685   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1, override, prefix));
686   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode2, override, prefix));
687   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3, override, prefix));
688   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4, override, prefix));
689   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5, override, prefix));
690   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6, override, prefix));
691 }
692 
TEST(Interception,PatchableFunctionPadding)693 TEST(Interception, PatchableFunctionPadding) {
694   TestOverrideFunction override = OverrideFunction;
695   FunctionPrefixKind prefix = FunctionPrefixPadding;
696 
697   EXPECT_TRUE(TestFunctionPatching(kPatchableCode1, override, prefix));
698   EXPECT_TRUE(TestFunctionPatching(kPatchableCode2, override, prefix));
699 #if SANITIZER_WINDOWS64
700   EXPECT_FALSE(TestFunctionPatching(kPatchableCode3, override, prefix));
701 #else
702   EXPECT_TRUE(TestFunctionPatching(kPatchableCode3, override, prefix));
703 #endif
704   EXPECT_TRUE(TestFunctionPatching(kPatchableCode4, override, prefix));
705 
706   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1, override, prefix));
707   EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode2, override, prefix));
708   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3, override, prefix));
709   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4, override, prefix));
710   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5, override, prefix));
711   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6, override, prefix));
712 }
713 
TEST(Interception,EmptyExportTable)714 TEST(Interception, EmptyExportTable) {
715   // We try to get a pointer to a function from an executable that doesn't
716   // export any symbol (empty export table).
717   uptr FunPtr = InternalGetProcAddress((void *)GetModuleHandleA(0), "example");
718   EXPECT_EQ(0U, FunPtr);
719 }
720 
721 }  // namespace __interception
722 
723 #endif  // SANITIZER_WINDOWS
724 #endif  // #if !SANITIZER_DEBUG
725