PR tree-optimization/82646 - bogus -Wstringop-overflow with -D_FORTIFY_SOURCE=2 on...
authorMartin Sebor <msebor@redhat.com>
Wed, 6 Dec 2017 17:59:01 +0000 (17:59 +0000)
committerMartin Sebor <msebor@gcc.gnu.org>
Wed, 6 Dec 2017 17:59:01 +0000 (10:59 -0700)
gcc/ChangeLog:

PR tree-optimization/82646
* builtins.c (maybe_emit_chk_warning): Use size as the bound for
strncpy, not maxlen.

gcc/testsuite/ChangeLog:

PR tree-optimization/82646
* gcc.dg/builtin-stringop-chk-1.c: Adjust.
* gcc.dg/builtin-stringop-chk-9.c: New test.
* g++.dg/ext/strncpy-chk1.C: Adjust.

From-SVN: r255448

gcc/ChangeLog
gcc/builtins.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/ext/strncpy-chk1.C
gcc/testsuite/gcc.dg/builtin-stringop-chk-1.c
gcc/testsuite/gcc.dg/builtin-stringop-chk-9.c [new file with mode: 0644]

index 1615acf8a3f9a843990ff9ab16398331474e72c6..de037da6b02776fadda7f56701de0589e48089f7 100644 (file)
@@ -1,3 +1,9 @@
+2017-12-06  Martin Sebor  <msebor@redhat.com>
+
+       PR tree-optimization/82646
+       * builtins.c (maybe_emit_chk_warning): Use size as the bound for
+       strncpy, not maxlen.
+
 2017-12-06  Martin Sebor  <msebor@redhat.com>
 
        * doc/invoke.texi (-Wstringop-truncation): Mention attribute
index 097e1b7356380a869233d182ed48f00cfd7fc1e3..6b25253950ce390609a8e9fa895bb01a22aa018a 100644 (file)
@@ -9861,6 +9861,8 @@ maybe_emit_chk_warning (tree exp, enum built_in_function fcode)
      (such as __strncat_chk) or null if the operation isn't bounded
      (such as __strcat_chk).  */
   tree maxlen = NULL_TREE;
+  /* The exact size of the access (such as in __strncpy_chk).  */
+  tree size = NULL_TREE;
 
   switch (fcode)
     {
@@ -9888,7 +9890,7 @@ maybe_emit_chk_warning (tree exp, enum built_in_function fcode)
     case BUILT_IN_STRNCPY_CHK:
     case BUILT_IN_STPNCPY_CHK:
       srcstr = CALL_EXPR_ARG (exp, 1);
-      maxlen = CALL_EXPR_ARG (exp, 2);
+      size = CALL_EXPR_ARG (exp, 2);
       objsize = CALL_EXPR_ARG (exp, 3);
       break;
 
@@ -9911,7 +9913,7 @@ maybe_emit_chk_warning (tree exp, enum built_in_function fcode)
     }
 
   check_sizes (OPT_Wstringop_overflow_, exp,
-              /*size=*/NULL_TREE, maxlen, srcstr, objsize);
+              size, maxlen, srcstr, objsize);
 }
 
 /* Emit warning if a buffer overflow is detected at compile time
index c39f3d260c6386664a240592557ca5130c0c88a2..a42348fbb77217f26868d8fdc3c48f942f107370 100644 (file)
@@ -1,3 +1,10 @@
+2017-12-06  Martin Sebor  <msebor@redhat.com>
+
+       PR tree-optimization/82646
+       * gcc.dg/builtin-stringop-chk-1.c: Adjust.
+       * gcc.dg/builtin-stringop-chk-9.c: New test.
+       * g++.dg/ext/strncpy-chk1.C: Adjust.
+
 2017-12-06  Martin Sebor  <msebor@redhat.com>
 
        PR tree-optimization/83075
index b94c3bdb77a74cf6a1c8b2316d98b17d30a6dbf0..8f8822b67b6a976c5c195276c13ad53bc8622417 100644 (file)
@@ -1,4 +1,4 @@
-// PR c++/40502
+// PR c++/40502 - [4.5 Regression] crash in cp_diagnostic_starter
 // { dg-do compile }
 // { dg-options "-O2" }
 // { dg-skip-if "packed attribute missing for struct A" { "epiphany-*-*" } }
@@ -9,7 +9,8 @@ struct B { char z[50]; };
 inline void
 foo (char *dest, const char *__restrict src, __SIZE_TYPE__ n)
 {
-  __builtin___strncpy_chk (dest, src, n, __builtin_object_size (dest, 0));     // { dg-warning "specified bound 36 exceeds destination size 35" }
+  // This triggers a -Wstringop-overflow warning (pruned below).
+  __builtin___strncpy_chk (dest, src, n, __builtin_object_size (dest, 0));
 }
 
 void bar (const char *, int);
@@ -30,3 +31,5 @@ test ()
 {
   baz (0);
 }
+
+// { dg-prune-output "\\\[-Wstringop-overflow=]" }
index 35cc6dc93bb9f955c8056e2938ae2ef894c616b8..10048f32cf0bc980ab2b9e48e7e4d15fe711a0b3 100644 (file)
@@ -36,7 +36,7 @@ test (int arg, ...)
   vx = stpcpy (&buf2[18], "a");
   vx = stpcpy (&buf2[18], "ab"); /* { dg-warning "writing 3" "stpcpy" } */
   strncpy (&buf2[18], "a", 2);
