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_internal_defs.h" 20 21 #if SANITIZER_LINUX 22 23 extern "C" int isalnum(int d); 24 extern "C" int __interceptor_isalpha(int d); 25 extern "C" int ___interceptor_isalnum(int d); // the sanitizer interceptor 26 extern "C" int ___interceptor_islower(int d); // the sanitizer interceptor 27 28 namespace __interception { 29 extern int isalpha_called; 30 extern int isalnum_called; 31 extern int islower_called; 32 } // namespace __interception 33 using namespace __interception; 34 35 // Direct foreign interceptor. This is the "normal" protocol that other 36 // interceptors should follow. 37 extern "C" int isalpha(int d) { 38 // Use non-commutative arithmetic to verify order of calls. 39 isalpha_called = isalpha_called * 10 + 1; 40 return __interceptor_isalpha(d); 41 } 42 43 // Indirect foreign interceptor. This pattern should only be used to co-exist 44 // with direct foreign interceptors and sanitizer interceptors. 45 extern "C" int __interceptor_isalnum(int d) { 46 isalnum_called = isalnum_called * 10 + 1; 47 return ___interceptor_isalnum(d); 48 } 49 50 extern "C" int __interceptor_islower(int d) { 51 islower_called = islower_called * 10 + 2; 52 return ___interceptor_islower(d); 53 } 54 55 extern "C" int islower(int d) { 56 islower_called = islower_called * 10 + 1; 57 return __interceptor_islower(d); 58 } 59 60 namespace __interception { 61 62 TEST(ForeignInterception, ForeignOverrideDirect) { 63 isalpha_called = 0; 64 EXPECT_NE(0, isalpha('a')); 65 EXPECT_EQ(13, isalpha_called); 66 isalpha_called = 0; 67 EXPECT_EQ(0, isalpha('_')); 68 EXPECT_EQ(13, isalpha_called); 69 } 70 71 TEST(ForeignInterception, ForeignOverrideIndirect) { 72 isalnum_called = 0; 73 EXPECT_NE(0, isalnum('a')); 74 EXPECT_EQ(13, isalnum_called); 75 isalnum_called = 0; 76 EXPECT_EQ(0, isalnum('_')); 77 EXPECT_EQ(13, isalnum_called); 78 } 79 80 TEST(ForeignInterception, ForeignOverrideThree) { 81 islower_called = 0; 82 EXPECT_NE(0, islower('a')); 83 EXPECT_EQ(123, islower_called); 84 islower_called = 0; 85 EXPECT_EQ(0, islower('_')); 86 EXPECT_EQ(123, islower_called); 87 } 88 89 } // namespace __interception 90 91 #endif // SANITIZER_LINUX 92