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
25static int isdigit_called;
26namespace __interception {
27int isalpha_called;
28int isalnum_called;
29int islower_called;
30} // namespace __interception
31using namespace __interception;
32
33DECLARE_REAL(int, isdigit, int);
34DECLARE_REAL(int, isalpha, int);
35DECLARE_REAL(int, isalnum, int);
36DECLARE_REAL(int, islower, int);
37
38INTERCEPTOR(void *, malloc, SIZE_T s) { return calloc(nmemb: 1, size: s); }
39INTERCEPTOR(void, dummy_doesnt_exist__, ) { __builtin_trap(); }
40
41INTERCEPTOR(int, isdigit, int d) {
42 ++isdigit_called;
43 return d >= '0' && d <= '9';
44}
45
46INTERCEPTOR(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
52INTERCEPTOR(int, isalnum, int d) {
53 isalnum_called = isalnum_called * 10 + 3;
54 return __interceptor_isalpha(d) || __interceptor_isdigit(d);
55}
56
57INTERCEPTOR(int, islower, int d) {
58 islower_called = islower_called * 10 + 3;
59 return d >= 'a' && d <= 'z';
60}
61
62namespace __interception {
63
64TEST(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
79TEST(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
96TEST(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
114TEST(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
131TEST(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

source code of compiler-rt/lib/interception/tests/interception_linux_test.cpp