public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* C++ PATCH for sanitizer/79993 (ICE with VLA initialized from string constant)
@ 2017-04-03 20:53 Jason Merrill
  0 siblings, 0 replies; only message in thread
From: Jason Merrill @ 2017-04-03 20:53 UTC (permalink / raw)
  To: gcc-patches List

[-- Attachment #1: Type: text/plain, Size: 257 bytes --]

In this testcase we were giving a STRING_CST a VLA type, which is
nonsensical and leads to the asan crash.  After fixing that the
initialization semantics are still wrong, so this patch corrects that
as well.

Tested x86_64-pc-linux-gnu, applying to trunk.

[-- Attachment #2: 79993.diff --]
[-- Type: text/plain, Size: 5978 bytes --]

commit 0ada9f9492a4184e638bd8796db5fb68532aae51
Author: Jason Merrill <jason@redhat.com>
Date:   Fri Mar 24 16:37:24 2017 -0400

            PR c++/79993 - ICE with VLA initialization
    
            * 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.

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;

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2017-04-03 20:53 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-04-03 20:53 C++ PATCH for sanitizer/79993 (ICE with VLA initialized from string constant) Jason Merrill

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).