https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70147
--- Comment #15 from Bernd Edlinger <bernd.edlinger at hotmail dot de> ---
Yep, maybe this would be a compromise:
Index: cp-ubsan.c
===================================================================
--- cp-ubsan.c (revision 234184)
+++ cp-ubsan.c (working copy)
@@ -285,6 +285,15 @@ cp_ubsan_dfs_initialize_vtbl_ptrs (tree binfo, voi
if (!BINFO_PRIMARY_P (binfo) || BINFO_VIRTUAL_P (binfo))
{
+ tree if_stmt = NULL_TREE;
+
+ if (BINFO_VIRTUAL_P (binfo))
+ {
+ tree flag = DECL_CHAIN (DECL_ARGUMENTS (current_function_decl));
+ if_stmt = begin_if_stmt ();
+ finish_if_stmt_cond (flag, if_stmt);
+ }
+
tree base_ptr = TREE_VALUE ((tree) data);
base_ptr = build_base_path (PLUS_EXPR, base_ptr, binfo, /*nonnull=*/1,
@@ -301,6 +310,11 @@ cp_ubsan_dfs_initialize_vtbl_ptrs (tree binfo, voi
tree vtbl = build_zero_cst (TREE_TYPE (vtbl_ptr));
finish_expr_stmt (cp_build_modify_expr (vtbl_ptr, NOP_EXPR, vtbl,
tf_warning_or_error));
+ if (if_stmt != NULL_TREE)
+ {
+ finish_then_clause (if_stmt);
+ finish_if_stmt (if_stmt);
+ }
}
return NULL_TREE;
It does not catch the calls to i() but, it slightly improves
this test case and avoids the eh-problem from the previous example:
cat test1.cc
struct A { A () {} A (int x) : a (x) {} virtual int i () { return 0; } int a;
};
__attribute__((noinline,noclone)) int foo (A* x) { return x->i(); }
struct B : virtual A { B () {} B (int x) : A (foo (this)) {} };
struct C : virtual B { C () : A (foo (this)), B (foo (this)) {} };
int
main ()
{
C cc;
}
this invalid example does not crash as it would with my other patch,
which never erases the virtual vptr.
g++ -fsanitize=undefined -fno-sanitize-recover=undefined test1.cc
./a.out
test1.cc:2:64: runtime error: load of null pointer of type '<unknown> *'
note the message is about null pointer not undefined vptr, but at
least it is not a segfault.