mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-20 11:00:57 +08:00
re PR c++/70035 (Calling a non-virtual member in base-class constructor call with ubsan causes segfault when superclass has virtual member with same name)
PR c++/70035 * cp-tree.h (cp_ubsan_maybe_initialize_vtbl_ptrs): New prototype. * decl.c (start_preparsed_function): Call cp_ubsan_maybe_initialize_vtbl_ptrs if needed. * cp-ubsan.c (cp_ubsan_dfs_initialize_vtbl_ptrs, cp_ubsan_maybe_initialize_vtbl_ptrs): New functions. * g++.dg/ubsan/pr70035.C: New test. From-SVN: r233984
This commit is contained in:
parent
188e53bd7e
commit
0c8825de94
@ -1,3 +1,12 @@
|
||||
2016-03-04 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR c++/70035
|
||||
* cp-tree.h (cp_ubsan_maybe_initialize_vtbl_ptrs): New prototype.
|
||||
* decl.c (start_preparsed_function): Call
|
||||
cp_ubsan_maybe_initialize_vtbl_ptrs if needed.
|
||||
* cp-ubsan.c (cp_ubsan_dfs_initialize_vtbl_ptrs,
|
||||
cp_ubsan_maybe_initialize_vtbl_ptrs): New functions.
|
||||
|
||||
2016-03-04 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/67364
|
||||
|
@ -6940,6 +6940,7 @@ extern void cp_ubsan_maybe_instrument_member_call (tree);
|
||||
extern void cp_ubsan_instrument_member_accesses (tree *);
|
||||
extern tree cp_ubsan_maybe_instrument_downcast (location_t, tree, tree, tree);
|
||||
extern tree cp_ubsan_maybe_instrument_cast_to_vbase (location_t, tree, tree);
|
||||
extern void cp_ubsan_maybe_initialize_vtbl_ptrs (tree);
|
||||
|
||||
/* -- end of C++ */
|
||||
|
||||
|
@ -272,3 +272,55 @@ cp_ubsan_maybe_instrument_cast_to_vbase (location_t loc, tree type, tree op)
|
||||
return cp_ubsan_maybe_instrument_vptr (loc, op, type, true,
|
||||
UBSAN_CAST_TO_VBASE);
|
||||
}
|
||||
|
||||
/* Called from initialize_vtbl_ptrs via dfs_walk. BINFO is the base
|
||||
which we want to initialize the vtable pointer for, DATA is
|
||||
TREE_LIST whose TREE_VALUE is the this ptr expression. */
|
||||
|
||||
static tree
|
||||
cp_ubsan_dfs_initialize_vtbl_ptrs (tree binfo, void *data)
|
||||
{
|
||||
if (!TYPE_CONTAINS_VPTR_P (BINFO_TYPE (binfo)))
|
||||
return dfs_skip_bases;
|
||||
|
||||
if (!BINFO_PRIMARY_P (binfo) || BINFO_VIRTUAL_P (binfo))
|
||||
{
|
||||
tree base_ptr = TREE_VALUE ((tree) data);
|
||||
|
||||
base_ptr = build_base_path (PLUS_EXPR, base_ptr, binfo, /*nonnull=*/1,
|
||||
tf_warning_or_error);
|
||||
|
||||
/* Compute the location of the vtpr. */
|
||||
tree vtbl_ptr
|
||||
= build_vfield_ref (cp_build_indirect_ref (base_ptr, RO_NULL,
|
||||
tf_warning_or_error),
|
||||
TREE_TYPE (binfo));
|
||||
gcc_assert (vtbl_ptr != error_mark_node);
|
||||
|
||||
/* Assign NULL to the vptr. */
|
||||
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));
|
||||
}
|
||||
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Initialize all the vtable pointers in the object pointed to by
|
||||
ADDR to NULL, so that we catch invalid calls to methods before
|
||||
mem-initializers are completed. */
|
||||
|
||||
void
|
||||
cp_ubsan_maybe_initialize_vtbl_ptrs (tree addr)
|
||||
{
|
||||
if (!cp_ubsan_instrument_vptr_p (NULL_TREE))
|
||||
return;
|
||||
|
||||
tree type = TREE_TYPE (TREE_TYPE (addr));
|
||||
tree list = build_tree_list (type, addr);
|
||||
|
||||
/* Walk through the hierarchy, initializing the vptr in each base
|
||||
class to NULL. */
|
||||
dfs_walk_once (TYPE_BINFO (type), cp_ubsan_dfs_initialize_vtbl_ptrs,
|
||||
NULL, list);
|
||||
}
|
||||
|
@ -14136,6 +14136,13 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
|
||||
finish_expr_stmt (exprstmt);
|
||||
}
|
||||
|
||||
if (!processing_template_decl
|
||||
&& DECL_CONSTRUCTOR_P (decl1)
|
||||
&& (flag_sanitize & SANITIZE_VPTR)
|
||||
&& !DECL_CLONED_FUNCTION_P (decl1)
|
||||
&& !implicit_default_ctor_p (decl1))
|
||||
cp_ubsan_maybe_initialize_vtbl_ptrs (current_class_ptr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,8 @@
|
||||
2016-03-04 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR c++/70035
|
||||
* g++.dg/ubsan/pr70035.C: New test.
|
||||
|
||||
PR target/70062
|
||||
* gcc.target/i386/pr70062.c: New test.
|
||||
|
||||
|
26
gcc/testsuite/g++.dg/ubsan/pr70035.C
Normal file
26
gcc/testsuite/g++.dg/ubsan/pr70035.C
Normal file
@ -0,0 +1,26 @@
|
||||
// PR c++/70035
|
||||
// { dg-do run }
|
||||
// { dg-shouldfail "ubsan" }
|
||||
// { dg-options "-fsanitize=vptr -fno-sanitize-recover=undefined" }
|
||||
|
||||
struct A {
|
||||
A (int) {}
|
||||
virtual int foo () { return 1; }
|
||||
};
|
||||
struct B : public A {
|
||||
using A::foo;
|
||||
B (int x) : A (foo (x)) {}
|
||||
int foo (int x) { return x * 2; }
|
||||
};
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
B b (20);
|
||||
}
|
||||
|
||||
// { dg-output "\[^\n\r]*pr70035.C:12:\[0-9]*: runtime error: member call on address 0x\[0-9a-fA-F]* which does not point to an object of type 'B'(\n|\r\n|\r)" }
|
||||
// { dg-output "0x\[0-9a-fA-F]*: note: object has invalid vptr(\n|\r\n|\r)" }
|
||||
// { dg-output " ?.. .. .. .. ?.. .. .. .. ?.. .. .. .. \[^\n\r]*(\n|\r\n|\r)" }
|
||||
// { dg-output " ?\\^~~~~~~~~~~\[^\n\r]*(\n|\r\n|\r)" }
|
||||
// { dg-output " ?invalid vptr" }
|
Loading…
x
Reference in New Issue
Block a user