PR tree-optimization/85259 - Missing -Wstringop-overflow= since r256683
authorMartin Sebor <msebor@redhat.com>
Tue, 12 Jun 2018 18:05:13 +0000 (18:05 +0000)
committerMartin Sebor <msebor@gcc.gnu.org>
Tue, 12 Jun 2018 18:05:13 +0000 (12:05 -0600)
gcc/ChangeLog:

PR tree-optimization/85259
* builtins.c (compute_objsize): Handle constant offsets.
* gimple-ssa-warn-restrict.c (maybe_diag_offset_bounds): Return
true iff a warning has been issued.
* gimple.h (gimple_nonartificial_location): New function.
* tree-ssa-strlen.c (maybe_diag_stxncpy_trunc): Call
gimple_nonartificial_location and handle -Wno-system-headers.
(handle_builtin_stxncpy): Same.

gcc/testsuite/ChangeLog:

PR tree-optimization/85259
* gcc.dg/Wstringop-overflow-5.c: New test.
* gcc.dg/Wstringop-overflow-6.c: New test.

From-SVN: r261518

gcc/ChangeLog
gcc/builtins.c
gcc/gimple-ssa-warn-restrict.c
gcc/gimple.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/Wstringop-overflow-5.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/Wstringop-overflow-6.c [new file with mode: 0644]
gcc/tree-ssa-strlen.c

index b1b32998fde38c0853524259538cadde0a5d70c5..aa0247df98f7039187c82329cf1d724f5385ec34 100644 (file)
@@ -1,3 +1,14 @@
+2018-06-12  Martin Sebor  <msebor@redhat.com>
+
+       PR tree-optimization/85259
+       * builtins.c (compute_objsize): Handle constant offsets.
+       * gimple-ssa-warn-restrict.c (maybe_diag_offset_bounds): Return
+       true iff a warning has been issued.
+       * gimple.h (gimple_nonartificial_location): New function.
+       * tree-ssa-strlen.c (maybe_diag_stxncpy_trunc): Call
+       gimple_nonartificial_location and handle -Wno-system-headers.
+       (handle_builtin_stxncpy): Same.
+
 2018-06-12  Martin Sebor  <msebor@redhat.com>
 
        PR c/85931
