Handle DECLs and EXPRESSIONs consistently (PR middle-end/97175).
authorMartin Sebor <msebor@redhat.com>
Wed, 23 Sep 2020 21:04:32 +0000 (15:04 -0600)
committerMartin Sebor <msebor@redhat.com>
Wed, 23 Sep 2020 21:10:20 +0000 (15:10 -0600)
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.

gcc/builtins.c
gcc/testsuite/gcc.dg/Wstringop-overflow-44.c [new file with mode: 0644]

index 45efc1c3992a1b99b25da6be13b4073947c9bcd2..cac842fd4a39c4a3c1817ae76edee64e0e7ad417 100644 (file)
@@ -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 (file)
index 0000000..9e292a9
--- /dev/null
@@ -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" } */