diff options
author | Jason Merrill <jason@redhat.com> | 2017-04-03 17:15:36 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2017-04-03 17:15:36 -0400 |
commit | 5a68fae797b88216b40eb6af8c75dec6e98b983c (patch) | |
tree | 28f3a1d200fa86ca4057f09c132ba79749c015a7 /gcc/cp | |
parent | b0dfb235e837330a5f91ff14092aa76684fee24d (diff) | |
download | gcc-5a68fae797b88216b40eb6af8c75dec6e98b983c.zip gcc-5a68fae797b88216b40eb6af8c75dec6e98b983c.tar.gz gcc-5a68fae797b88216b40eb6af8c75dec6e98b983c.tar.bz2 |
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
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/cp/init.c | 92 | ||||
-rw-r--r-- | gcc/cp/typeck2.c | 7 |
3 files changed, 80 insertions, 28 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 7438479..f3c668b 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 7732795..2015205 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 58a01c9..d1a3930 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; |