PR tree-optimization/85259 - Missing -Wstringop-overflow= since r256683

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
This commit is contained in:
Martin Sebor 2018-06-12 18:05:13 +00:00 committed by Martin Sebor
parent 47feeb3652
commit e3329a782f
8 changed files with 222 additions and 47 deletions

View 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> 2018-06-12 Martin Sebor <msebor@redhat.com>
PR c/85931 PR c/85931

View File

@ -3326,10 +3326,29 @@ compute_objsize (tree dest, int ostype)
{ {
/* compute_builtin_object_size fails for addresses with /* compute_builtin_object_size fails for addresses with
non-constant offsets. Try to determine the range of 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. */ size. */
tree off = gimple_assign_rhs2 (stmt); 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))) && INTEGRAL_TYPE_P (TREE_TYPE (off)))
{ {
wide_int min, max; wide_int min, max;

View 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); loc = expansion_point_location_if_in_system_header (loc);
tree type;
char rangestr[2][64]; char rangestr[2][64];
if (ooboff[0] == ooboff[1] if (ooboff[0] == ooboff[1]
|| (ooboff[0] != ref.offrange[0] || (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[0].to_shwi (),
(long long) ooboff[1].to_shwi ()); (long long) ooboff[1].to_shwi ());
bool warned = false;
if (oobref == error_mark_node) if (oobref == error_mark_node)
{ {
if (ref.sizrange[0] == ref.sizrange[1]) 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[0].to_shwi (),
(long long) ref.sizrange[1].to_shwi ()); (long long) ref.sizrange[1].to_shwi ());
tree type;
if (DECL_P (ref.base) if (DECL_P (ref.base)
&& TREE_CODE (type = TREE_TYPE (ref.base)) == ARRAY_TYPE) && 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 " "%G%qD pointer overflow between offset %s "
"and size %s accessing array %qD with type %qT", "and size %s accessing array %qD with type %qT",
call, func, rangestr[0], rangestr[1], ref.base, type)) 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 else
warning_at (loc, OPT_Warray_bounds, warned = warning_at (loc, OPT_Warray_bounds,
"%G%qD pointer overflow between offset %s " "%G%qD pointer overflow between offset %s "
"and size %s", "and size %s",
call, func, rangestr[0], rangestr[1]); call, func, rangestr[0], rangestr[1]);
} }
else else
warning_at (loc, OPT_Warray_bounds, warned = warning_at (loc, OPT_Warray_bounds,
"%G%qD pointer overflow between offset %s " "%G%qD pointer overflow between offset %s "
"and size %s", "and size %s",
call, func, rangestr[0], rangestr[1]); call, func, rangestr[0], rangestr[1]);
} }
else if (oobref == ref.base) 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"), "of object %qD with type %qT"),
call, func, rangestr[0], call, func, rangestr[0],
ref.base, TREE_TYPE (ref.base))) 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) else if (ref.basesize < maxobjsize)
warning_at (loc, OPT_Warray_bounds, warned = warning_at (loc, OPT_Warray_bounds,
form form
? G_("%G%qD forming offset %s is out of the bounds " ? G_("%G%qD forming offset %s is out "
"[0, %wu]") "of the bounds [0, %wu]")
: G_("%G%qD offset %s is out of the bounds [0, %wu]"), : G_("%G%qD offset %s is out "
call, func, rangestr[0], ref.basesize.to_uhwi ()); "of the bounds [0, %wu]"),
call, func, rangestr[0], ref.basesize.to_uhwi ());
else else
warning_at (loc, OPT_Warray_bounds, warned = warning_at (loc, OPT_Warray_bounds,
form form
? G_("%G%qD forming offset %s is out of bounds") ? G_("%G%qD forming offset %s is out of bounds")
: G_("%G%qD offset %s is out of bounds"), : G_("%G%qD offset %s is out of bounds"),
call, func, rangestr[0]); call, func, rangestr[0]);
} }
else if (TREE_CODE (ref.ref) == MEM_REF) 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 = TREE_TYPE (type);
type = TYPE_MAIN_VARIANT (type); type = TYPE_MAIN_VARIANT (type);
warning_at (loc, OPT_Warray_bounds, warned = warning_at (loc, OPT_Warray_bounds,
"%G%qD offset %s from the object at %qE is out " "%G%qD offset %s from the object at %qE is out "
"of the bounds of %qT", "of the bounds of %qT",
call, func, rangestr[0], ref.base, type); call, func, rangestr[0], ref.base, type);
} }
else else
{ {
type = TYPE_MAIN_VARIANT (TREE_TYPE (ref.ref)); tree type = TYPE_MAIN_VARIANT (TREE_TYPE (ref.ref));
warning_at (loc, OPT_Warray_bounds, warned = warning_at (loc, OPT_Warray_bounds,
"%G%qD offset %s from the object at %qE is out " "%G%qD offset %s from the object at %qE is out "
"of the bounds of referenced subobject %qD with type %qT " "of the bounds of referenced subobject %qD with "
"at offset %wu", "type %qT at offset %wu",
call, func, rangestr[0], ref.base, TREE_OPERAND (ref.ref, 1), call, func, rangestr[0], ref.base,
type, ref.refoff.to_uhwi ()); TREE_OPERAND (ref.ref, 1), type,
ref.refoff.to_uhwi ());
} }
return true; return warned;
} }
/* Check a CALL statement for restrict-violations and issue warnings /* 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, check_bounds_or_overlap (gcall *call, tree dst, tree src, tree dstsize,
tree srcsize, bool bounds_only /* = false */) tree srcsize, bool bounds_only /* = false */)
{ {
location_t loc = gimple_location (call); location_t loc = gimple_nonartificial_location (call);
if (tree block = gimple_block (call))
if (location_t *pbloc = block_nonartificial_location (block))
loc = *pbloc;
loc = expansion_point_location_if_in_system_header (loc); loc = expansion_point_location_if_in_system_header (loc);
tree func = gimple_call_fndecl (call); tree func = gimple_call_fndecl (call);

View 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. */ /* Return the file name of the location of STMT. */
static inline const char * static inline const char *

View File

@ -3,6 +3,12 @@
PR fortran/44491 PR fortran/44491
* gfortran.dg/pr44491.f90: New testcase * 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> 2018-06-12 Martin Sebor <msebor@redhat.com>
PR c/85931 PR c/85931

View File

@ -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=]" } */
}

View File

@ -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=]" } */
}

View 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); tree func = gimple_call_fndecl (stmt);
if (lenrange[0] != 0 || !wi::neg_p (lenrange[1])) 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)). */ to strlen(S)). */
strinfo *silen = get_strinfo (pss->first); 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); tree func = gimple_call_fndecl (stmt);