forked from OSchip/llvm-project
Add tests for non-virtual call checking.
Differential Revision: http://reviews.llvm.org/D8792 llvm-svn: 233876
This commit is contained in:
parent
1a7488afaa
commit
7881648a4e
|
@ -0,0 +1,8 @@
|
|||
The tests in this directory use a common convention for exercising the
|
||||
functionality associated with bit sets of different sizes. When certain
|
||||
macros are defined the tests instantiate classes that force the bit sets
|
||||
to be of certain sizes.
|
||||
|
||||
- B32 forces 32-bit bit sets.
|
||||
- B64 forces 64-bit bit sets.
|
||||
- BM forces memory bit sets.
|
|
@ -0,0 +1,65 @@
|
|||
// RUN: %clangxx_cfi -o %t %s
|
||||
// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s
|
||||
|
||||
// RUN: %clangxx_cfi -DB32 -o %t %s
|
||||
// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s
|
||||
|
||||
// RUN: %clangxx_cfi -DB64 -o %t %s
|
||||
// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s
|
||||
|
||||
// RUN: %clangxx_cfi -DBM -o %t %s
|
||||
// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s
|
||||
|
||||
// RUN: %clangxx -o %t %s
|
||||
// RUN: %t 2>&1 | FileCheck --check-prefix=NCFI %s
|
||||
|
||||
// Tests that the CFI mechanism crashes the program when making a non-virtual
|
||||
// call to an object of the wrong class, by casting a pointer to such an object
|
||||
// and attempting to make a call through it.
|
||||
|
||||
#include <stdio.h>
|
||||
#include "utils.h"
|
||||
|
||||
struct A {
|
||||
virtual void f();
|
||||
};
|
||||
|
||||
void A::f() {}
|
||||
|
||||
struct B {
|
||||
void f();
|
||||
virtual void g();
|
||||
};
|
||||
|
||||
void B::f() {}
|
||||
void B::g() {}
|
||||
|
||||
int main() {
|
||||
#ifdef B32
|
||||
break_optimization(new Deriver<B, 0>);
|
||||
#endif
|
||||
|
||||
#ifdef B64
|
||||
break_optimization(new Deriver<B, 0>);
|
||||
break_optimization(new Deriver<B, 1>);
|
||||
#endif
|
||||
|
||||
#ifdef BM
|
||||
break_optimization(new Deriver<B, 0>);
|
||||
break_optimization(new Deriver<B, 1>);
|
||||
break_optimization(new Deriver<B, 2>);
|
||||
#endif
|
||||
|
||||
A *a = new A;
|
||||
break_optimization(a);
|
||||
|
||||
// CFI: 1
|
||||
// NCFI: 1
|
||||
fprintf(stderr, "1\n");
|
||||
|
||||
((B *)a)->f(); // UB here
|
||||
|
||||
// CFI-NOT: 2
|
||||
// NCFI: 2
|
||||
fprintf(stderr, "2\n");
|
||||
}
|
|
@ -3,95 +3,119 @@
|
|||
|
||||
// Tests that the CFI mechanism does not crash the program when making various
|
||||
// kinds of valid calls involving classes with various different linkages and
|
||||
// types of inheritance.
|
||||
// types of inheritance, and both virtual and non-virtual member functions.
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
struct A {
|
||||
virtual void f();
|
||||
void g();
|
||||
};
|
||||
|
||||
void A::f() {}
|
||||
void A::g() {}
|
||||
|
||||
struct A2 : A {
|
||||
virtual void f();
|
||||
void g();
|
||||
};
|
||||
|
||||
void A2::f() {}
|
||||
void A2::g() {}
|
||||
|
||||
struct B {
|
||||
virtual void f() {}
|
||||
void g() {}
|
||||
};
|
||||
|
||||
struct B2 : B {
|
||||
virtual void f() {}
|
||||
void g() {}
|
||||
};
|
||||
|
||||
namespace {
|
||||
|
||||
struct C {
|
||||
virtual void f();
|
||||
void g();
|
||||
};
|
||||
|
||||
void C::f() {}
|
||||
void C::g() {}
|
||||
|
||||
struct C2 : C {
|
||||
virtual void f();
|
||||
void g();
|
||||
};
|
||||
|
||||
void C2::f() {}
|
||||
void C2::g() {}
|
||||
|
||||
struct D {
|
||||
virtual void f() {}
|
||||
void g() {}
|
||||
};
|
||||
|
||||
struct D2 : D {
|
||||
virtual void f() {}
|
||||
void g() {}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
struct E {
|
||||
virtual void f() {}
|
||||
void g() {}
|
||||
};
|
||||
|
||||
struct E2 : virtual E {
|
||||
virtual void f() {}
|
||||
void g() {}
|
||||
};
|
||||
|
||||
int main() {
|
||||
A *a = new A;
|
||||
break_optimization(a);
|
||||
a->f();
|
||||
a->g();
|
||||
a = new A2;
|
||||
break_optimization(a);
|
||||
a->f();
|
||||
a->g();
|
||||
|
||||
B *b = new B;
|
||||
break_optimization(b);
|
||||
b->f();
|
||||
b->g();
|
||||
b = new B2;
|
||||
break_optimization(b);
|
||||
b->f();
|
||||
b->g();
|
||||
|
||||
C *c = new C;
|
||||
break_optimization(c);
|
||||
c->f();
|
||||
c->g();
|
||||
c = new C2;
|
||||
break_optimization(c);
|
||||
c->f();
|
||||
c->g();
|
||||
|
||||
D *d = new D;
|
||||
break_optimization(d);
|
||||
d->f();
|
||||
d->g();
|
||||
d = new D2;
|
||||
break_optimization(d);
|
||||
d->f();
|
||||
d->g();
|
||||
|
||||
E *e = new E;
|
||||
break_optimization(e);
|
||||
e->f();
|
||||
e->g();
|
||||
e = new E2;
|
||||
break_optimization(e);
|
||||
e->f();
|
||||
e->g();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue