aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog11
-rw-r--r--gcc/builtins.c23
-rw-r--r--gcc/gimple-ssa-warn-restrict.c93
-rw-r--r--gcc/gimple.h14
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.dg/Wstringop-overflow-5.c58
-rw-r--r--gcc/testsuite/gcc.dg/Wstringop-overflow-6.c59
-rw-r--r--gcc/tree-ssa-strlen.c7
8 files changed, 223 insertions, 48 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index b1b3299..aa0247d 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,16 @@
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
* fold-const.c (operand_equal_p): Handle SAVE_EXPR.
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 8707e0c..6b3e6b2 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -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;
diff --git a/gcc/gimple-ssa-warn-restrict.c b/gcc/gimple-ssa-warn-restrict.c
index cc50fba..7dedb24 100644
--- a/gcc/gimple-ssa-warn-restrict.c
+++ b/gcc/gimple-ssa-warn-restrict.c
@@ -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);
diff --git a/gcc/gimple.h b/gcc/gimple.h
index 00a9f20..ab095f6 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -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 *
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index f009f2b..9ab1822 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -5,6 +5,12 @@
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
* gcc.dg/Wstringop-truncation-3.c: New test.
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-5.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-5.c
new file mode 100644
index 0000000..4abce01
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-5.c
@@ -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
index 0000000..9284a87
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-6.c
@@ -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=]" } */
+}
diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c
index cc1f5f4..8794cc2 100644
--- a/gcc/tree-ssa-strlen.c
+++ b/gcc/tree-ssa-strlen.c
@@ -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);