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