@@ -151,8 +151,7 @@ sanopt_optimize_walker (basic_block bb, struct sanopt_ctx *ctx)
|| flag_sanitize_undefined_trap_on_error
|| gimple_location (g)
== gimple_location (stmt);
- if (!remove && gimple_bb (g) == gimple_bb (stmt)
- && tree_int_cst_compare (cur_align, align) == 0)
+ if (!remove && gimple_bb (g) == gimple_bb (stmt))
v.pop ();
break;
}
@@ -1,6 +1,6 @@
/* { dg-do run } */
/* { dg-skip-if "" { *-*-* } { "*" } { "-O2" } } */
-/* { dg-options "-fsanitize=undefined" } */
+/* { dg-options "-fsanitize=object-size" } */
static char a[128];
static int b[128];
@@ -19,8 +19,7 @@ fn2 (int i)
return a[i & 128];
}
-/* { dg-output "index 128 out of bounds for type 'char \\\[128\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*load of address \[^\n\r]* with insufficient space for an object of type 'char'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "load of address \[^\n\r]* with insufficient space for an object of type 'char'\[^\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)" } */
@@ -39,7 +38,6 @@ fn4 (int i)
return b[i & 128];
}
-/* { dg-output "\[^\n\r]*index 128 out of bounds for type 'int \\\[128\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output "\[^\n\r]*load of address \[^\n\r]* with insufficient space for an object of type 'int'\[^\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)" } */
@@ -52,7 +50,6 @@ fn5 (int i, int j)
return b[i & j];
}
-/* { dg-output "\[^\n\r]*index 128 out of bounds for type 'int \\\[128\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output "\[^\n\r]*load of address \[^\n\r]* with insufficient space for an object of type 'int'\[^\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)" } */
@@ -1,6 +1,6 @@
/* { dg-do run } */
/* { dg-skip-if "" { *-*-* } { "*" } { "-O2" } } */
-/* { dg-options "-fsanitize=undefined" } */
+/* { dg-options "-fsanitize=object-size" } */
/* Test PARM_DECLs and RESULT_DECLs. */
@@ -35,7 +35,6 @@ f2 (int i)
return x;
}
-/* { dg-output "\[^\n\r]*index 12 out of bounds for type 'char \\\[8\\\]'\[^\n\r]*(\n|\r\n|\r)" { target { c++ } } } */
/* { dg-output "\[^\n\r]*store to address \[^\n\r]* with insufficient space for an object of type 'char'\[^\n\r]*(\n|\r\n|\r)" { target { c++ } } } */
/* { dg-output "\[^\n\r]*note: pointer points here\[^\n\r]*(\n|\r\n|\r)" { target { c++ } } } */
/* { dg-output "\[^\n\r]*\[^\n\r]*(\n|\r\n|\r)" { target { c++ } } } */
@@ -64,7 +63,6 @@ f4 (int i)
return s.d[i].b;
}
-/* { dg-output "\[^\n\r]*index 12 out of bounds for type 'U \\\[10\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output "\[^\n\r]*load of address \[^\n\r]* with insufficient space for an object of type 'unsigned int'\[^\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)" } */
@@ -0,0 +1,67 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fsanitize=undefined -fno-sanitize-recover=object-size" } */
+/* Test that we only emit UBSAN_BOUNDS for the following ARRAY_REFs. */
+
+static int g;
+struct S { int a[10]; };
+
+__attribute__((noinline, noclone)) void
+fn1 (void)
+{
+ int a[10];
+ asm ("" : : "r" (&a) : "memory");
+ g = a[10];
+}
+
+/* { dg-output "index 10 out of bounds for type 'int \\\[10\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
+
+__attribute__((noinline, noclone)) void
+fn2 (int i)
+{
+ int a[10];
+ asm ("" : : "r" (&a) : "memory");
+ g = a[i];
+}
+
+/* { dg-output "\[^\n\r]*index 10 out of bounds for type 'int \\\[10\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
+
+__attribute__((noinline, noclone)) void
+fn3 (int i)
+{
+ int a[10][10][10];
+ asm ("" : : "r" (&a) : "memory");
+ g += a[i][5][5];
+}
+
+/* { dg-output "\[^\n\r]*index 10 out of bounds for type 'int \\\[10\\\]\\\[10\\\]\\\[10\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
+
+__attribute__((noinline, noclone)) void
+fn4 (int i)
+{
+ struct S s;
+ asm ("" : : "r" (&s.a) : "memory");
+ g = s.a[i];
+}
+
+/* { dg-output "\[^\n\r]*index 10 out of bounds for type 'int \\\[10\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
+
+__attribute__((noinline, noclone)) void
+fn5 (int i)
+{
+ int a[10];
+ a[1] = 10;
+ asm ("" : : "r" (&a) : "memory");
+ g = a[a[1]];
+}
+
+/* { dg-output "\[^\n\r]*index 10 out of bounds for type 'int \\\[10\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
+
+int
+main ()
+{
+ fn1 ();
+ fn2 (10);
+ fn3 (10);
+ fn4 (10);
+ fn5 (10);
+}
@@ -1484,6 +1484,22 @@ instrument_object_size (gimple_stmt_iterator *gsi, bool is_lhs)
|| bitsize != size_in_bytes * BITS_PER_UNIT)
return;
+ /* Don't instrument ARRAY_REFs if -fsanitize=bounds already
+ took care of that. */
+ gimple_stmt_iterator gsi2 = *gsi;
+ if ((flag_sanitize & SANITIZE_BOUNDS) && !gsi_end_p (gsi2))
+ {
+ /* Look at the previous statement. */
+ gsi_prev (&gsi2);
+ gimple prev_stmt = gsi_stmt (gsi2);
+ if (prev_stmt && is_gimple_call (prev_stmt)
+ && gimple_call_internal_p (prev_stmt)
+ && gimple_call_internal_fn (prev_stmt) == IFN_UBSAN_BOUNDS)
+ /* Ok, we have at least one UBSAN_BOUNDS call that is checking
+ this very ARRAY_REF. No need to emit objsize checking. */
+ return;
+ }
+
bool decl_p = DECL_P (inner);
tree base = decl_p ? inner : TREE_OPERAND (inner, 0);
tree ptr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (t)), t);
@@ -1630,6 +1646,16 @@ pass_ubsan::execute (function *fun)
continue;
}
+ /* Perform this instrumentation first, so we can easily
+ check for UBSAN_BOUNDS before this statement. */
+ if (flag_sanitize & SANITIZE_OBJECT_SIZE)
+ {
+ if (gimple_store_p (stmt))
+ instrument_object_size (&gsi, true);
+ if (gimple_assign_load_p (stmt))
+ instrument_object_size (&gsi, false);
+ }
+
if ((flag_sanitize & SANITIZE_SI_OVERFLOW)
&& is_gimple_assign (stmt))
instrument_si_overflow (gsi);
@@ -1664,14 +1690,6 @@ pass_ubsan::execute (function *fun)
bb = gimple_bb (stmt);
}
- if (flag_sanitize & SANITIZE_OBJECT_SIZE)
- {
- if (gimple_store_p (stmt))
- instrument_object_size (&gsi, true);
- if (gimple_assign_load_p (stmt))
- instrument_object_size (&gsi, false);
- }
-
gsi_next (&gsi);
}
}