+2017-06-16 Jakub Jelinek <jakub@redhat.com>
+
+ 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 <tetra2005@gmail.com>
PR tree-optimization/81089
--- /dev/null
+/* 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;
+}
/* 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);
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;
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);
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);
}
}
}
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);