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(); }
int main() { #ifdef B32 break_optimization(new Deriver<A, 0>); #endif #ifdef B64 break_optimization(new Deriver<A, 0>); break_optimization(new Deriver<A, 1>); #endif #ifdef BM break_optimization(new Deriver<A, 0>); break_optimization(new Deriver<A, 1>); break_optimization(new Deriver<A, 2>); #endif A *a = new A; *((void **)a) = fake_vtable; // UB here break_optimization(a); // CFI: 1 // NCFI: 1 fprintf(stderr, "1\n"); // CFI-NOT: foo // NCFI: foo a->f(); // CFI-NOT: 2 // NCFI: 2 fprintf(stderr, "2\n"); }
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"); }
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"); // CFI-DIAG: runtime error: control flow integrity check for type 'B' failed during virtual call // CFI-DIAG-NEXT: note: vtable is of type 'A' delete (B *)a; // UB here // CFI-NOT: 2 // NCFI: 2 fprintf(stderr, "2\n"); }
int main(int argc, char **argv) { #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 B *b = new B; break_optimization(b); // FAIL: 1 // PASS: 1 fprintf(stderr, "1\n"); A a; switch (argv[1][0]) { case 'a': static_cast<B *>(&a); // UB break; case 'b': static_cast<B &>(a); // UB break; case 'c': static_cast<B &&>(a); // UB break; case 'd': static_cast<C *>(&a); // UB, strict only break; case 'e': static_cast<C &>(a); // UB, strict only break; case 'f': static_cast<C &&>(a); // UB, strict only break; case 'g': static_cast<B *>(static_cast<void *>(&a)); // Non-UB bad cast break; case 'h': static_cast<C *>(static_cast<void *>(&a)); // Non-UB bad cast, strict only break; } // FAIL-NOT: 2 // PASS: 2 fprintf(stderr, "2\n"); }
int main(int argc, char **argv) { create_derivers<B>(); B *b = new B; break_optimization(b); // FAIL: 1 // PASS: 1 fprintf(stderr, "1\n"); A a; // CFI-DIAG-D: runtime error: control flow integrity check for type 'B' failed during base-to-derived cast // CFI-DIAG-D-NEXT: note: vtable is of type '{{(struct )?}}A' // CFI-DIAG-U: runtime error: control flow integrity check for type 'B' failed during cast to unrelated type // CFI-DIAG-U-NEXT: note: vtable is of type '{{(struct )?}}A' switch (argv[1][0]) { case 'a': static_cast<B *>(&a); // UB break; case 'b': static_cast<B &>(a); // UB break; case 'c': static_cast<B &&>(a); // UB break; case 'd': static_cast<C *>(&a); // UB, strict only break; case 'e': static_cast<C &>(a); // UB, strict only break; case 'f': static_cast<C &&>(a); // UB, strict only break; case 'g': static_cast<B *>(static_cast<void *>(&a)); // Non-UB bad cast break; case 'h': static_cast<C *>(static_cast<void *>(&a)); // Non-UB bad cast, strict only break; } // FAIL-NOT: {{^2$}} // PASS: {{^2$}} fprintf(stderr, "2\n"); }
int main() { create_derivers<A>(); A *a = new A; *((void **)a) = fake_vtable + 2; // UB here break_optimization(a); // CFI: 1 // NCFI: 1 fprintf(stderr, "1\n"); // CFI-NOT: foo // NCFI: foo // CFI-DIAG: runtime error: control flow integrity check for type 'A' failed during virtual call // CFI-DIAG-NEXT: note: invalid vtable a->f(); // We don't check for the absence of a 2 here because under devirtualization // our virtual call may be devirtualized and we will proceed with execution // rather than crashing. // NCFI: {{^2$}} fprintf(stderr, "2\n"); }
int main(int argc, char **argv) { #ifdef B32 break_optimization(new Deriver<A, 0>); break_optimization(new Deriver<B, 0>); #endif #ifdef B64 break_optimization(new Deriver<A, 0>); break_optimization(new Deriver<A, 1>); break_optimization(new Deriver<B, 0>); break_optimization(new Deriver<B, 1>); #endif #ifdef BM break_optimization(new Deriver<A, 0>); break_optimization(new Deriver<A, 1>); break_optimization(new Deriver<A, 2>); break_optimization(new Deriver<B, 0>); break_optimization(new Deriver<B, 1>); break_optimization(new Deriver<B, 2>); #endif C *c = new C; break_optimization(c); // CFI: 1 // NCFI: 1 fprintf(stderr, "1\n"); if (argc > 1) { A *a = c; // CFI-DIAG1: runtime error: control flow integrity check for type 'B' failed during cast to unrelated type // CFI-DIAG1-NEXT: note: vtable is of type '{{(struct )?}}C' ((B *)a)->g(); // UB here } else { // CFI-DIAG2: runtime error: control flow integrity check for type 'A' failed during cast to unrelated type // CFI-DIAG2-NEXT: note: vtable is of type '{{(struct )?}}C' B *b = c; ((A *)b)->f(); // UB here } // CFI-NOT: {{^2$}} // NCFI: {{^2$}} fprintf(stderr, "2\n"); }