1799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// RUN: %clangxx_cfi -o %t1 %s 2c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar// RUN: %expect_crash_unless_devirt %t1 2>&1 | FileCheck --check-prefix=CFI %s 386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 4799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// RUN: %clangxx_cfi -DB32 -o %t2 %s 5799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// RUN: %expect_crash %t2 2>&1 | FileCheck --check-prefix=CFI %s 686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 7799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// RUN: %clangxx_cfi -DB64 -o %t3 %s 8799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// RUN: %expect_crash %t3 2>&1 | FileCheck --check-prefix=CFI %s 986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 10799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// RUN: %clangxx_cfi -DBM -o %t4 %s 11799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// RUN: %expect_crash %t4 2>&1 | FileCheck --check-prefix=CFI %s 1286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 13799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// RUN: %clangxx -o %t5 %s 14799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// RUN: %t5 2>&1 | FileCheck --check-prefix=NCFI %s 15799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 16799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// RUN: %clangxx_cfi_diag -o %t6 %s 17799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// RUN: %t6 2>&1 | FileCheck --check-prefix=CFI-DIAG %s 1886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 1986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// Tests that the CFI mechanism crashes the program when a virtual table is 2086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// replaced with a compatible table of function pointers that does not belong to 2186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// any class, by manually overwriting the virtual table of an object and 2286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// attempting to make a call through it. 2386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 24799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// REQUIRES: cxxabi 25799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 2686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include <stdio.h> 2786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include "utils.h" 2886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 2986277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstruct A { 3086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines virtual void f(); 3186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}; 3286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 3386277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid A::f() {} 3486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 3586277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid foo() { 3686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines fprintf(stderr, "foo\n"); 3786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 3886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 39799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarvoid *fake_vtable[] = { 0, 0, (void *)&foo }; 4086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 4186277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesint main() { 42799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar create_derivers<A>(); 4386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 4486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines A *a = new A; 45799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar *((void **)a) = fake_vtable + 2; // UB here 4686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines break_optimization(a); 4786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 4886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // CFI: 1 4986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // NCFI: 1 5086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines fprintf(stderr, "1\n"); 5186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 5286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // CFI-NOT: foo 5386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // NCFI: foo 54799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // CFI-DIAG: runtime error: control flow integrity check for type 'A' failed during virtual call 55799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // CFI-DIAG-NEXT: note: invalid vtable 5686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines a->f(); 5786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 58c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar // We don't check for the absence of a 2 here because under devirtualization 59c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar // our virtual call may be devirtualized and we will proceed with execution 60c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar // rather than crashing. 61c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar 62799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // NCFI: {{^2$}} 6386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines fprintf(stderr, "2\n"); 6486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 65