diff options
author | Martin Sebor <msebor@redhat.com> | 2016-04-13 23:26:41 +0000 |
---|---|---|
committer | Martin Sebor <msebor@gcc.gnu.org> | 2016-04-13 17:26:41 -0600 |
commit | 342fac9537c6a75e65fe62943ba84b81bddede3f (patch) | |
tree | 1d55385c5ee07d32a08d9279dcb595632d96e73c /gcc/cp/decl.c | |
parent | 2ecc0c837bf2ac1309f41d30b7b30595331a6eb6 (diff) | |
download | gcc-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.c | 45 |
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); |