index 8707e0cfbc31aba24ee0803ba3d0fae428711ed3..6b3e6b2ea961f49e366a34ec10502ab5af316623 100644 (file)
@@ -3326,10 +3326,29 @@ compute_objsize (tree dest, int ostype)
        {
          /* compute_builtin_object_size fails for addresses with
             non-constant offsets.  Try to determine the range of
-            such an offset here and use it to adjus the constant
+            such an offset here and use it to adjust the constant
             size.  */
          tree off = gimple_assign_rhs2 (stmt);
-         if (TREE_CODE (off) == SSA_NAME
+         if (TREE_CODE (off) == INTEGER_CST)
+           {
+             if (tree size = compute_objsize (dest, ostype))
+               {
+                 wide_int wioff = wi::to_wide (off);
+                 wide_int wisiz = wi::to_wide (size);
+
+                 /* Ignore negative offsets for now.  For others,
+                    use the lower bound as the most optimistic
+                    estimate of the (remaining) size.  */
+                 if (wi::sign_mask (wioff))
+                   ;
+                 else if (wi::ltu_p (wioff, wisiz))
+                   return wide_int_to_tree (TREE_TYPE (size),
+                                            wi::sub (wisiz, wioff));
+                 else
+                   return size_zero_node;
+               }
+           }
+         else if (TREE_CODE (off) == SSA_NAME
              && INTEGRAL_TYPE_P (TREE_TYPE (off)))
            {
              wide_int min, max;
index cc50fba21d7b51325724b37f96465476053bece0..7dedb24fb9d8c4d27b0680410ea92af42c9a436f 100644 (file)
@@ -1593,8 +1593,6 @@ maybe_diag_offset_bounds (location_t loc, gcall *call, tree func, int strict,
 
   loc = expansion_point_location_if_in_system_header (loc);
 
-  tree type;
-
   char rangestr[2][64];
   if (ooboff[0] == ooboff[1]
       || (ooboff[0] != ref.offrange[0]
@@ -1605,6 +1603,8 @@ maybe_diag_offset_bounds (location_t loc, gcall *call, tree func, int strict,
             (long long) ooboff[0].to_shwi (),
             (long long) ooboff[1].to_shwi ());
 
+  bool warned = false;
+
   if (oobref == error_mark_node)
     {
       if (ref.sizrange[0] == ref.sizrange[1])
@@ -1614,6 +1614,8 @@ maybe_diag_offset_bounds (location_t loc, gcall *call, tree func, int strict,
                 (long long) ref.sizrange[0].to_shwi (),
                 (long long) ref.sizrange[1].to_shwi ());
 
+      tree type;
+
       if (DECL_P (ref.base)
          && TREE_CODE (type = TREE_TYPE (ref.base)) == ARRAY_TYPE)
        {
@@ -1621,19 +1623,22 @@ maybe_diag_offset_bounds (location_t loc, gcall *call, tree func, int strict,
                          "%G%qD pointer overflow between offset %s "
                          "and size %s accessing array %qD with type %qT",
                          call, func, rangestr[0], rangestr[1], ref.base, type))
-           inform (DECL_SOURCE_LOCATION (ref.base),
-                   "array %qD declared here", ref.base);
+           {
+             inform (DECL_SOURCE_LOCATION (ref.base),
+                     "array %qD declared here", ref.base);
+             warned = true;
+           }
          else
-           warning_at (loc, OPT_Warray_bounds,
-                       "%G%qD pointer overflow between offset %s "
-                       "and size %s",
-                       call, func, rangestr[0], rangestr[1]);
+           warned = warning_at (loc, OPT_Warray_bounds,
+                                "%G%qD pointer overflow between offset %s "
+                                "and size %s",
+                                call, func, rangestr[0], rangestr[1]);
        }
       else
-       warning_at (loc, OPT_Warray_bounds,
-                   "%G%qD pointer overflow between offset %s "
-                   "and size %s",
-                   call, func, rangestr[0], rangestr[1]);
+       warned = warning_at (loc, OPT_Warray_bounds,
+                            "%G%qD pointer overflow between offset %s "
+                            "and size %s",
+                            call, func, rangestr[0], rangestr[1]);
     }
   else if (oobref == ref.base)
     {
@@ -1664,22 +1669,26 @@ maybe_diag_offset_bounds (location_t loc, gcall *call, tree func, int strict,
                                  "of object %qD with type %qT"),
                             call, func, rangestr[0],
                             ref.base, TREE_TYPE (ref.base)))
-           inform (DECL_SOURCE_LOCATION (ref.base),
-                   "%qD declared here", ref.base);
+           {
+             inform (DECL_SOURCE_LOCATION (ref.base),
+                     "%qD declared here", ref.base);
+             warned = true;
+           }
        }
       else if (ref.basesize < maxobjsize)
-       warning_at (loc, OPT_Warray_bounds,
-                   form
-                   ? G_("%G%qD forming offset %s is out of the bounds "
-                        "[0, %wu]")
-                   : G_("%G%qD offset %s is out of the bounds [0, %wu]"),
-                   call, func, rangestr[0], ref.basesize.to_uhwi ());
+       warned = warning_at (loc, OPT_Warray_bounds,
+                            form
+                            ? G_("%G%qD forming offset %s is out "
+                                 "of the bounds [0, %wu]")
+                            : G_("%G%qD offset %s is out "
+                                 "of the bounds [0, %wu]"),
+                            call, func, rangestr[0], ref.basesize.to_uhwi ());
       else
-       warning_at (loc, OPT_Warray_bounds,
-                   form
-                   ? G_("%G%qD forming offset %s is out of bounds")
-                   : G_("%G%qD offset %s is out of bounds"),
-                   call, func, rangestr[0]);
+       warned = warning_at (loc, OPT_Warray_bounds,
+                            form
+                            ? G_("%G%qD forming offset %s is out of bounds")
+                            : G_("%G%qD offset %s is out of bounds"),
+                            call, func, rangestr[0]);
     }
   else if (TREE_CODE (ref.ref) == MEM_REF)
     {
@@ -1688,24 +1697,25 @@ maybe_diag_offset_bounds (location_t loc, gcall *call, tree func, int strict,
        type = TREE_TYPE (type);
       type = TYPE_MAIN_VARIANT (type);
 
-      warning_at (loc, OPT_Warray_bounds,
-                 "%G%qD offset %s from the object at %qE is out "
-                 "of the bounds of %qT",
-                 call, func, rangestr[0], ref.base, type);
+      warned = warning_at (loc, OPT_Warray_bounds,
+                          "%G%qD offset %s from the object at %qE is out "
+                          "of the bounds of %qT",
+                          call, func, rangestr[0], ref.base, type);
     }
   else
     {
-      type = TYPE_MAIN_VARIANT (TREE_TYPE (ref.ref));
-
-      warning_at (loc, OPT_Warray_bounds,
-               "%G%qD offset %s from the object at %qE is out "
-               "of the bounds of referenced subobject %qD with type %qT "
-               "at offset %wu",
-               call, func, rangestr[0], ref.base, TREE_OPERAND (ref.ref, 1),
-               type, ref.refoff.to_uhwi ());
+      tree type = TYPE_MAIN_VARIANT (TREE_TYPE (ref.ref));
+
+      warned = warning_at (loc, OPT_Warray_bounds,
+                          "%G%qD offset %s from the object at %qE is out "
+                          "of the bounds of referenced subobject %qD with "
+                          "type %qT at offset %wu",
+                          call, func, rangestr[0], ref.base,
+                          TREE_OPERAND (ref.ref, 1), type,
+                          ref.refoff.to_uhwi ());
     }
 
-  return true;
+  return warned;
 }
 
 /* Check a CALL statement for restrict-violations and issue warnings
@@ -1815,12 +1825,7 @@ bool
 check_bounds_or_overlap (gcall *call, tree dst, tree src, tree dstsize,
                         tree srcsize, bool bounds_only /* = false */)
 {
-  location_t loc = gimple_location (call);
-
-  if (tree block = gimple_block (call))
-    if (location_t *pbloc = block_nonartificial_location (block))
-      loc = *pbloc;
-
+  location_t loc = gimple_nonartificial_location (call);
   loc = expansion_point_location_if_in_system_header (loc);
 
   tree func = gimple_call_fndecl (call);
index 00a9f207bdf1d5e89d1f6a3225cc667a10fde63b..ab095f63908940c46031995ec647f8c1a0373e9b 100644 (file)
@@ -1796,6 +1796,20 @@ gimple_has_location (const gimple *g)
 }
 
 
+/* Return non-artificial location information for statement G.  */
+
+static inline location_t
+gimple_nonartificial_location (const gimple *g)
+{
+  location_t *ploc = NULL;
+
+  if (tree block = gimple_block (g))
+    ploc = block_nonartificial_location (block);
+
+  return ploc ? *ploc : gimple_location (g);
+}
+
+
 /* Return the file name of the location of STMT.  */
 
 static inline const char *
index f009f2b476898eb41e1dc579964d999387af397e..9ab1822be6efd077b211ceee4910c1650afd3ef3 100644 (file)
@@ -3,6 +3,12 @@
        PR fortran/44491
        * gfortran.dg/pr44491.f90: New testcase
 
+2018-06-12  Martin Sebor  <msebor@redhat.com>
+
+       PR tree-optimization/85259
+       * gcc.dg/Wstringop-overflow-5.c: New test.
+       * gcc.dg/Wstringop-overflow-6.c: New test.
+
 2018-06-12  Martin Sebor  <msebor@redhat.com>
 
        PR c/85931
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-5.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-5.c
new file mode 100644 (file)
index 0000000..4abce01
--- /dev/null
@@ -0,0 +1,58 @@
+/* PR tree-optimization/85259 - Missing -Wstringop-overflow= since r256683
+   { dg-do compile }
+   { dg-options "-O2 -Wstringop-overflow" } */
+
+extern char* strcpy (char*, const char*);
+extern char* strcat (char*, const char*);
+
+char a1[1];
+char a2[2];
+char a3[3];
+char a4[4];
+char a5[5];
+char a6[6];
+char a7[7];
+char a8[8];
+
+/* Verify that at least one instance of -Wstringop-overflow is issued
+   for each pair of strcpy/strcat calls.  */
+
+void test_strcpy_strcat_1 (void)
+{
+  strcpy (a1, "1"), strcat (a1, "2");   /* { dg-warning "\\\[-Wstringop-overflow=]" } */
+}
+
+void test_strcpy_strcat_2 (void)
+{
+  strcpy (a2, "12"), strcat (a2, "3");   /* { dg-warning "\\\[-Wstringop-overflow=]" } */
+}
+
+void test_strcpy_strcat_3 (void)
+{
+  strcpy (a3, "123"), strcat (a3, "4");   /* { dg-warning "\\\[-Wstringop-overflow=]" } */
+}
+
+void test_strcpy_strcat_4 (void)
+{
+  strcpy (a4, "1234"), strcat (a4, "5");   /* { dg-warning "\\\[-Wstringop-overflow=]" } */
+}
+
+void test_strcpy_strcat_5 (void)
+{
+  strcpy (a5, "12345"), strcat (a5, "6");   /* { dg-warning "\\\[-Wstringop-overflow=]" } */
+}
+
+void test_strcpy_strcat_6 (void)
+{
+  strcpy (a6, "123456"), strcat (a6, "7");   /* { dg-warning "\\\[-Wstringop-overflow=]" } */
+}
+
+void test_strcpy_strcat_7 (void)
+{
+  strcpy (a7, "1234567"), strcat (a7, "8");   /* { dg-warning "\\\[-Wstringop-overflow=]" } */
+}
+
+void test_strcpy_strcat_8 (void)
+{
+  strcpy (a8, "12345678"), strcat (a8, "9");   /* { dg-warning "\\\[-Wstringop-overflow=]" } */
+}
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-6.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-6.c
new file mode 100644 (file)
index 0000000..9284a87
--- /dev/null
@@ -0,0 +1,59 @@
+/* PR tree-optimization/85259 - Missing -Wstringop-overflow= since r256683
+   { dg-do compile }
+   { dg-options "-O2 -Wstringop-overflow -ftrack-macro-expansion=0" } */
+
+#define bos1(p) __builtin_object_size (p, 1)
+#define strcat(d, s) __builtin___strcat_chk (d, s, bos1 (d))
+#define strcpy(d, s) __builtin___strcpy_chk (d, s, bos1 (d))
+
+char a1[1];
+char a2[2];
+char a3[3];
+char a4[4];
+char a5[5];
+char a6[6];
+char a7[7];
+char a8[8];
+
+/* Verify that at least one instance of -Wstringop-overflow is issued
+   for each pair of strcpy/strcat calls.  */
+
+void test_strcpy_strcat_1 (void)
+{
+  strcpy (a1, "1"), strcat (a1, "2");   /* { dg-warning "\\\[-Wstringop-overflow=]" } */
+}
+
+void test_strcpy_strcat_2 (void)
+{
+  strcpy (a2, "12"), strcat (a2, "3");   /* { dg-warning "\\\[-Wstringop-overflow=]" "bug 86121" { xfail *-*-* } } */
+}
+
+void test_strcpy_strcat_3 (void)
+{
+  strcpy (a3, "123"), strcat (a3, "4");   /* { dg-warning "\\\[-Wstringop-overflow=]" } */
+}
+
+void test_strcpy_strcat_4 (void)
+{
+  strcpy (a4, "1234"), strcat (a4, "5");   /* { dg-warning "\\\[-Wstringop-overflow=]" } */
+}
+
+void test_strcpy_strcat_5 (void)
+{
+  strcpy (a5, "12345"), strcat (a5, "6");   /* { dg-warning "\\\[-Wstringop-overflow=]" } */
+}
+
+void test_strcpy_strcat_6 (void)
+{
+  strcpy (a6, "123456"), strcat (a6, "7");   /* { dg-warning "\\\[-Wstringop-overflow=]" } */
+}
+
+void test_strcpy_strcat_7 (void)
+{
+  strcpy (a7, "1234567"), strcat (a7, "8");   /* { dg-warning "\\\[-Wstringop-overflow=]" } */
+}
+
+void test_strcpy_strcat_8 (void)
+{
+  strcpy (a8, "12345678"), strcat (a8, "9");   /* { dg-warning "\\\[-Wstringop-overflow=]" } */
+}
index cc1f5f48e3411142c30549e175c4e84638904832..8794cc240c8b5cb2beb124981f3a35ff9633ff72 100644 (file)
@@ -1886,7 +1886,9 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt)
        }
     }
 
-  location_t callloc = gimple_location (stmt);
+  location_t callloc = gimple_nonartificial_location (stmt);
+  callloc = expansion_point_location_if_in_system_header (callloc);
+
   tree func = gimple_call_fndecl (stmt);
 
   if (lenrange[0] != 0 || !wi::neg_p (lenrange[1]))
@@ -2069,7 +2071,8 @@ handle_builtin_stxncpy (built_in_function, gimple_stmt_iterator *gsi)
      to strlen(S)).  */
   strinfo *silen = get_strinfo (pss->first);
 
-  location_t callloc = gimple_location (stmt);
+  location_t callloc = gimple_nonartificial_location (stmt);
+  callloc = expansion_point_location_if_in_system_header (callloc);
 
   tree func = gimple_call_fndecl (stmt);