Hello. This is small improvement that can catch a virtual call after a lifetime scope of an object.
Patch can bootstrap on ppc64le-redhat-linux and survives regression tests. Ready to be installed? Martin gcc/cp/ChangeLog: 2017-10-27 Martin Liska <mli...@suse.cz> * decl.c (begin_destructor_body): In case of disabled recovery, we can zero object in order to catch virtual calls after an object lifetime. gcc/testsuite/ChangeLog: 2017-10-27 Martin Liska <mli...@suse.cz> * g++.dg/ubsan/vptr-12.C: New test. --- gcc/cp/decl.c | 3 ++- gcc/testsuite/g++.dg/ubsan/vptr-12.C | 26 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/ubsan/vptr-12.C
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 15a8d283353..69636e30008 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -15281,7 +15281,8 @@ begin_destructor_body (void) /* Clobbering an empty base is harmful if it overlays real data. */ && !is_empty_class (current_class_type)) { - if (sanitize_flags_p (SANITIZE_VPTR)) + if (sanitize_flags_p (SANITIZE_VPTR) + && (flag_sanitize_recover & SANITIZE_VPTR) == 0) { tree fndecl = builtin_decl_explicit (BUILT_IN_MEMSET); tree call = build_call_expr (fndecl, 3, diff --git a/gcc/testsuite/g++.dg/ubsan/vptr-12.C b/gcc/testsuite/g++.dg/ubsan/vptr-12.C new file mode 100644 index 00000000000..96c8473d757 --- /dev/null +++ b/gcc/testsuite/g++.dg/ubsan/vptr-12.C @@ -0,0 +1,26 @@ +// { dg-do run } +// { dg-shouldfail "ubsan" } +// { dg-options "-fsanitize=vptr -fno-sanitize-recover=vptr" } + +struct MyClass +{ + virtual ~MyClass () {} + virtual void + Doit () + { + } +}; + +int +main () +{ + MyClass *c = new MyClass; + c->~MyClass (); + c->Doit (); + + return 0; +} + +// { dg-output "\[^\n\r]*vptr-12.C:19:\[0-9]*: runtime error: member call on address 0x\[0-9a-fA-F]* which does not point to an object of type 'MyClass'(\n|\r\n|\r)" } +// { dg-output "0x\[0-9a-fA-F]*: note: object has invalid vptr(\n|\r\n|\r)" } +