public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Cleanup strcpy/stpcpy no nul warning code
@ 2018-09-16 20:05 Bernd Edlinger
  2018-09-17 17:35 ` Jeff Law
                   ` (2 more replies)
  0 siblings, 3 replies; 16+ messages in thread
From: Bernd Edlinger @ 2018-09-16 20:05 UTC (permalink / raw)
  To: gcc-patches, Jeff Law, Richard Biener, Martin Sebor

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

Hi,

this is a cleanup of the recently added strlen/strcpy/stpcpy
no nul warning code.

Most importantly it moves the SSA_NAME handling from
unterminated_array to string_constant, thereby fixing
another round of xfails in the strlen and stpcpy test cases.

I need to say that the fix for bug 86622 is relying in
type info on the pointer which is probably not safe in
GIMPLE in the light of the recent discussion.

I had to add two further exceptions, which should
be safe in general: that is a pointer arithmentic on a string
literal is okay, and arithmetic on a string constant
that is exactly the size of the whole DECL, cannot
access an adjacent member.


Bootstrapped and reg-tested on x86_64-pc-linux-gnu.
Is it OK for trunk?


Thanks
Bernd.

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: patch-cleanup-no-nul.diff --]
[-- Type: text/x-patch; name="patch-cleanup-no-nul.diff", Size: 12368 bytes --]

gcc:
2018-09-16  Bernd Edlinger  <bernd.edlinger@hotmail.de>

	* builtins.h (unterminated_array): Remove prototype.
        * builtins.c (unterminated_array): Simplify.  Make static.
        (expand_builtin_strcpy_args): Don't use TREE_NO_WARNING here.
	(expand_builtin_stpcpy_1): Remove warn_string_no_nul without effect.
	* expr.c (string_constant): Handle SSA_NAME.  Add more exceptions
	where pointer arithmetic is safe.
	* gimple-fold.c (get_range_strlen): Handle nonstr like in c_strlen.
	(get_max_strlen): Remove the unnecessary mynonstr handling.
	(gimple_fold_builtin_strcpy): Simplify.
	(gimple_fold_builtin_stpcpy): Simplify.
	(gimple_fold_builtin_sprintf): Remove NO_WARNING propagation
	without effect.
	(gimple_fold_builtin_strlen): Simplify.

testsuite:
2018-09-16  Bernd Edlinger  <bernd.edlinger@hotmail.de>

	* gcc.dg/warn-stpcpy-no-nul.c: Remove xfails.
	* gcc.dg/warn-strlen-no-nul.c: Remove xfails.

Index: gcc/builtins.c
===================================================================
--- gcc/builtins.c	(revision 264342)
+++ gcc/builtins.c	(working copy)
@@ -567,31 +567,12 @@ warn_string_no_nul (location_t loc, const char *fn
    the declaration of the object of which the array is a member or
    element.  Otherwise return null.  */
 
-tree
+static tree
 unterminated_array (tree exp)
 {
-  if (TREE_CODE (exp) == SSA_NAME)
-    {
-      gimple *stmt = SSA_NAME_DEF_STMT (exp);
-      if (!is_gimple_assign (stmt))
-	return NULL_TREE;
-
-      tree rhs1 = gimple_assign_rhs1 (stmt);
-      tree_code code = gimple_assign_rhs_code (stmt);
-      if (code == ADDR_EXPR
-	  && TREE_CODE (TREE_OPERAND (rhs1, 0)) == ARRAY_REF)
-	rhs1 = rhs1;
-      else if (code != POINTER_PLUS_EXPR)
-	return NULL_TREE;
-
-      exp = rhs1;
-    }
-
   tree nonstr = NULL;
-  if (c_strlen (exp, 1, &nonstr, 1) == NULL && nonstr)
-    return nonstr;
-
-  return NULL_TREE;
+  c_strlen (exp, 1, &nonstr);
+  return nonstr;
 }
 
 /* Compute the length of a null-terminated character string or wide
@@ -3936,8 +3917,7 @@ expand_builtin_strcpy_args (tree exp, tree dest, t
   if (tree nonstr = unterminated_array (src))
     {
       /* NONSTR refers to the non-nul terminated constant array.  */
-      if (!TREE_NO_WARNING (exp))
-	warn_string_no_nul (EXPR_LOCATION (exp), "strcpy", src, nonstr);
+      warn_string_no_nul (EXPR_LOCATION (exp), "strcpy", src, nonstr);
       return NULL_RTX;
     }
 
