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.

From-SVN: r246662
This commit is contained in:
Jason Merrill 2017-04-03 17:15:36 -04:00 committed by Jason Merrill
parent b0dfb235e8
commit 5a68fae797
5 changed files with 108 additions and 28 deletions

View File

@ -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

View File

@ -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)

View File

@ -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;

View File

@ -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();
}

View File

@ -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();
}
}