[ubsan] Add -fsanitize=bounds-strict

Marek Polacek polacek@redhat.com
Wed Apr 29 15:22:00 GMT 2015


This patch adds the -fsanitize=bounds-strict option Martin U. wanted; it is
actually based on his earlier patch, I did only some small adjustments.

Bootstrapped/regtested on x86_64-linux, ok for trunk?

2015-04-29  Marek Polacek  <polacek@redhat.com>
	    Martin Uecker  <uecker@eecs.berkeley.edu>

	* c-ubsan.c (ubsan_instrument_bounds): Don't skip instrumenting
	flexible member array-like members if SANITIZE_BOUNDS_STRICT.

	* doc/invoke.texi: Document -fsanitize=bounds-strict.
	* flag-types.h (enum sanitize_code): Add SANITIZE_BOUNDS_STRICT, or it
	into SANITIZE_NONDEFAULT.
	* opts.c (common_handle_option): Handle -fsanitize=bounds-strict.

	* c-c++-common/ubsan/bounds-10.c: New test.

diff --git gcc/c-family/c-ubsan.c gcc/c-family/c-ubsan.c
index a14426f..dbbdc5b 100644
--- gcc/c-family/c-ubsan.c
+++ gcc/c-family/c-ubsan.c
@@ -301,9 +301,11 @@ ubsan_instrument_bounds (location_t loc, tree array, tree *index,
     bound = fold_build2 (PLUS_EXPR, TREE_TYPE (bound), bound,
 			 build_int_cst (TREE_TYPE (bound), 1));
 
-  /* Detect flexible array members and suchlike.  */
+  /* Detect flexible array members and suchlike, unless
+     -fsanitize=bounds-strict.  */
   tree base = get_base_address (array);
-  if (TREE_CODE (array) == COMPONENT_REF
+  if ((flag_sanitize & SANITIZE_BOUNDS_STRICT) == 0
+      && TREE_CODE (array) == COMPONENT_REF
       && base && (TREE_CODE (base) == INDIRECT_REF
 		  || TREE_CODE (base) == MEM_REF))
     {
diff --git gcc/doc/invoke.texi gcc/doc/invoke.texi
index 7d2f6e5..d050ba6 100644
--- gcc/doc/invoke.texi
+++ gcc/doc/invoke.texi
@@ -5728,6 +5728,13 @@ This option enables instrumentation of array bounds.  Various out of bounds
 accesses are detected.  Flexible array members, flexible array member-like
 arrays, and initializers of variables with static storage are not instrumented.
 
+@item -fsanitize=bounds-strict
+@opindex fsanitize=bounds-strict
+This option enables strict instrumentation of array bounds.  Most out of bounds
+accesses are detected, including flexible array members and flexible array
+member-like arrays.  Initializers of variables with static storage are not
+instrumented.
+
 @item -fsanitize=alignment
 @opindex fsanitize=alignment
 
diff --git gcc/flag-types.h gcc/flag-types.h
index bfdce44..2f820a5 100644
--- gcc/flag-types.h
+++ gcc/flag-types.h
@@ -238,6 +238,7 @@ enum sanitize_code {
   SANITIZE_RETURNS_NONNULL_ATTRIBUTE = 1UL << 19,
   SANITIZE_OBJECT_SIZE = 1UL << 20,
   SANITIZE_VPTR = 1UL << 21,
+  SANITIZE_BOUNDS_STRICT = 1UL << 22,
   SANITIZE_UNDEFINED = SANITIZE_SHIFT | SANITIZE_DIVIDE | SANITIZE_UNREACHABLE
 		       | SANITIZE_VLA | SANITIZE_NULL | SANITIZE_RETURN
 		       | SANITIZE_SI_OVERFLOW | SANITIZE_BOOL | SANITIZE_ENUM
@@ -246,6 +247,7 @@ enum sanitize_code {
 		       | SANITIZE_RETURNS_NONNULL_ATTRIBUTE
 		       | SANITIZE_OBJECT_SIZE | SANITIZE_VPTR,
   SANITIZE_NONDEFAULT = SANITIZE_FLOAT_DIVIDE | SANITIZE_FLOAT_CAST
+			| SANITIZE_BOUNDS_STRICT
 };
 
 /* flag_vtable_verify initialization levels. */
diff --git gcc/opts.c gcc/opts.c
index 39c190d..8c6716b 100644
--- gcc/opts.c
+++ gcc/opts.c
@@ -1584,6 +1584,8 @@ common_handle_option (struct gcc_options *opts,
 	      { "float-cast-overflow", SANITIZE_FLOAT_CAST,
 		sizeof "float-cast-overflow" - 1 },
 	      { "bounds", SANITIZE_BOUNDS, sizeof "bounds" - 1 },
+	      { "bounds-strict", SANITIZE_BOUNDS | SANITIZE_BOUNDS_STRICT,
+		sizeof "bounds-strict" - 1 },
 	      { "alignment", SANITIZE_ALIGNMENT, sizeof "alignment" - 1 },
 	      { "nonnull-attribute", SANITIZE_NONNULL_ATTRIBUTE,
 		sizeof "nonnull-attribute" - 1 },
diff --git gcc/testsuite/c-c++-common/ubsan/bounds-10.c gcc/testsuite/c-c++-common/ubsan/bounds-10.c
index e69de29..a6187b5 100644
--- gcc/testsuite/c-c++-common/ubsan/bounds-10.c
+++ gcc/testsuite/c-c++-common/ubsan/bounds-10.c
@@ -0,0 +1,16 @@
+/* { dg-do run } */
+/* { dg-options "-fsanitize=bounds-strict" } */
+
+struct V { int l; int a[1]; };
+
+int
+main (void)
+{
+  /* For strict, do instrument last array in a struct.  */
+  struct V *v = (struct V *) __builtin_malloc (sizeof (struct V) + 10);
+  v->a[1] = 1;
+
+  return 0;
+}
+
+/* { dg-output "index 1 out of bounds for type 'int \\\[1\\\]'" } */

	Marek



More information about the Gcc-patches mailing list