@@ -3984,14 +3964,10 @@ expand_builtin_stpcpy_1 (tree exp, rtx target, mac
 	 compile-time, not an expression containing a string.  This is
 	 because the latter will potentially produce pessimized code
 	 when used to produce the return value.  */
-      tree nonstr = NULL_TREE;
       if (!c_getstr (src, NULL)
-	  || !(len = c_strlen (src, 0, &nonstr, 1)))
+	  || !(len = c_strlen (src, 0)))
 	return expand_movstr (dst, src, target, /*endp=*/2);
 
-      if (nonstr && !TREE_NO_WARNING (exp))
-	warn_string_no_nul (EXPR_LOCATION (exp), "stpcpy", src, nonstr);
-
       lenp1 = size_binop_loc (loc, PLUS_EXPR, len, ssize_int (1));
       ret = expand_builtin_mempcpy_args (dst, src, lenp1,
 					 target, exp, /*endp=*/2);
Index: gcc/builtins.h
===================================================================
--- gcc/builtins.h	(revision 264342)
+++ gcc/builtins.h	(working copy)
@@ -104,7 +104,6 @@ extern internal_fn associated_internal_fn (tree);
 extern internal_fn replacement_internal_fn (gcall *);
 
 extern void warn_string_no_nul (location_t, const char *, tree, tree);
-extern tree unterminated_array (tree);
 extern tree max_object_size ();
 
 #endif /* GCC_BUILTINS_H */
Index: gcc/expr.c
===================================================================
--- gcc/expr.c	(revision 264342)
+++ gcc/expr.c	(working copy)
@@ -11372,7 +11372,10 @@ string_constant (tree arg, tree *ptr_offset, tree
 	  /* Avoid pointers to arrays (see bug 86622).  */
 	  if (POINTER_TYPE_P (TREE_TYPE (arg))
 	      && TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) == ARRAY_TYPE
-	      && TREE_CODE (TREE_OPERAND (arg0, 0)) == ARRAY_REF)
+	      && !(decl && !*decl)
+	      && !(decl && tree_fits_uhwi_p (DECL_SIZE_UNIT (*decl))
+		   && mem_size && tree_fits_uhwi_p (*mem_size)
+		   && tree_int_cst_equal (*mem_size, DECL_SIZE_UNIT (*decl))))
 	    return NULL_TREE;
 
 	  tree type = TREE_TYPE (arg1);
@@ -11381,6 +11384,38 @@ string_constant (tree arg, tree *ptr_offset, tree
 	}
       return NULL_TREE;
     }
+  else if (TREE_CODE (arg) == SSA_NAME)
+    {
+      gimple *stmt = SSA_NAME_DEF_STMT (arg);
+      if (!is_gimple_assign (stmt))
+	return NULL_TREE;
+
+      tree rhs1 = gimple_assign_rhs1 (stmt);
+      tree_code code = gimple_assign_rhs_code (stmt);
+      if (code == ADDR_EXPR)
+	return string_constant (rhs1, ptr_offset, mem_size, decl);
+      else if (code != POINTER_PLUS_EXPR)
+	return NULL_TREE;
+
+      tree offset;
+      if (tree str = string_constant (rhs1, &offset, mem_size, decl))
+	{
+	  /* Avoid pointers to arrays (see bug 86622).  */
+	  if (POINTER_TYPE_P (TREE_TYPE (rhs1))
+	      && TREE_CODE (TREE_TYPE (TREE_TYPE (rhs1))) == ARRAY_TYPE
+	      && !(decl && !*decl)
+	      && !(decl && tree_fits_uhwi_p (DECL_SIZE_UNIT (*decl))
+		   && mem_size && tree_fits_uhwi_p (*mem_size)
+		   && tree_int_cst_equal (*mem_size, DECL_SIZE_UNIT (*decl))))
+	    return NULL_TREE;
+
+	  tree rhs2 = gimple_assign_rhs2 (stmt);
+	  tree type = TREE_TYPE (rhs2);
+	  *ptr_offset = fold_build2 (PLUS_EXPR, type, offset, rhs2);
+	  return str;
+	}
+      return NULL_TREE;
+    }
   else if (DECL_P (arg))
     array = arg;
   else
