diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3f883c2b7a8..d6f2d7240d4 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2017-06-16 Jakub Jelinek + + PR sanitizer/81094 + * ubsan.c (instrument_null): Add T argument, use it instead + of computing it based on IS_LHS. + (instrument_object_size): Likewise. + (pass_ubsan::execute): Adjust instrument_null and + instrument_object_size callers to pass gimple_get_lhs or + gimple_assign_rhs1 result to it. Use instrument_null instead of + calling get_base_address and instrument_mem_ref. Handle + aggregate call arguments for object-size sanitization. + 2017-06-16 Yury Gribov PR tree-optimization/81089 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 7e48992478b..2257edc7864 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2017-06-16 Jakub Jelinek + + PR sanitizer/81094 + * c-c++-common/ubsan/object-size-11.c: New test. + 2017-06-15 Martin Sebor PR c++/80560 diff --git a/gcc/testsuite/c-c++-common/ubsan/object-size-11.c b/gcc/testsuite/c-c++-common/ubsan/object-size-11.c new file mode 100644 index 00000000000..866c7ed4086 --- /dev/null +++ b/gcc/testsuite/c-c++-common/ubsan/object-size-11.c @@ -0,0 +1,53 @@ +/* PR sanitizer/81094 */ +/* { dg-do run } */ +/* { dg-skip-if "" { *-*-* } { "*" } { "-O2" } } */ +/* { dg-options "-fsanitize=object-size" } */ + +#define N 20 + +struct S { int i; }; + +__attribute__((noinline, noclone)) void +f0 (struct S s) +{ + asm volatile ("" : : "r" (s.i) : "memory"); +} + +__attribute__((noinline, noclone)) void +f1 (int i) +{ + char *orig; + struct S *p; + orig = (char *) __builtin_calloc (N, sizeof (struct S)); + p = (struct S *) orig; + f0 (*(p + i)); + f0 (p[i]); + p++; + f0 (p[i - 1]); + f0 (*(p + i - 1)); + __builtin_free (orig); +} + +/* { dg-output "load of address \[^\n\r]* with insufficient space for an object of type 'struct S'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*note: pointer points here\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*\\^\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*load of address \[^\n\r]* with insufficient space for an object of type 'struct S'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*note: pointer points here\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*\\^\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*load of address \[^\n\r]* with insufficient space for an object of type 'struct S'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*note: pointer points here\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*\\^\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*load of address \[^\n\r]* with insufficient space for an object of type 'struct S'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*note: pointer points here\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*\\^" } */ + +int +main () +{ + f1 (N); + return 0; +} diff --git a/gcc/ubsan.c b/gcc/ubsan.c index cee525ccf98..52ba5b586bd 100644 --- a/gcc/ubsan.c +++ b/gcc/ubsan.c @@ -1204,10 +1204,8 @@ instrument_mem_ref (tree mem, tree base, gimple_stmt_iterator *iter, /* Perform the pointer instrumentation. */ static void -instrument_null (gimple_stmt_iterator gsi, bool is_lhs) +instrument_null (gimple_stmt_iterator gsi, tree t, bool is_lhs) { - gimple *stmt = gsi_stmt (gsi); - tree t = is_lhs ? gimple_get_lhs (stmt) : gimple_assign_rhs1 (stmt); /* Handle also e.g. &s->i. */ if (TREE_CODE (t) == ADDR_EXPR) t = TREE_OPERAND (t, 0); @@ -1754,11 +1752,10 @@ instrument_nonnull_return (gimple_stmt_iterator *gsi) points to an out-of-bounds location. */ static void -instrument_object_size (gimple_stmt_iterator *gsi, bool is_lhs) +instrument_object_size (gimple_stmt_iterator *gsi, tree t, bool is_lhs) { gimple *stmt = gsi_stmt (*gsi); location_t loc = gimple_location (stmt); - tree t = is_lhs ? gimple_get_lhs (stmt) : gimple_assign_rhs1 (stmt); tree type; tree index = NULL_TREE; HOST_WIDE_INT size_in_bytes; @@ -1989,9 +1986,9 @@ pass_ubsan::execute (function *fun) if (sanitize_flags_p (SANITIZE_NULL | SANITIZE_ALIGNMENT, fun->decl)) { if (gimple_store_p (stmt)) - instrument_null (gsi, true); + instrument_null (gsi, gimple_get_lhs (stmt), true); if (gimple_assign_single_p (stmt)) - instrument_null (gsi, false); + instrument_null (gsi, gimple_assign_rhs1 (stmt), false); if (is_gimple_call (stmt)) { unsigned args_num = gimple_call_num_args (stmt); @@ -2000,10 +1997,7 @@ pass_ubsan::execute (function *fun) tree arg = gimple_call_arg (stmt, i); if (is_gimple_reg (arg) || is_gimple_min_invariant (arg)) continue; - tree base = get_base_address (arg); - if (TREE_CODE (base) == MEM_REF - && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME) - instrument_mem_ref (arg, base, &gsi, false); + instrument_null (gsi, arg, false); } } } @@ -2033,9 +2027,21 @@ pass_ubsan::execute (function *fun) if (sanitize_flags_p (SANITIZE_OBJECT_SIZE, fun->decl)) { if (gimple_store_p (stmt)) - instrument_object_size (&gsi, true); + instrument_object_size (&gsi, gimple_get_lhs (stmt), true); if (gimple_assign_load_p (stmt)) - instrument_object_size (&gsi, false); + instrument_object_size (&gsi, gimple_assign_rhs1 (stmt), + false); + if (is_gimple_call (stmt)) + { + unsigned args_num = gimple_call_num_args (stmt); + for (unsigned i = 0; i < args_num; ++i) + { + tree arg = gimple_call_arg (stmt, i); + if (is_gimple_reg (arg) || is_gimple_min_invariant (arg)) + continue; + instrument_object_size (&gsi, arg, false); + } + } } gsi_next (&gsi);