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