1 //===-- interception_linux_foreign_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.
11 // Tests that foreign interceptors work.
13 //===----------------------------------------------------------------------===//
15 // Do not declare functions in ctype.h.
18 #include "gtest/gtest.h"
19 #include "sanitizer_common/sanitizer_asm.h"
20 #include "sanitizer_common/sanitizer_internal_defs.h"
24 extern "C" int isalnum(int d
);
25 extern "C" int __interceptor_isalpha(int d
);
26 extern "C" int ___interceptor_isalnum(int d
); // the sanitizer interceptor
27 extern "C" int ___interceptor_islower(int d
); // the sanitizer interceptor
29 namespace __interception
{
30 extern int isalpha_called
;
31 extern int isalnum_called
;
32 extern int islower_called
;
33 } // namespace __interception
34 using namespace __interception
;
36 // Direct foreign interceptor. This is the "normal" protocol that other
37 // interceptors should follow.
38 extern "C" int isalpha(int d
) {
39 // Use non-commutative arithmetic to verify order of calls.
40 isalpha_called
= isalpha_called
* 10 + 1;
41 return __interceptor_isalpha(d
);
44 #if ASM_INTERCEPTOR_TRAMPOLINE_SUPPORT
45 // Indirect foreign interceptor. This pattern should only be used to co-exist
46 // with direct foreign interceptors and sanitizer interceptors.
47 extern "C" int __interceptor_isalnum(int d
) {
48 isalnum_called
= isalnum_called
* 10 + 1;
49 return ___interceptor_isalnum(d
);
52 extern "C" int __interceptor_islower(int d
) {
53 islower_called
= islower_called
* 10 + 2;
54 return ___interceptor_islower(d
);
57 extern "C" int islower(int d
) {
58 islower_called
= islower_called
* 10 + 1;
59 return __interceptor_islower(d
);
61 #endif // ASM_INTERCEPTOR_TRAMPOLINE_SUPPORT
63 namespace __interception
{
65 TEST(ForeignInterception
, ForeignOverrideDirect
) {
67 EXPECT_NE(0, isalpha('a'));
68 EXPECT_EQ(13, isalpha_called
);
70 EXPECT_EQ(0, isalpha('_'));
71 EXPECT_EQ(13, isalpha_called
);
74 #if ASM_INTERCEPTOR_TRAMPOLINE_SUPPORT
75 TEST(ForeignInterception
, ForeignOverrideIndirect
) {
77 EXPECT_NE(0, isalnum('a'));
78 EXPECT_EQ(13, isalnum_called
);
80 EXPECT_EQ(0, isalnum('_'));
81 EXPECT_EQ(13, isalnum_called
);
84 TEST(ForeignInterception
, ForeignOverrideThree
) {
86 EXPECT_NE(0, islower('a'));
87 EXPECT_EQ(123, islower_called
);
89 EXPECT_EQ(0, islower('_'));
90 EXPECT_EQ(123, islower_called
);
92 #endif // ASM_INTERCEPTOR_TRAMPOLINE_SUPPORT
94 } // namespace __interception
96 #endif // SANITIZER_LINUX