diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2b8ce47490c..31e9670fa89 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2013-11-27 Marek Polacek + + PR sanitizer/59306 + * ubsan.c (instrument_null): Use gimple_store_p/gimple_assign_load_p + instead of walk_gimple_op. + (ubsan_pass): Adjust. Call instrument_null only if SANITIZE_NULL. + 2013-11-27 Aldy Hernandez Jakub Jelinek diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 20e885ade3c..084e8128dcc 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2013-11-27 Marek Polacek + + PR sanitizer/59306 + * g++.dg/ubsan/pr59306.C: New test. + 2013-11-27 Aldy Hernandez Jakub Jelinek diff --git a/gcc/testsuite/g++.dg/ubsan/pr59306.C b/gcc/testsuite/g++.dg/ubsan/pr59306.C new file mode 100644 index 00000000000..426e6a5bd5f --- /dev/null +++ b/gcc/testsuite/g++.dg/ubsan/pr59306.C @@ -0,0 +1,14 @@ +// { dg-do compile } +// { dg-options "-fsanitize=undefined" } +// { dg-skip-if "" { *-*-* } { "-flto" } { "" } } + +class A { + void bar (void (A::*) (int)); + void foo (int); + void B (); +}; + +void A::B() +{ + bar (&A::foo); +} diff --git a/gcc/ubsan.c b/gcc/ubsan.c index fa6b42a868f..e33e62a028a 100644 --- a/gcc/ubsan.c +++ b/gcc/ubsan.c @@ -614,24 +614,22 @@ instrument_mem_ref (tree t, gimple_stmt_iterator *iter, bool is_lhs) gsi_insert_before (iter, g, GSI_SAME_STMT); } -/* Callback function for the pointer instrumentation. */ +/* Perform the pointer instrumentation. */ -static tree -instrument_null (tree *tp, int * /*walk_subtree*/, void *data) +static void +instrument_null (gimple_stmt_iterator gsi, bool is_lhs) { - tree t = *tp; + gimple stmt = gsi_stmt (gsi); + tree t = is_lhs ? gimple_get_lhs (stmt) : gimple_assign_rhs1 (stmt); + t = get_base_address (t); const enum tree_code code = TREE_CODE (t); - struct walk_stmt_info *wi = (struct walk_stmt_info *) data; - if (code == MEM_REF && TREE_CODE (TREE_OPERAND (t, 0)) == SSA_NAME) - instrument_mem_ref (TREE_OPERAND (t, 0), &wi->gsi, wi->is_lhs); + instrument_mem_ref (TREE_OPERAND (t, 0), &gsi, is_lhs); else if (code == ADDR_EXPR && POINTER_TYPE_P (TREE_TYPE (t)) && TREE_CODE (TREE_TYPE (TREE_TYPE (t))) == METHOD_TYPE) - instrument_member_call (&wi->gsi); - - return NULL_TREE; + instrument_member_call (&gsi); } /* Gate and execute functions for ubsan pass. */ @@ -646,7 +644,6 @@ ubsan_pass (void) { for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);) { - struct walk_stmt_info wi; gimple stmt = gsi_stmt (gsi); if (is_gimple_debug (stmt) || gimple_clobber_p (stmt)) { @@ -654,9 +651,14 @@ ubsan_pass (void) continue; } - memset (&wi, 0, sizeof (wi)); - wi.gsi = gsi; - walk_gimple_op (stmt, instrument_null, &wi); + if (flag_sanitize & SANITIZE_NULL) + { + if (gimple_store_p (stmt)) + instrument_null (gsi, true); + if (gimple_assign_load_p (stmt)) + instrument_null (gsi, false); + } + gsi_next (&gsi); } }