// UNSUPPORTED: win32 // RUN: %clangxx_cfi -o %t %s // RUN: %expect_crash %run %t a // RUN: %expect_crash %run %t b // RUN: %expect_crash %run %t c // RUN: %expect_crash %run %t d // RUN: %expect_crash %run %t e // RUN: %run %t f // RUN: %run %t g // RUN: %clangxx_cfi_diag -o %t2 %s // RUN: %run %t2 a 2>&1 | FileCheck --check-prefix=A %s // RUN: %run %t2 b 2>&1 | FileCheck --check-prefix=B %s // RUN: %run %t2 c 2>&1 | FileCheck --check-prefix=C %s // RUN: %run %t2 d 2>&1 | FileCheck --check-prefix=D %s // RUN: %run %t2 e 2>&1 | FileCheck --check-prefix=E %s #include #include struct SBase1 { void b1() {} }; struct SBase2 { void b2() {} }; struct S : SBase1, SBase2 { void f1() {} int f2() { return 1; } virtual void g1() {} virtual int g2() { return 1; } virtual int g3() { return 1; } }; struct T { void f1() {} int f2() { return 2; } virtual void g1() {} virtual int g2() { return 2; } virtual void g3() {} }; typedef void (S::*S_void)(); typedef int (S::*S_int)(); typedef int (T::*T_int)(); template To bitcast(From f) { assert(sizeof(To) == sizeof(From)); To t; memcpy(&t, &f, sizeof(f)); return t; } int main(int argc, char **argv) { S s; T t; switch (argv[1][0]) { case 'a': // A: runtime error: control flow integrity check for type 'int (S::*)()' failed during non-virtual pointer to member function call // A: note: S::f1() defined here (s.*bitcast(&S::f1))(); break; case 'b': // B: runtime error: control flow integrity check for type 'int (T::*)()' failed during non-virtual pointer to member function call // B: note: S::f2() defined here (t.*bitcast(&S::f2))(); break; case 'c': // C: runtime error: control flow integrity check for type 'int (S::*)()' failed during virtual pointer to member function call // C: note: vtable is of type 'S' (s.*bitcast(&S::g1))(); break; case 'd': // D: runtime error: control flow integrity check for type 'int (S::*)()' failed during virtual pointer to member function call // D: note: vtable is of type 'T' (reinterpret_cast(t).*&S::g2)(); break; case 'e': // E: runtime error: control flow integrity check for type 'void (S::*)()' failed during virtual pointer to member function call // E: note: vtable is of type 'S' (s.*bitcast(&T::g3))(); break; case 'f': (s.*&SBase1::b1)(); break; case 'g': (s.*&SBase2::b2)(); break; } }