mirror of git://gcc.gnu.org/git/gcc.git
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:
parent
47feeb3652
commit
e3329a782f
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
14
gcc/gimple.h
14
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. */
|
/* Return the file name of the location of STMT. */
|
||||||
|
|
||||||
static inline const char *
|
static inline const char *
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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=]" } */
|
||||||
|
}
|
||||||
|
|
@ -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=]" } */
|
||||||
|
}
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue