1 /** 2 * Copyright (c) 2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #include "cfi_util.h" 17 18 struct A { 19 virtual void Test(); 20 }; 21 Test()22void A::Test() 23 { 24 printf("A::Test()\n"); 25 } 26 27 struct B : A { 28 virtual void Test(); 29 }; 30 Test()31void B::Test() 32 { 33 printf("B::Test()\n"); 34 } 35 36 struct C : A { 37 }; 38 39 struct D { 40 virtual void Test(); 41 }; 42 Test()43void D::Test() 44 { 45 printf("D::Test()\n"); 46 } 47 48 struct CallTestA { 49 virtual void VcallFunc(); 50 void CallFunc(); 51 }; 52 VcallFunc()53void CallTestA::VcallFunc() 54 { 55 printf("CallTestA::VcallFunc()\n"); 56 } 57 CallFunc()58void CallTestA::CallFunc() 59 { 60 printf("CallTestA::CallFunc()\n"); 61 } 62 63 struct CallTestB { 64 virtual void VcallFunc(); 65 void CallFunc(); 66 }; 67 VcallFunc()68void CallTestB::VcallFunc() 69 { 70 printf("CallTestB::VcallFunc()\n"); 71 } 72 CallFunc()73void CallTestB::CallFunc() 74 { 75 printf("CallTestB::CallFunc()\n"); 76 } 77 CfiCastStrict()78void CfiCastStrict() 79 { 80 C *c = new C; 81 A a; 82 c = static_cast<C *>(&a); 83 } 84 CfiDerivedCast()85void CfiDerivedCast() 86 { 87 B *b = new B; 88 A a; 89 b = static_cast<B *>(&a); 90 } 91 CfiUnrelatedCast()92void CfiUnrelatedCast() 93 { 94 D *d = new D; 95 A a; 96 d = ((D *)&a); 97 } 98 Icall()99void Icall() 100 { 101 printf("Icall()\n"); 102 } 103 CfiIcall()104void CfiIcall() 105 { 106 ((void (*)(int))Icall)(42); 107 } 108 CfiVcall()109void CfiVcall() 110 { 111 CallTestA *a; 112 void *p = (void *)(new CallTestB()); 113 memcpy(&a, &p, sizeof(a)); 114 a->VcallFunc(); 115 } 116 CfiNvcall()117void CfiNvcall() 118 { 119 CallTestA *a; 120 void *p = (void *)(new CallTestB()); 121 memcpy(&a, &p, sizeof(a)); 122 a->CallFunc(); 123 } 124 125 main()126int main() 127 { 128 if (DEBUG) { 129 ShowCfiLogFile(); 130 } 131 ClearCfiLog(); 132 if (DEBUG) { 133 ShowCfiLogFile(); 134 } 135 // clang allow it by default. It can be disabled with -fsanitize=cfi-cast-strict. 136 CfiCastStrict(); 137 138 CfiDerivedCast(); 139 FindAndCheck("runtime error: control flow integrity check for type 'B' failed during base-to-derived cast"); 140 141 CfiUnrelatedCast(); 142 FindAndCheck("runtime error: control flow integrity check for type 'D' failed during cast to unrelated type"); 143 144 CfiNvcall(); 145 FindAndCheck("runtime error: control flow integrity check for type 'CallTestA' failed during non-virtual call"); 146 147 CfiVcall(); 148 FindAndCheck("runtime error: control flow integrity check for type 'CallTestA' failed during virtual call"); 149 150 CfiIcall(); 151 FindAndCheck("runtime error: control flow integrity check for type 'void (int)' failed during indirect function call"); 152 153 if (DEBUG) { 154 ShowCfiLogFile(); 155 } 156 } 157