+2017-11-15 Martin Liska <mliska@suse.cz>
+
+ * decl.c (begin_destructor_body): In case of VPTR sanitization
+ (with disabled recovery), zero vptr in order to catch virtual calls
+ after lifetime of an object.
+
2017-11-14 Jason Merrill <jason@redhat.com>
Use GTY((cache)) on some hash tables.
if (flag_lifetime_dse
/* Clobbering an empty base is harmful if it overlays real data. */
&& !is_empty_class (current_class_type))
- finish_decl_cleanup (NULL_TREE, build_clobber_this ());
+ {
+ if (sanitize_flags_p (SANITIZE_VPTR)
+ && (flag_sanitize_recover & SANITIZE_VPTR) == 0
+ && TYPE_CONTAINS_VPTR_P (current_class_type))
+ {
+ tree binfo = TYPE_BINFO (current_class_type);
+ tree ref
+ = cp_build_indirect_ref (current_class_ptr, RO_NULL,
+ tf_warning_or_error);
+
+ tree vtbl_ptr = build_vfield_ref (ref, TREE_TYPE (binfo));
+ tree vtbl = build_zero_cst (TREE_TYPE (vtbl_ptr));
+ tree stmt = cp_build_modify_expr (input_location, vtbl_ptr,
+ NOP_EXPR, vtbl,
+ tf_warning_or_error);
+ finish_decl_cleanup (NULL_TREE, stmt);
+ }
+ else
+ finish_decl_cleanup (NULL_TREE, build_clobber_this ());
+ }
/* And insert cleanups for our bases and members so that they
will be properly destroyed if we throw. */
--- /dev/null
+// { 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:16:\[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" }