1//===-- interception_linux_foreign_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//
11// Tests that foreign interceptors work.
12//
13//===----------------------------------------------------------------------===//
14
15// Do not declare functions in ctype.h.
16#define __NO_CTYPE
17
18#include "gtest/gtest.h"
19#include "sanitizer_common/sanitizer_asm.h"
20#include "sanitizer_common/sanitizer_internal_defs.h"
21
22#if SANITIZER_LINUX
23
24extern "C" int isalnum(int d);
25extern "C" int __interceptor_isalpha(int d);
26extern "C" int ___interceptor_isalnum(int d); // the sanitizer interceptor
27extern "C" int ___interceptor_islower(int d); // the sanitizer interceptor
28
29namespace __interception {
30extern int isalpha_called;
31extern int isalnum_called;
32extern int islower_called;
33} // namespace __interception
34using namespace __interception;
35
36// Direct foreign interceptor. This is the "normal" protocol that other
37// interceptors should follow.
38extern "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);
42}
43
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.
47extern "C" int __interceptor_isalnum(int d) {
48 isalnum_called = isalnum_called * 10 + 1;
49 return ___interceptor_isalnum(d);
50}
51
52extern "C" int __interceptor_islower(int d) {
53 islower_called = islower_called * 10 + 2;
54 return ___interceptor_islower(d);
55}
56
57extern "C" int islower(int d) {
58 islower_called = islower_called * 10 + 1;
59 return __interceptor_islower(d);
60}
61#endif // ASM_INTERCEPTOR_TRAMPOLINE_SUPPORT
62
63namespace __interception {
64
65TEST(ForeignInterception, ForeignOverrideDirect) {
66 isalpha_called = 0;
67 EXPECT_NE(0, isalpha(d: 'a'));
68 EXPECT_EQ(13, isalpha_called);
69 isalpha_called = 0;
70 EXPECT_EQ(0, isalpha(d: '_'));
71 EXPECT_EQ(13, isalpha_called);
72}
73
74#if ASM_INTERCEPTOR_TRAMPOLINE_SUPPORT
75TEST(ForeignInterception, ForeignOverrideIndirect) {
76 isalnum_called = 0;
77 EXPECT_NE(0, isalnum(d: 'a'));
78 EXPECT_EQ(13, isalnum_called);
79 isalnum_called = 0;
80 EXPECT_EQ(0, isalnum(d: '_'));
81 EXPECT_EQ(13, isalnum_called);
82}
83
84TEST(ForeignInterception, ForeignOverrideThree) {
85 islower_called = 0;
86 EXPECT_NE(0, islower(d: 'a'));
87 EXPECT_EQ(123, islower_called);
88 islower_called = 0;
89 EXPECT_EQ(0, islower(d: '_'));
90 EXPECT_EQ(123, islower_called);
91}
92#endif // ASM_INTERCEPTOR_TRAMPOLINE_SUPPORT
93
94} // namespace __interception
95
96#endif // SANITIZER_LINUX
97

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