xref: /llvm-project/compiler-rt/lib/interception/tests/interception_linux_foreign_test.cpp (revision 37445e96d867f4266993085e821fbd4c4d8fa401)
1*37445e96SMarco Elver //===-- interception_linux_foreign_test.cpp -------------------------------===//
2*37445e96SMarco Elver //
3*37445e96SMarco Elver // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*37445e96SMarco Elver // See https://llvm.org/LICENSE.txt for license information.
5*37445e96SMarco Elver // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*37445e96SMarco Elver //
7*37445e96SMarco Elver //===----------------------------------------------------------------------===//
8*37445e96SMarco Elver //
9*37445e96SMarco Elver // This file is a part of ThreadSanitizer/AddressSanitizer runtime.
10*37445e96SMarco Elver //
11*37445e96SMarco Elver // Tests that foreign interceptors work.
12*37445e96SMarco Elver //
13*37445e96SMarco Elver //===----------------------------------------------------------------------===//
14*37445e96SMarco Elver 
15*37445e96SMarco Elver // Do not declare functions in ctype.h.
16*37445e96SMarco Elver #define __NO_CTYPE
17*37445e96SMarco Elver 
18*37445e96SMarco Elver #include "gtest/gtest.h"
19*37445e96SMarco Elver #include "sanitizer_common/sanitizer_asm.h"
20*37445e96SMarco Elver #include "sanitizer_common/sanitizer_internal_defs.h"
21*37445e96SMarco Elver 
22*37445e96SMarco Elver #if SANITIZER_LINUX
23*37445e96SMarco Elver 
24*37445e96SMarco Elver extern "C" int isalnum(int d);
25*37445e96SMarco Elver extern "C" int __interceptor_isalpha(int d);
26*37445e96SMarco Elver extern "C" int ___interceptor_isalnum(int d);  // the sanitizer interceptor
27*37445e96SMarco Elver extern "C" int ___interceptor_islower(int d);  // the sanitizer interceptor
28*37445e96SMarco Elver 
29*37445e96SMarco Elver namespace __interception {
30*37445e96SMarco Elver extern int isalpha_called;
31*37445e96SMarco Elver extern int isalnum_called;
32*37445e96SMarco Elver extern int islower_called;
33*37445e96SMarco Elver }  // namespace __interception
34*37445e96SMarco Elver using namespace __interception;
35*37445e96SMarco Elver 
36*37445e96SMarco Elver // Direct foreign interceptor. This is the "normal" protocol that other
37*37445e96SMarco Elver // interceptors should follow.
isalpha(int d)38*37445e96SMarco Elver extern "C" int isalpha(int d) {
39*37445e96SMarco Elver   // Use non-commutative arithmetic to verify order of calls.
40*37445e96SMarco Elver   isalpha_called = isalpha_called * 10 + 1;
41*37445e96SMarco Elver   return __interceptor_isalpha(d);
42*37445e96SMarco Elver }
43*37445e96SMarco Elver 
44*37445e96SMarco Elver #if ASM_INTERCEPTOR_TRAMPOLINE_SUPPORT
45*37445e96SMarco Elver // Indirect foreign interceptor. This pattern should only be used to co-exist
46*37445e96SMarco Elver // with direct foreign interceptors and sanitizer interceptors.
__interceptor_isalnum(int d)47*37445e96SMarco Elver extern "C" int __interceptor_isalnum(int d) {
48*37445e96SMarco Elver   isalnum_called = isalnum_called * 10 + 1;
49*37445e96SMarco Elver   return ___interceptor_isalnum(d);
50*37445e96SMarco Elver }
51*37445e96SMarco Elver 
__interceptor_islower(int d)52*37445e96SMarco Elver extern "C" int __interceptor_islower(int d) {
53*37445e96SMarco Elver   islower_called = islower_called * 10 + 2;
54*37445e96SMarco Elver   return ___interceptor_islower(d);
55*37445e96SMarco Elver }
56*37445e96SMarco Elver 
islower(int d)57*37445e96SMarco Elver extern "C" int islower(int d) {
58*37445e96SMarco Elver   islower_called = islower_called * 10 + 1;
59*37445e96SMarco Elver   return __interceptor_islower(d);
60*37445e96SMarco Elver }
61*37445e96SMarco Elver #endif  // ASM_INTERCEPTOR_TRAMPOLINE_SUPPORT
62*37445e96SMarco Elver 
63*37445e96SMarco Elver namespace __interception {
64*37445e96SMarco Elver 
TEST(ForeignInterception,ForeignOverrideDirect)65*37445e96SMarco Elver TEST(ForeignInterception, ForeignOverrideDirect) {
66*37445e96SMarco Elver   isalpha_called = 0;
67*37445e96SMarco Elver   EXPECT_NE(0, isalpha('a'));
68*37445e96SMarco Elver   EXPECT_EQ(13, isalpha_called);
69*37445e96SMarco Elver   isalpha_called = 0;
70*37445e96SMarco Elver   EXPECT_EQ(0, isalpha('_'));
71*37445e96SMarco Elver   EXPECT_EQ(13, isalpha_called);
72*37445e96SMarco Elver }
73*37445e96SMarco Elver 
74*37445e96SMarco Elver #if ASM_INTERCEPTOR_TRAMPOLINE_SUPPORT
TEST(ForeignInterception,ForeignOverrideIndirect)75*37445e96SMarco Elver TEST(ForeignInterception, ForeignOverrideIndirect) {
76*37445e96SMarco Elver   isalnum_called = 0;
77*37445e96SMarco Elver   EXPECT_NE(0, isalnum('a'));
78*37445e96SMarco Elver   EXPECT_EQ(13, isalnum_called);
79*37445e96SMarco Elver   isalnum_called = 0;
80*37445e96SMarco Elver   EXPECT_EQ(0, isalnum('_'));
81*37445e96SMarco Elver   EXPECT_EQ(13, isalnum_called);
82*37445e96SMarco Elver }
83*37445e96SMarco Elver 
TEST(ForeignInterception,ForeignOverrideThree)84*37445e96SMarco Elver TEST(ForeignInterception, ForeignOverrideThree) {
85*37445e96SMarco Elver   islower_called = 0;
86*37445e96SMarco Elver   EXPECT_NE(0, islower('a'));
87*37445e96SMarco Elver   EXPECT_EQ(123, islower_called);
88*37445e96SMarco Elver   islower_called = 0;
89*37445e96SMarco Elver   EXPECT_EQ(0, islower('_'));
90*37445e96SMarco Elver   EXPECT_EQ(123, islower_called);
91*37445e96SMarco Elver }
92*37445e96SMarco Elver #endif  // ASM_INTERCEPTOR_TRAMPOLINE_SUPPORT
93*37445e96SMarco Elver 
94*37445e96SMarco Elver }  // namespace __interception
95*37445e96SMarco Elver 
96*37445e96SMarco Elver #endif  // SANITIZER_LINUX
97