-  strncpy (&buf2[18], "a", 3); /* { dg-warning "specified bound 3 exceeds destination size 2" "strncpy" } */
+  strncpy (&buf2[18], "a", 3); /* { dg-warning "writing 3 bytes into a region of size 2" "strncpy" } */
   strncpy (&buf2[18], "abc", 2);
   strncpy (&buf2[18], "abc", 3); /* { dg-warning "writing 3 " "strncpy" } */
   memset (buf2, '\0', sizeof (buf2));
@@ -93,7 +93,7 @@ void
 test2 (const H h)
 {
   char c;
-  strncpy (&c, str, 3); /* { dg-warning "specified bound 3 exceeds destination size 1" "strncpy" } */
+  strncpy (&c, str, 3); /* { dg-warning "writing 3 bytes into a region of size 1" "strncpy" } */
 
   struct { char b[4]; } x;
   sprintf (x.b, "%s", "ABCD"); /* { dg-warning "writing 5" "sprintf" } */
diff --git a/gcc/testsuite/gcc.dg/builtin-stringop-chk-9.c b/gcc/testsuite/gcc.dg/builtin-stringop-chk-9.c
new file mode 100644 (file)
index 0000000..b5464c2
--- /dev/null
@@ -0,0 +1,150 @@
+/* PR middle-end/82646 - bogus -Wstringop-overflow with -D_FORTIFY_SOURCE=2
+   on strncpy with range to a member array
+   { dg-do compile }
+   { dg-options "-O2 -Wstringop-overflow -ftrack-macro-expansion=0" } */
+
+#define bos(p)   __builtin_object_size (p, 1)
+
+struct S {
+  char a[5];
+  void (*pf)(void);
+};
+
+/* Verify that none of the string function calls below triggers a warning.  */
+
+char* test_stpncpy_const_nowarn (struct S *p)
+{
+  int n = sizeof p->a;
+
+  return __builtin_stpncpy (p->a, "123456", n);
+}
+
+char* test_strncpy_const_nowarn (struct S *p)
+{
+  int n = sizeof p->a;
+
+  return __builtin_strncpy (p->a, "1234567", n);
+}
+
+char* test_stpncpy_chk_const_nowarn (struct S *p)
+{
+  int n = sizeof p->a;
+
+  return __builtin___stpncpy_chk (p->a, "12345678", n, bos (p->a));
+}
+
+char* test_strncpy_chk_const_nowarn (struct S *p)
+{
+  int n = sizeof p->a;
+
+  return __builtin___strncpy_chk (p->a, "123456789", n, bos (p->a));
+}
+
+
+char* test_stpncpy_range_nowarn (struct S *p, int n)
+{
+  if (n < sizeof p->a)
+    n = sizeof p->a;
+
+  return __builtin_stpncpy (p->a, "123456", n);
+}
+
+char* test_strncpy_range_nowarn (struct S *p, int n)
+{
+  if (n < sizeof p->a)
+    n = sizeof p->a;
+
+  return __builtin_strncpy (p->a, "1234567", n);
+}
+
+char* test_stpncpy_chk_range_nowarn (struct S *p, int n)
+{
+  if (n < sizeof p->a)
+    n = sizeof p->a;
+
+  return __builtin___stpncpy_chk (p->a, "12345678", n, bos (p->a));   /* { dg-bogus "\\\[-Wstringop-overflow=]" } */
+}
+
+char* test_strncpy_chk_range_nowarn (struct S *p, int n)
+{
+  if (n < sizeof p->a)
+    n = sizeof p->a;
+
+  return __builtin___strncpy_chk (p->a, "123456789", n, bos (p->a));  /* { dg-bogus "\\\[-Wstringop-overflow=]" } */
+}
+
+
+/* Verify that all of the string function calls below trigger a warning.  */
+
+char* test_stpncpy_const_warn (struct S *p)
+{
+  int n = sizeof p->a;
+
+  ++n;
+
+  return __builtin_stpncpy (p->a, "123456", n);                       /* { dg-warning "\\\[-Wstringop-overflow=]" } */
+}
+
+char* test_strncpy_const_warn (struct S *p)
+{
+  int n = sizeof p->a;
+
+  /* A call to strncpy() with a known string and small bound is folded
+     into memcpy() which defeats the warning in this case since memcpy
+     uses Object Size Type 0, i.e., the largest object that p->a may
+     be a part of.  Use a larger bound to get around this here.  */
+  n += 11;
+
+  return __builtin_strncpy (p->a, "1234567", n);                      /* { dg-warning "\\\[-Wstringop-overflow=]" } */
+}
+
+char* test_stpncpy_chk_const_warn (struct S *p)
+{
+  int n = sizeof p->a;
+
+  ++n;
+
+  return __builtin___stpncpy_chk (p->a, "12345678", n, bos (p->a));   /* { dg-warning "\\\[-Wstringop-overflow=]" } */
+}
+
+char* test_strncpy_chk_const_warn (struct S *p)
+{
+  int n = sizeof p->a;
+
+  ++n;
+
+  return __builtin___strncpy_chk (p->a, "123456789", n, bos (p->a));  /* { dg-warning "\\\[-Wstringop-overflow=]" } */
+}
+
+
+char* test_stpncpy_range_warn (struct S *p, int n)
+{
+  if (n < sizeof p->a + 1)
+    n = sizeof p->a + 1;
+
+  return __builtin_stpncpy (p->a, "123456", n);                       /* { dg-warning "\\\[-Wstringop-overflow=]" } */
+}
+
+char* test_strncpy_range_warn (struct S *p, int n)
+{
+  if (n < sizeof p->a + 1)
+    n = sizeof p->a + 1;
+
+  return __builtin_strncpy (p->a, "1234567", n);                      /* { dg-warning "\\\[-Wstringop-overflow=]" } */
+}
+
+char* test_stpncpy_chk_range_warn (struct S *p, int n)
+{
+  if (n < sizeof p->a + 1)
+    n = sizeof p->a + 1;
+
+  return __builtin___stpncpy_chk (p->a, "12345678", n, bos (p->a));   /* { dg-warning "\\\[-Wstringop-overflow=]" } */
+}
+
+char* test_strncpy_chk_range_warn (struct S *p, int n)
+{
+  if (n < sizeof p->a + 1)
+    n = sizeof p->a + 1;
+
+  return __builtin___strncpy_chk (p->a, "123456789", n, bos (p->a));  /* { dg-warning "\\\[-Wstringop-overflow=]" } */
+}