/** * Copyright (c) 2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "cfi_util.h" struct A { virtual void Test(); }; void A::Test() { printf("A::Test()\n"); } struct B : A { virtual void Test(); }; void B::Test() { printf("B::Test()\n"); } struct C : A { }; struct D { virtual void Test(); }; void D::Test() { printf("D::Test()\n"); } struct CallTestA { virtual void VcallFunc(); void CallFunc(); }; void CallTestA::VcallFunc() { printf("CallTestA::VcallFunc()\n"); } void CallTestA::CallFunc() { printf("CallTestA::CallFunc()\n"); } struct CallTestB { virtual void VcallFunc(); void CallFunc(); }; void CallTestB::VcallFunc() { printf("CallTestB::VcallFunc()\n"); } void CallTestB::CallFunc() { printf("CallTestB::CallFunc()\n"); } void CfiCastStrict() { C *c = new C; A a; c = static_cast(&a); } void CfiDerivedCast() { B *b = new B; A a; b = static_cast(&a); } void CfiUnrelatedCast() { D *d = new D; A a; d = ((D *)&a); } void Icall() { printf("Icall()\n"); } void CfiIcall() { ((void (*)(int))Icall)(42); } void CfiVcall() { CallTestA *a; void *p = (void *)(new CallTestB()); memcpy(&a, &p, sizeof(a)); a->VcallFunc(); } void CfiNvcall() { CallTestA *a; void *p = (void *)(new CallTestB()); memcpy(&a, &p, sizeof(a)); a->CallFunc(); } int main() { if (DEBUG) { ShowCfiLogFile(); } ClearCfiLog(); if (DEBUG) { ShowCfiLogFile(); } // clang allow it by default. It can be disabled with -fsanitize=cfi-cast-strict. CfiCastStrict(); CfiDerivedCast(); FindAndCheck("runtime error: control flow integrity check for type 'B' failed during base-to-derived cast"); CfiUnrelatedCast(); FindAndCheck("runtime error: control flow integrity check for type 'D' failed during cast to unrelated type"); CfiNvcall(); FindAndCheck("runtime error: control flow integrity check for type 'CallTestA' failed during non-virtual call"); CfiVcall(); FindAndCheck("runtime error: control flow integrity check for type 'CallTestA' failed during virtual call"); CfiIcall(); FindAndCheck("runtime error: control flow integrity check for type 'void (int)' failed during indirect function call"); if (DEBUG) { ShowCfiLogFile(); } }