aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/decl.c
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2016-04-13 23:26:41 +0000
committerMartin Sebor <msebor@gcc.gnu.org>2016-04-13 17:26:41 -0600
commit342fac9537c6a75e65fe62943ba84b81bddede3f (patch)
tree1d55385c5ee07d32a08d9279dcb595632d96e73c /gcc/cp/decl.c
parent2ecc0c837bf2ac1309f41d30b7b30595331a6eb6 (diff)
downloadgcc-342fac9537c6a75e65fe62943ba84b81bddede3f.zip
gcc-342fac9537c6a75e65fe62943ba84b81bddede3f.tar.gz
gcc-342fac9537c6a75e65fe62943ba84b81bddede3f.tar.bz2
PR c++/69517 - [5/6 regression] SEGV on a VLA with excess initializer elements
PR c++/69517 - [5/6 regression] SEGV on a VLA with excess initializer elements PR c++/70019 - VLA size overflow not detected PR c++/70588 - SIGBUS on a VLA larger than SIZE_MAX / 2 gcc/testsuite/ChangeLog: 2016-04-13 Martin Sebor <msebor@redhat.com> PR c++/69517 PR c++/70019 PR c++/70588 * c-c++-common/ubsan/vla-1.c (main): Catch exceptions. * g++.dg/cpp1y/vla11.C: New test. * g++.dg/cpp1y/vla12.C: New test. * g++.dg/cpp1y/vla13.C: New test. * g++.dg/cpp1y/vla14.C: New test. * g++.dg/cpp1y/vla3.C: Restore deleted test. * gcc/testsuite/g++.dg/init/array24.C: Fully brace VLA initializer. * g++.dg/ubsan/vla-1.C: Disable exceptions. gcc/cp/ChangeLog: 2016-04-13 Martin Sebor <msebor@redhat.com> PR c++/69517 PR c++/70019 PR c++/70588 * cp-tree.h (throw_bad_array_length, build_vla_check): Declare new functions. * decl.c (check_initializer, cp_finish_decl): Call them. (reshape_init_r): Reject incompletely braced intializer-lists for VLAs. * init.c (throw_bad_array_length, build_vla_check) (build_vla_size_check, build_vla_init_check): Define new functions. * typeck2.c (split_nonconstant_init_1): Use variably_modified_type_p() to detect a VLA. (store_init_value): Same. gcc/doc/ChangeLog: 2016-04-13 Martin Sebor <msebor@redhat.com> PR c++/69517 PR c++/70019 PR c++/70588 * extend.texi (Variable Length): Document C++ specifics. libstdc++-v3/ChangeLog: 2016-04-13 Martin Sebor <msebor@redhat.com> PR c++/69517 * testsuite/25_algorithms/rotate/moveable2.cc: Make sure VLA upper bound is positive. From-SVN: r234966
Diffstat (limited to 'gcc/cp/decl.c')
-rw-r--r--gcc/cp/decl.c45
1 files changed, 44 insertions, 1 deletions
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 7099199..42e853f 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -5896,6 +5896,16 @@ reshape_init_r (tree type, reshape_iter *d, bool first_initializer_p,
}
}
+ if (variably_modified_type_p (type, NULL_TREE))
+ {
+ /* Require VLAs to have their initializers fully braced
+ to avoid initializing the wrong elements. */
+ if (complain & tf_error)
+ error ("missing braces around initializer for a variable length "
+ "array %qT", type);
+ return error_mark_node;
+ }
+
warning (OPT_Wmissing_braces, "missing braces around initializer for %qT",
type);
}
@@ -6048,6 +6058,10 @@ check_initializer (tree decl, tree init, int flags, vec<tree, va_gc> **cleanups)
/* There is no way to make a variable-sized class type in GNU C++. */
gcc_assert (TREE_CONSTANT (TYPE_SIZE (type)));
+ /* Initializer exression used to check invalid VLA bounds and excess
+ initializer elements. */
+ tree saved_init_for_vla_check = NULL_TREE;
+
if (init && BRACE_ENCLOSED_INITIALIZER_P (init))
{
int init_len = vec_safe_length (CONSTRUCTOR_ELTS (init));
@@ -6199,7 +6213,9 @@ check_initializer (tree decl, tree init, int flags, vec<tree, va_gc> **cleanups)
&& PAREN_STRING_LITERAL_P (DECL_INITIAL (decl)))
warning (0, "array %qD initialized by parenthesized string literal %qE",
decl, DECL_INITIAL (decl));
- init = NULL;
+
+ saved_init_for_vla_check = init;
+ init = NULL_TREE;
}
}
else
@@ -6213,6 +6229,33 @@ check_initializer (tree decl, tree init, int flags, vec<tree, va_gc> **cleanups)
check_for_uninitialized_const_var (decl);
}
+ if (TREE_CODE (type) == ARRAY_TYPE
+ && variably_modified_type_p (type, NULL_TREE)
+ && !processing_template_decl)
+ {
+ /* Statically check for overflow in VLA bounds and build
+ an expression that checks at runtime whether the VLA
+ is erroneous due to invalid (runtime) bounds.
+ Another expression to check for excess initializers
+ is built in build_vec_init. */
+ tree check = build_vla_check (TREE_TYPE (decl), saved_init_for_vla_check);
+
+ if (flag_exceptions && current_function_decl
+ /* Avoid instrumenting constexpr functions for now.
+ Those must be checked statically, and the (non-
+ constexpr) dynamic instrumentation would cause
+ them to be rejected. See c++/70507. */
+ && !DECL_DECLARED_CONSTEXPR_P (current_function_decl))
+ {
+ /* Use the runtime check only when exceptions are enabled.
+ Otherwise let bad things happen... */
+ check = build3 (COND_EXPR, void_type_node, check,
+ throw_bad_array_length (), void_node);
+
+ finish_expr_stmt (check);
+ }
+ }
+
if (init && init != error_mark_node)
init_code = build2 (INIT_EXPR, type, decl, init);