xref: /llvm-project/compiler-rt/lib/interception/tests/interception_linux_test.cpp (revision 37445e96d867f4266993085e821fbd4c4d8fa401)
1 //===-- interception_linux_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_linux.h.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 // Do not declare functions in ctype.h.
15 #define __NO_CTYPE
16 
17 #include "interception/interception.h"
18 
19 #include <stdlib.h>
20 
21 #include "gtest/gtest.h"
22 
23 #if SANITIZER_LINUX
24 
25 static int isdigit_called;
26 namespace __interception {
27 int isalpha_called;
28 int isalnum_called;
29 int islower_called;
30 }  // namespace __interception
31 using namespace __interception;
32 
33 DECLARE_REAL(int, isdigit, int);
34 DECLARE_REAL(int, isalpha, int);
35 DECLARE_REAL(int, isalnum, int);
36 DECLARE_REAL(int, islower, int);
37 
INTERCEPTOR(void *,malloc,SIZE_T s)38 INTERCEPTOR(void *, malloc, SIZE_T s) { return calloc(1, s); }
39 INTERCEPTOR(void, dummy_doesnt_exist__, ) { __builtin_trap(); }
40 
INTERCEPTOR(int,isdigit,int d)41 INTERCEPTOR(int, isdigit, int d) {
42   ++isdigit_called;
43   return d >= '0' && d <= '9';
44 }
45 
INTERCEPTOR(int,isalpha,int d)46 INTERCEPTOR(int, isalpha, int d) {
47   // Use non-commutative arithmetic to verify order of calls.
48   isalpha_called = isalpha_called * 10 + 3;
49   return (d >= 'a' && d <= 'z') || (d >= 'A' && d <= 'Z');
50 }
51 
INTERCEPTOR(int,isalnum,int d)52 INTERCEPTOR(int, isalnum, int d) {
53   isalnum_called = isalnum_called * 10 + 3;
54   return __interceptor_isalpha(d) || __interceptor_isdigit(d);
55 }
56 
INTERCEPTOR(int,islower,int d)57 INTERCEPTOR(int, islower, int d) {
58   islower_called = islower_called * 10 + 3;
59   return d >= 'a' && d <= 'z';
60 }
61 
62 namespace __interception {
63 
TEST(Interception,InterceptFunction)64 TEST(Interception, InterceptFunction) {
65   uptr malloc_address = 0;
66   EXPECT_TRUE(InterceptFunction("malloc", &malloc_address, (uptr)&malloc,
67                                 (uptr)&TRAMPOLINE(malloc)));
68   EXPECT_NE(0U, malloc_address);
69   EXPECT_FALSE(InterceptFunction("malloc", &malloc_address, (uptr)&calloc,
70                                  (uptr)&TRAMPOLINE(malloc)));
71 
72   uptr dummy_address = 0;
73   EXPECT_FALSE(InterceptFunction("dummy_doesnt_exist__", &dummy_address,
74                                  (uptr)&dummy_doesnt_exist__,
75                                  (uptr)&TRAMPOLINE(dummy_doesnt_exist__)));
76   EXPECT_EQ(0U, dummy_address);
77 }
78 
TEST(Interception,Basic)79 TEST(Interception, Basic) {
80   EXPECT_TRUE(INTERCEPT_FUNCTION(isdigit));
81 
82   // After interception, the counter should be incremented.
83   isdigit_called = 0;
84   EXPECT_NE(0, isdigit('1'));
85   EXPECT_EQ(1, isdigit_called);
86   EXPECT_EQ(0, isdigit('a'));
87   EXPECT_EQ(2, isdigit_called);
88 
89   // Calling the REAL function should not affect the counter.
90   isdigit_called = 0;
91   EXPECT_NE(0, REAL(isdigit)('1'));
92   EXPECT_EQ(0, REAL(isdigit)('a'));
93   EXPECT_EQ(0, isdigit_called);
94 }
95 
TEST(Interception,ForeignOverrideDirect)96 TEST(Interception, ForeignOverrideDirect) {
97   // Actual interceptor is overridden.
98   EXPECT_FALSE(INTERCEPT_FUNCTION(isalpha));
99 
100   isalpha_called = 0;
101   EXPECT_NE(0, isalpha('a'));
102   EXPECT_EQ(13, isalpha_called);
103   isalpha_called = 0;
104   EXPECT_EQ(0, isalpha('_'));
105   EXPECT_EQ(13, isalpha_called);
106 
107   isalpha_called = 0;
108   EXPECT_NE(0, REAL(isalpha)('a'));
109   EXPECT_EQ(0, REAL(isalpha)('_'));
110   EXPECT_EQ(0, isalpha_called);
111 }
112 
113 #if ASM_INTERCEPTOR_TRAMPOLINE_SUPPORT
TEST(Interception,ForeignOverrideIndirect)114 TEST(Interception, ForeignOverrideIndirect) {
115   // Actual interceptor is _not_ overridden.
116   EXPECT_TRUE(INTERCEPT_FUNCTION(isalnum));
117 
118   isalnum_called = 0;
119   EXPECT_NE(0, isalnum('a'));
120   EXPECT_EQ(13, isalnum_called);
121   isalnum_called = 0;
122   EXPECT_EQ(0, isalnum('_'));
123   EXPECT_EQ(13, isalnum_called);
124 
125   isalnum_called = 0;
126   EXPECT_NE(0, REAL(isalnum)('a'));
127   EXPECT_EQ(0, REAL(isalnum)('_'));
128   EXPECT_EQ(0, isalnum_called);
129 }
130 
TEST(Interception,ForeignOverrideThree)131 TEST(Interception, ForeignOverrideThree) {
132   // Actual interceptor is overridden.
133   EXPECT_FALSE(INTERCEPT_FUNCTION(islower));
134 
135   islower_called = 0;
136   EXPECT_NE(0, islower('a'));
137   EXPECT_EQ(123, islower_called);
138   islower_called = 0;
139   EXPECT_EQ(0, islower('A'));
140   EXPECT_EQ(123, islower_called);
141 
142   islower_called = 0;
143   EXPECT_NE(0, REAL(islower)('a'));
144   EXPECT_EQ(0, REAL(islower)('A'));
145   EXPECT_EQ(0, islower_called);
146 }
147 #endif  // ASM_INTERCEPTOR_TRAMPOLINE_SUPPORT
148 
149 }  // namespace __interception
150 
151 #endif  // SANITIZER_LINUX
152