1 //===-- interception_linux_test.cpp ---------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file is a part of ThreadSanitizer/AddressSanitizer runtime.
10 // Tests for interception_linux.h.
12 //===----------------------------------------------------------------------===//
14 // Do not declare functions in ctype.h.
17 #include "interception/interception.h"
21 #include "gtest/gtest.h"
25 static int isdigit_called
;
26 namespace __interception
{
30 } // namespace __interception
31 using namespace __interception
;
33 DECLARE_REAL(int, isdigit
, int);
34 DECLARE_REAL(int, isalpha
, int);
35 DECLARE_REAL(int, isalnum
, int);
36 DECLARE_REAL(int, islower
, int);
38 INTERCEPTOR(void *, malloc
, SIZE_T s
) { return calloc(1, s
); }
39 INTERCEPTOR(void, dummy_doesnt_exist__
, ) { __builtin_trap(); }
41 INTERCEPTOR(int, isdigit
, int d
) {
43 return d
>= '0' && d
<= '9';
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');
52 INTERCEPTOR(int, isalnum
, int d
) {
53 isalnum_called
= isalnum_called
* 10 + 3;
54 return __interceptor_isalpha(d
) || __interceptor_isdigit(d
);
57 INTERCEPTOR(int, islower
, int d
) {
58 islower_called
= islower_called
* 10 + 3;
59 return d
>= 'a' && d
<= 'z';
62 namespace __interception
{
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
)));
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
);
79 TEST(Interception
, Basic
) {
80 EXPECT_TRUE(INTERCEPT_FUNCTION(isdigit
));
82 // After interception, the counter should be incremented.
84 EXPECT_NE(0, isdigit('1'));
85 EXPECT_EQ(1, isdigit_called
);
86 EXPECT_EQ(0, isdigit('a'));
87 EXPECT_EQ(2, isdigit_called
);
89 // Calling the REAL function should not affect the counter.
91 EXPECT_NE(0, REAL(isdigit
)('1'));
92 EXPECT_EQ(0, REAL(isdigit
)('a'));
93 EXPECT_EQ(0, isdigit_called
);
96 TEST(Interception
, ForeignOverrideDirect
) {
97 // Actual interceptor is overridden.
98 EXPECT_FALSE(INTERCEPT_FUNCTION(isalpha
));
101 EXPECT_NE(0, isalpha('a'));
102 EXPECT_EQ(13, isalpha_called
);
104 EXPECT_EQ(0, isalpha('_'));
105 EXPECT_EQ(13, isalpha_called
);
108 EXPECT_NE(0, REAL(isalpha
)('a'));
109 EXPECT_EQ(0, REAL(isalpha
)('_'));
110 EXPECT_EQ(0, isalpha_called
);
113 #if ASM_INTERCEPTOR_TRAMPOLINE_SUPPORT
114 TEST(Interception
, ForeignOverrideIndirect
) {
115 // Actual interceptor is _not_ overridden.
116 EXPECT_TRUE(INTERCEPT_FUNCTION(isalnum
));
119 EXPECT_NE(0, isalnum('a'));
120 EXPECT_EQ(13, isalnum_called
);
122 EXPECT_EQ(0, isalnum('_'));
123 EXPECT_EQ(13, isalnum_called
);
126 EXPECT_NE(0, REAL(isalnum
)('a'));
127 EXPECT_EQ(0, REAL(isalnum
)('_'));
128 EXPECT_EQ(0, isalnum_called
);
131 TEST(Interception
, ForeignOverrideThree
) {
132 // Actual interceptor is overridden.
133 EXPECT_FALSE(INTERCEPT_FUNCTION(islower
));
136 EXPECT_NE(0, islower('a'));
137 EXPECT_EQ(123, islower_called
);
139 EXPECT_EQ(0, islower('A'));
140 EXPECT_EQ(123, islower_called
);
143 EXPECT_NE(0, REAL(islower
)('a'));
144 EXPECT_EQ(0, REAL(islower
)('A'));
145 EXPECT_EQ(0, islower_called
);
147 #endif // ASM_INTERCEPTOR_TRAMPOLINE_SUPPORT
149 } // namespace __interception
151 #endif // SANITIZER_LINUX