diff mbox series

[committed] check for a DECL or EXPRESSION before using its location (PR 97175)

Message ID 7b4a2978-dc95-4659-5d5e-439dc86f153f@gmail.com
State New
Headers show
Series [committed] check for a DECL or EXPRESSION before using its location (PR 97175) | expand

Commit Message

Martin Sebor Sept. 23, 2020, 9:42 p.m. UTC
Using DECL_SOURCE_LOCATION() with a tree node that's not a DECL
isn't a good idea, and neither is using EXPR_LOCATION() with
a node that is a DECL.  Both trigger an ICE when presented with
a node they don't expect.  Until a TREE_LOCATION() that's safe
to use with either is introduced, the attached patch does
the obligatory dance to extract a location from either kind
of node in an ICE-proof way.  I have committed it in r11-3409
after bootstrapping and regtesting in on x86_64-linux.

Martin
diff mbox series

Patch

Handle DECLs and EXPRESSIONs consistently (PR middle-end/97175).

gcc/ChangeLog:

	PR middle-end/97175
	* builtins.c (maybe_warn_for_bound): Handle both DECLs and EXPRESSIONs
	in pad->dst.ref, same is pad->src.ref.

gcc/testsuite/ChangeLog:

	PR middle-end/97175
	* gcc.dg/Wstringop-overflow-44.c: New test.

diff --git a/gcc/builtins.c b/gcc/builtins.c
index 45efc1c3992..cac842fd4a3 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -3480,8 +3480,14 @@  maybe_warn_for_bound (int opt, location_t loc, tree exp, tree func,
   if (warned)
     {
       if (pad && pad->dst.ref)
-	inform (DECL_SOURCE_LOCATION (pad->dst.ref),
-		"destination object declared here");
+	{
+	  if (DECL_P (pad->dst.ref))
+	    inform (DECL_SOURCE_LOCATION (pad->dst.ref),
+		    "destination object declared here");
+	  else if (EXPR_HAS_LOCATION (pad->dst.ref))
+	    inform (EXPR_LOCATION (pad->dst.ref),
+		    "destination object allocated here");
+	}
       TREE_NO_WARNING (exp) = true;
     }
 
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-44.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-44.c
new file mode 100644
index 00000000000..9e292a9b7f9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-44.c
@@ -0,0 +1,129 @@ 
+/* PR middle-end/97175 - ICE on an excessive strncpy bound
+   { dg-do compile }
+   { dg-options "-O -Wall" } */
+
+int n;
+
+char *d;
+
+void sink (void*);
+
+/* Exercise calls with a destination of unknown size.  */
+
+void f0 (const void *s)
+{
+  if (n > 0) return;
+  __builtin_memcpy (d, s, n);       // eliminated
+}
+
+void f1 (const void *s)
+{
+  if (n > 0) return;
+  __builtin_memmove (d, s, n);      // eliminated
+}
+
+void f2 (void)
+{
+  if (n > 0) return;
+  __builtin_memset (d, 0, n);       // eliminated
+}
+
+void f3 (const char *s)
+{
+  if (n > 0) return;
+  __builtin_strncpy (d, s, n);      // can be eliminated but isn't
+}
+
+void f4 (const char *s)
+{
+  if (n > 0) return;
+  *d = 0;
+  __builtin_strncat (d, s, n);      // can be eliminated but isn't
+}
+
+
+/* Exercise the same calls but with a declared destination object.  */
+
+void g0 (const void *s)
+{
+  if (n > 0) return;
+  char a[1];
+  __builtin_memcpy (a, s, n);       // eliminated
+  sink (a);
+}
+
+void g1 (const void *s)
+{
+  if (n > 0) return;
+  char a[1];
+  __builtin_memmove (a, s, n);      // eliminated
+  sink (a);
+}
+
+void g2 (void)
+{
+  if (n > 0) return;
+  char a[1];
+  __builtin_memset (a, 0, n);       // eliminated
+  sink (a);
+}
+
+void g3 (const char *s)
+{
+  if (n > 0) return;
+  char a[1];
+  __builtin_strncpy (a, s, n);      // can be eliminated but isn't
+  sink (a);
+}
+
+void g4 (const char *s)
+{
+  if (n > 0) return;
+  char a[1];
+  *a = 0;
+  __builtin_strncat (a, s, n);      // can be eliminated but isn't
+  sink (a);
+}
+
+
+void h0 (const void *s)
+{
+  if (n > 0) return;
+  d = __builtin_malloc (1);
+  __builtin_memcpy (d, s, n);       // eliminated
+}
+
+void h1 (const void *s)
+{
+  if (n > 0) return;
+  d = __builtin_malloc (1);
+  __builtin_memmove (d, s, n);      // eliminated
+}
+
+void h2 (void)
+{
+  if (n > 0) return;
+  d = __builtin_malloc (1);
+  __builtin_memset (d, 0, n);       // eliminated
+}
+
+void h3 (const char *s)
+{
+  if (n > 0) return;
+  d = __builtin_malloc (1);
+  __builtin_strncpy (d, s, n);      // can be eliminated but isn't
+}
+
+void h4 (const char *s)
+{
+  if (n > 0) return;
+  d = __builtin_malloc (1);
+  *d = 0;
+  __builtin_strncat (d, s, n);      // can be eliminated but isn't
+}
+
+/* The calls above that aren't eliminated trigger
+     warning: specified size between INT_MAX and SIZE_MAX exceed maximum
+              object size PTRDIFF_MAX
+  { dg-prune-output "-Wstringop-overflow" }
+  { dg-prune-output "-Wstringop-overread" } */