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