aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2017-04-03 21:15:36 +0000
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2017-04-03 21:15:36 +0000
commitc571b0c612fe865fe06eac34aa4a7edbc278b5dc (patch)
tree28f3a1d200fa86ca4057f09c132ba79749c015a7
parentbcd9d3669829ac6111c842c8fd31fb271a67e517 (diff)
PR sanitizer/79993 - ICE with VLA initialization from string
PR c++/69487 - wrong VLA initialization from string * init.c (finish_length_check): Split out from build_vec_init. (build_vec_init): Handle STRING_CST. * typeck2.c (split_nonconstant_init): Handle STRING_CST. (digest_init_r): Don't give a STRING_CST VLA type. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@246662 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/cp/ChangeLog9
-rw-r--r--gcc/cp/init.c92
-rw-r--r--gcc/cp/typeck2.c7
-rw-r--r--gcc/testsuite/g++.dg/asan/pr78201.C13
-rw-r--r--gcc/testsuite/g++.dg/ext/vla17.C15
5 files changed, 108 insertions, 28 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 743847908d0..f3c668b870d 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,12 @@
+2017-04-03 Jason Merrill <jason@redhat.com>
+
+ PR sanitizer/79993 - ICE with VLA initialization from string
+ PR c++/69487 - wrong VLA initialization from string
+ * init.c (finish_length_check): Split out from build_vec_init.
+ (build_vec_init): Handle STRING_CST.
+ * typeck2.c (split_nonconstant_init): Handle STRING_CST.
+ (digest_init_r): Don't give a STRING_CST VLA type.
+
2017-03-31 Jakub Jelinek <jakub@redhat.com>
PR c++/79572
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 773279504ee..2015205efd6 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -3884,6 +3884,35 @@ vec_copy_assign_is_trivial (tree inner_elt_type, tree init)
return is_trivially_xible (MODIFY_EXPR, inner_elt_type, fromtype);
}
+/* Subroutine of build_vec_init: Check that the array has at least N
+ elements. Other parameters are local variables in build_vec_init. */
+
+void
+finish_length_check (tree atype, tree iterator, tree obase, unsigned n)
+{
+ tree nelts = build_int_cst (ptrdiff_type_node, n - 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
+ && do_ubsan_in_current_function ())
+ {
+ /* 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));
+ }
+}
+
/* `build_vec_init' returns tree structure that performs
initialization of a vector of aggregate types.
@@ -3932,6 +3961,8 @@ build_vec_init (tree base, tree maxindex, tree init,
tree obase = base;
bool xvalue = false;
bool errors = false;
+ location_t loc = (init ? EXPR_LOC_OR_LOC (init, input_location)
+ : location_of (base));
if (TREE_CODE (atype) == ARRAY_TYPE && TYPE_DOMAIN (atype))
maxindex = array_type_nelts (atype);
@@ -3963,10 +3994,12 @@ build_vec_init (tree base, tree maxindex, tree init,
}
}
- /* If we have a braced-init-list, make sure that the array
+ /* If we have a braced-init-list or string constant, make sure that the array
is big enough for all the initializers. */
- bool length_check = (init && TREE_CODE (init) == CONSTRUCTOR
- && CONSTRUCTOR_NELTS (init) > 0
+ bool length_check = (init
+ && (TREE_CODE (init) == STRING_CST
+ || (TREE_CODE (init) == CONSTRUCTOR
+ && CONSTRUCTOR_NELTS (init) > 0))
&& !TREE_CONSTANT (maxindex));
if (init
@@ -4105,30 +4138,7 @@ build_vec_init (tree base, tree maxindex, tree init,
from_array = 0;
if (length_check)
- {
- tree nelts = build_int_cst (ptrdiff_type_node,
- 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
- && do_ubsan_in_current_function ())
- {
- /* 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));
- }
- }
+ finish_length_check (atype, iterator, obase, CONSTRUCTOR_NELTS (init));
if (try_const)
vec_alloc (const_vec, CONSTRUCTOR_NELTS (init));
@@ -4196,6 +4206,34 @@ build_vec_init (tree base, tree maxindex, tree init,
/* Any elements without explicit initializers get T{}. */
empty_list = true;
}
+ else if (init && TREE_CODE (init) == STRING_CST)
+ {
+ /* Check that the array is at least as long as the string. */
+ if (length_check)
+ finish_length_check (atype, iterator, obase,
+ TREE_STRING_LENGTH (init));
+ tree length = build_int_cst (ptrdiff_type_node,
+ TREE_STRING_LENGTH (init));
+
+ /* Copy the string to the first part of the array. */
+ tree alias_set = build_int_cst (build_pointer_type (type), 0);
+ tree lhs = build2 (MEM_REF, TREE_TYPE (init), base, alias_set);
+ tree stmt = build2 (MODIFY_EXPR, void_type_node, lhs, init);
+ finish_expr_stmt (stmt);
+
+ /* Adjust the counter and pointer. */
+ stmt = cp_build_binary_op (loc, MINUS_EXPR, iterator, length, complain);
+ stmt = build2 (MODIFY_EXPR, void_type_node, iterator, stmt);
+ finish_expr_stmt (stmt);
+
+ stmt = cp_build_binary_op (loc, PLUS_EXPR, base, length, complain);
+ stmt = build2 (MODIFY_EXPR, void_type_node, base, stmt);
+ finish_expr_stmt (stmt);
+
+ /* And set the rest of the array to NUL. */
+ from_array = 0;
+ explicit_value_init_p = true;
+ }
else if (from_array)
{
if (init)
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index 58a01c98f2a..d1a393059a4 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -749,6 +749,10 @@ split_nonconstant_init (tree dest, tree init)
DECL_INITIAL (dest) = init;
TREE_READONLY (dest) = 0;
}
+ else if (TREE_CODE (init) == STRING_CST
+ && array_of_runtime_bound_p (TREE_TYPE (dest)))
+ code = build_vec_init (dest, NULL_TREE, init, /*value-init*/false,
+ /*from array*/1, tf_warning_or_error);
else
code = build2 (INIT_EXPR, TREE_TYPE (dest), dest, init);
@@ -1066,7 +1070,8 @@ digest_init_r (tree type, tree init, bool nested, int flags,
}
}
- if (type != TREE_TYPE (init))
+ if (type != TREE_TYPE (init)
+ && !variably_modified_type_p (type, NULL_TREE))
{
init = copy_node (init);
TREE_TYPE (init) = type;
diff --git a/gcc/testsuite/g++.dg/asan/pr78201.C b/gcc/testsuite/g++.dg/asan/pr78201.C
new file mode 100644
index 00000000000..931ef44a966
--- /dev/null
+++ b/gcc/testsuite/g++.dg/asan/pr78201.C
@@ -0,0 +1,13 @@
+// PR middle-end/78201
+// { dg-do compile }
+// { dg-options "-O2 -fsanitize=address" }
+
+struct B { long d (); } *c;
+long e;
+
+void
+foo ()
+{
+ char a[e] = "";
+ c && c->d();
+}
diff --git a/gcc/testsuite/g++.dg/ext/vla17.C b/gcc/testsuite/g++.dg/ext/vla17.C
new file mode 100644
index 00000000000..431167cb48e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/vla17.C
@@ -0,0 +1,15 @@
+// PR c++/69487
+// { dg-do run }
+// { dg-options -Wno-vla }
+
+int size = 6;
+
+int main()
+{
+ char buffer[size] = "";
+ for (int i = 0; i != size; ++i)
+ {
+ if (buffer[i] != 0)
+ __builtin_abort();
+ }
+}