init.c (build_vec_init): Call ubsan_instrument_bounds to check whether an initializer...
authorJason Merrill <jason@redhat.com>
Thu, 8 Jan 2015 20:58:39 +0000 (15:58 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Thu, 8 Jan 2015 20:58:39 +0000 (15:58 -0500)
* init.c (build_vec_init): Call ubsan_instrument_bounds to check
whether an initializer-list is too big for a VLA.
(throw_bad_array_length): Remove.
* cp-tree.h: Remove prototype.

From-SVN: r219359

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/init.c
gcc/doc/invoke.texi
gcc/testsuite/g++.dg/ubsan/vla-1.C [new file with mode: 0644]

index 5c576bc262b610e728faae4e45f3d3da2197fd35..46d795705d9c553eb9b4a05d0ca547282bb9e542 100644 (file)
@@ -1,3 +1,10 @@
+2015-01-08  Jason Merrill  <jason@redhat.com>
+
+       * init.c (build_vec_init): Call ubsan_instrument_bounds to check
+       whether an initializer-list is too big for a VLA.
+       (throw_bad_array_length): Remove.
+       * cp-tree.h: Remove prototype.
+
 2015-01-08  Paolo Carlini  <paolo.carlini@oracle.com>
 
        PR c++/60753
index 2afa531addaecbbc63485569c147010a8b80e24b..77f2b5b918ca2b252924764ee5fd2f6beafdaa39 100644 (file)
@@ -5574,7 +5574,6 @@ extern tree get_nsdmi                             (tree, bool);
 extern tree build_offset_ref                   (tree, tree, bool,
                                                 tsubst_flags_t);
 extern tree throw_bad_array_new_length         (void);
-extern tree throw_bad_array_length             (void);
 extern tree build_new                          (vec<tree, va_gc> **, tree, tree,
                                                 vec<tree, va_gc> **, int,
                                                  tsubst_flags_t);
index a5ac11c3a0fabc9e0e80318d94d32e2562b509c1..6f324926aefaf6d2f6d432c7e87a73694bbdd2c3 100644 (file)
@@ -32,6 +32,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "target.h"
 #include "gimplify.h"
 #include "wide-int.h"
+#include "c-family/c-ubsan.h"
 
 static bool begin_init_stmts (tree *, tree *);
 static tree finish_init_stmts (bool, tree, tree);
@@ -2241,20 +2242,6 @@ throw_bad_array_new_length (void)
   return build_cxx_call (fn, 0, NULL, tf_warning_or_error);
 }
 
-/* Call __cxa_bad_array_length to indicate that there were too many
-   initializers.  */
-
-tree
-throw_bad_array_length (void)
-{
-  tree fn = get_identifier ("__cxa_throw_bad_array_length");
-  if (!get_global_value_if_present (fn, &fn))
-    fn = push_throw_library_fn (fn, build_function_type_list (void_type_node,
-                                                             NULL_TREE));
-
-  return build_cxx_call (fn, 0, NULL, tf_warning_or_error);
-}
-
 /* Generate code for a new-expression, including calling the "operator
    new" function, initializing the object, and, if an exception occurs
    during construction, cleaning up.  The arguments are as for
@@ -3419,7 +3406,6 @@ build_vec_init (tree base, tree maxindex, tree init,
   tree obase = base;
   bool xvalue = false;
   bool errors = false;
-  tree length_check = NULL_TREE;
 
   if (TREE_CODE (atype) == ARRAY_TYPE && TYPE_DOMAIN (atype))
     maxindex = array_type_nelts (atype);
@@ -3440,12 +3426,9 @@ build_vec_init (tree base, tree maxindex, tree init,
 
   /* If we have a braced-init-list, make sure that the array
      is big enough for all the initializers.  */
-  if (init && TREE_CODE (init) == CONSTRUCTOR
-      && CONSTRUCTOR_NELTS (init) > 0
-      && !TREE_CONSTANT (maxindex)
-      && flag_exceptions)
-    length_check = fold_build2 (LT_EXPR, boolean_type_node, maxindex,
-                               size_int (CONSTRUCTOR_NELTS (init) - 1));
+  bool length_check = (init && TREE_CODE (init) == CONSTRUCTOR
+                      && CONSTRUCTOR_NELTS (init) > 0
+                      && !TREE_CONSTANT (maxindex));
 
   if (init
       && TREE_CODE (atype) == ARRAY_TYPE
@@ -3468,10 +3451,6 @@ build_vec_init (tree base, tree maxindex, tree init,
       if (BRACE_ENCLOSED_INITIALIZER_P (init))
        init = digest_init (atype, init, complain);
       stmt_expr = build2 (INIT_EXPR, atype, base, init);
-      if (length_check)
-       stmt_expr = build3 (COND_EXPR, atype, length_check,
-                           throw_bad_array_length (),
-                           stmt_expr);
       return stmt_expr;
     }
 
@@ -3582,11 +3561,30 @@ build_vec_init (tree base, tree maxindex, tree init,
 
       if (length_check)
        {
-         tree throw_call;
-         throw_call = throw_bad_array_new_length ();
-         length_check = build3 (COND_EXPR, void_type_node, length_check,
-                                throw_call, void_node);
-         finish_expr_stmt (length_check);
+         tree nelts = size_int (CONSTRUCTOR_NELTS (init) - 1);
+         if (TREE_CODE (atype) != ARRAY_TYPE)
+           {
+             if (flag_exceptions)
+               {
+                 tree c = fold_build2 (LT_EXPR, boolean_type_node, iterator,
+                                       nelts);
+                 c = build3 (COND_EXPR, void_type_node, c,
+                             throw_bad_array_new_length (), void_node);
+                 finish_expr_stmt (c);
+               }
+             /* Don't check an array new when -fno-exceptions.  */
+           }
+         else if (flag_sanitize & SANITIZE_BOUNDS
+                  && current_function_decl
+                  && !lookup_attribute ("no_sanitize_undefined",
+                                        DECL_ATTRIBUTES
+                                        (current_function_decl)))
+           {
+             /* Make sure the last element of the initializer is in bounds. */
+             finish_expr_stmt
+               (ubsan_instrument_bounds
+                (input_location, obase, &nelts, /*ignore_off_by_one*/false));
+           }
        }
 
       if (try_const)
index 817312741c6be558869ab5764d3ce46f9b129f32..2d06396b2418bcee90745595df81fb731f740c42 100644 (file)
@@ -5629,9 +5629,7 @@ call into a diagnostics message call instead.  When reaching the
 @item -fsanitize=vla-bound
 @opindex fsanitize=vla-bound
 This option instructs the compiler to check that the size of a variable
-length array is positive.  This option does not have any effect in
-@option{-std=c++14} mode, as the standard requires the exception be thrown
-instead.
+length array is positive.
 
 @item -fsanitize=null
 @opindex fsanitize=null
diff --git a/gcc/testsuite/g++.dg/ubsan/vla-1.C b/gcc/testsuite/g++.dg/ubsan/vla-1.C
new file mode 100644 (file)
index 0000000..e7f2494
--- /dev/null
@@ -0,0 +1,13 @@
+// { dg-do run }
+// { dg-options "-Wno-vla -fsanitize=undefined" }
+// { dg-shouldfail "ubsan" }
+// { dg-output "index 1 out of bounds" }
+
+void f(int i) {
+  int ar[i] = { 42, 24 };
+}
+
+int main()
+{
+  f(1);
+}