Index: gcc/gimple-fold.c
===================================================================
--- gcc/gimple-fold.c	(revision 264342)
+++ gcc/gimple-fold.c	(working copy)
@@ -1573,11 +1573,6 @@ get_range_strlen (tree arg, tree minmaxlen[2], uns
   minmaxlen[0] = NULL_TREE;
   minmaxlen[1] = NULL_TREE;
 
-  tree nonstrbuf;
-  if (!nonstr)
-    nonstr = &nonstrbuf;
-  *nonstr = NULL_TREE;
-
   bool flexarray = false;
   if (!get_range_strlen (arg, minmaxlen, &visited, 1, strict ? 1 : 2,
 			 &flexarray, eltsize, nonstr))
@@ -1607,24 +1602,12 @@ get_maxval_strlen (tree arg, int type, tree *nonst
   tree len[2] = { NULL_TREE, NULL_TREE };
 
   bool dummy;
-  /* Set to non-null if ARG refers to an untermianted array.  */
-  tree mynonstr = NULL_TREE;
-  if (!get_range_strlen (arg, len, &visited, type, 0, &dummy, 1, &mynonstr))
+  if (!get_range_strlen (arg, len, &visited, type, 0, &dummy, 1, nonstr))
     len[1] = NULL_TREE;
   if (visited)
     BITMAP_FREE (visited);
 
-  if (nonstr)
-    {
-      /* For callers prepared to handle unterminated arrays set
-	 *NONSTR to point to the declaration of the array and return
-	 the maximum length/size. */
-      *nonstr = mynonstr;
-      return len[1];
-    }
-
-  /* Fail if the constant array isn't nul-terminated.  */
-  return mynonstr ? NULL_TREE : len[1];
+  return len[1];
 }
 
 
@@ -1672,13 +1655,7 @@ gimple_fold_builtin_strcpy (gimple_stmt_iterator *
   tree len = get_maxval_strlen (src, 0, &nonstr);
 
   if (nonstr)
-    {
-      /* Avoid folding calls with unterminated arrays.  */
-      if (!gimple_no_warning_p (stmt))
-	warn_string_no_nul (loc, "strcpy", src, nonstr);
-      gimple_set_no_warning (stmt, true);
-      return false;
-    }
+    warn_string_no_nul (loc, "strcpy", src, nonstr);
 
   if (!len)
     return false;
@@ -2813,24 +2790,15 @@ gimple_fold_builtin_stpcpy (gimple_stmt_iterator *
 
   /* Set to non-null if ARG refers to an unterminated array.  */
   tree nonstr = NULL;
-  tree len = c_strlen (src, 1, &nonstr, 1);
+  tree len = c_strlen (src, 1, &nonstr);
+
+  if (nonstr)
+    warn_string_no_nul (loc, "stpcpy", src, nonstr);
+
   if (!len
       || TREE_CODE (len) != INTEGER_CST)
-    {
-      nonstr = unterminated_array (src);
-      if (!nonstr)
-	return false;
-    }
+    return false;
 
-  if (nonstr)
-    {
-      /* Avoid folding calls with unterminated arrays.  */
-      if (!gimple_no_warning_p (stmt))
-	warn_string_no_nul (loc, "stpcpy", src, nonstr);
-      gimple_set_no_warning (stmt, true);
-      return false;
-    }
-
   if (optimize_function_for_size_p (cfun)
       /* If length is zero it's small enough.  */
       && !integer_zerop (len))
@@ -3093,11 +3061,6 @@ gimple_fold_builtin_sprintf (gimple_stmt_iterator
       gimple_seq stmts = NULL;
       gimple *repl = gimple_build_call (fn, 2, dest, fmt);
 
-      /* Propagate the NO_WARNING bit to avoid issuing the same
-	 warning more than once.  */
-      if (gimple_no_warning_p (stmt))
-	gimple_set_no_warning (repl, true);
-
       gimple_seq_add_stmt_without_update (&stmts, repl);
       if (gimple_call_lhs (stmt))
 	{
@@ -3147,11 +3110,6 @@ gimple_fold_builtin_sprintf (gimple_stmt_iterator
       gimple_seq stmts = NULL;
       gimple *repl = gimple_build_call (fn, 2, dest, orig);
 
-      /* Propagate the NO_WARNING bit to avoid issuing the same
-	 warning more than once.  */
-      if (gimple_no_warning_p (stmt))
-	gimple_set_no_warning (repl, true);
-
       gimple_seq_add_stmt_without_update (&stmts, repl);
       if (gimple_call_lhs (stmt))
 	{
@@ -3582,10 +3540,8 @@ gimple_fold_builtin_strlen (gimple_stmt_iterator *
   wide_int minlen;
   wide_int maxlen;
 
-  /* Set to non-null if ARG refers to an unterminated array.  */
-  tree nonstr;
   tree lenrange[2];
-  if (!get_range_strlen (arg, lenrange, 1, true, &nonstr)
+  if (!get_range_strlen (arg, lenrange, 1, true)
       && lenrange[0] && TREE_CODE (lenrange[0]) == INTEGER_CST
       && lenrange[1] && TREE_CODE (lenrange[1]) == INTEGER_CST)
     {
Index: gcc/testsuite/gcc.dg/warn-stpcpy-no-nul.c
===================================================================
--- gcc/testsuite/gcc.dg/warn-stpcpy-no-nul.c	(revision 264342)
+++ gcc/testsuite/gcc.dg/warn-stpcpy-no-nul.c	(working copy)
@@ -71,13 +71,13 @@ void test_two_dim_array (char *d)
   T (&b[3][1] + 1);     /* { dg-warning "nul" }  */
   T (&b[3][v0]);        /* { dg-warning "nul" }  */
   T (&b[3][1] + v0);    /* { dg-warning "nul" }  */
-  T (&b[3][v0] + v1);   /* { dg-warning "nul" "bug ???" { xfail *-*-* } }  */
+  T (&b[3][v0] + v1);   /* { dg-warning "nul" }  */
 
   T (&b[i3][i1]);       /* { dg-warning "nul" }  */
   T (&b[i3][i1] + i1);  /* { dg-warning "nul" }  */
   T (&b[i3][v0]);       /* { dg-warning "nul" }  */
   T (&b[i3][i1] + v0);  /* { dg-warning "nul" }  */
-  T (&b[i3][v0] + v1);  /* { dg-warning "nul" "bug ???" { xfail *-*-* } }  */
+  T (&b[i3][v0] + v1);  /* { dg-warning "nul" }  */
 
   T (v0 ? "" : b[0]);
   T (v0 ? "" : b[1]);
Index: gcc/testsuite/gcc.dg/warn-strlen-no-nul.c
===================================================================
--- gcc/testsuite/gcc.dg/warn-strlen-no-nul.c	(revision 264342)
+++ gcc/testsuite/gcc.dg/warn-strlen-no-nul.c	(working copy)
@@ -71,9 +71,9 @@ T (&b[3][v0] + v1);     /* { dg-warning "nul" }  *
 T (&b[i3][i1]);         /* { dg-warning "nul" }  */
 T (&b[i3][i1] + 1);     /* { dg-warning "nul" }  */
 T (&b[i3][i1] + i1);    /* { dg-warning "nul" }  */
-T (&b[i3][v0]);         /* { dg-warning "nul" "pr86919" { xfail *-*-* } }  */
-T (&b[i3][i1] + v0);    /* { dg-warning "nul" "pr86919" { xfail *-*-* } }  */
-T (&b[i3][v0] + v1);    /* { dg-warning "nul" "pr86919" { xfail *-*-* } }  */
+T (&b[i3][v0]);         /* { dg-warning "nul" }  */
+T (&b[i3][i1] + v0);    /* { dg-warning "nul" }  */
+T (&b[i3][v0] + v1);    /* { dg-warning "nul" }  */
 
 T (v0 ? "" : b[0]);
 T (v0 ? "" : b[1]);
@@ -152,10 +152,10 @@ T (&s.b[1] + v0);     /* { dg-warning "nul" }  */
 
 T (&s.b[i0]);         /* { dg-warning "nul" }  */
 T (&s.b[i0] + i1);    /* { dg-warning "nul" }  */
-T (&s.b[i0] + v0);    /* { dg-warning "nul" "pr86919" { xfail *-*-* } }  */
+T (&s.b[i0] + v0);    /* { dg-warning "nul" }  */
 T (&s.b[i1]);         /* { dg-warning "nul" }  */
 T (&s.b[i1] + i1);    /* { dg-warning "nul" }  */
-T (&s.b[i1] + v0);    /* { dg-warning "nul" "pr86919" { xfail *-*-* } }  */
+T (&s.b[i1] + v0);    /* { dg-warning "nul" }  */
 
 struct B { struct A a[2]; };
 

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2018-09-25 22:21 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-09-16 20:05 [PATCH] Cleanup strcpy/stpcpy no nul warning code Bernd Edlinger
2018-09-17 17:35 ` Jeff Law
2018-09-17 18:32   ` Bernd Edlinger
2018-09-17 18:35     ` Jeff Law
2018-09-17 19:18       ` Bernd Edlinger
2018-09-17 23:01         ` Jeff Law
2018-09-18  5:38         ` Jeff Law
2018-09-18 12:06           ` Bernd Edlinger
2018-09-18 18:55             ` Jeff Law
2018-09-22 18:47               ` Martin Liška
2018-09-23  8:49                 ` Martin Liška
2018-09-23 14:35                 ` Jeff Law
2018-09-24 18:17 ` Jeff Law
2018-09-24 18:19   ` Bernd Edlinger
2018-09-25  3:19     ` Jeff Law
2018-09-25 22:43 ` Jeff Law

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