mirror of git://gcc.gnu.org/git/gcc.git
PR tree-optimization/85700 - Spurious -Wstringop-truncation warning with strncat
gcc/ChangeLog: PR tree-optimization/85700 * gimple-fold.c (gimple_fold_builtin_strncat): Adjust comment. * tree-ssa-strlen.c (is_strlen_related_p): Handle integer subtraction. (maybe_diag_stxncpy_trunc): Distinguish strncat from strncpy. gcc/testsuite/ChangeLog: PR tree-optimization/85700 * gcc.dg/Wstringop-truncation-4.c: New test. From-SVN: r262110
This commit is contained in:
parent
2bcd87a7b5
commit
eec5f615cb
|
|
@ -1,3 +1,10 @@
|
|||
2018-06-25 Martin Sebor <msebor@redhat.com>
|
||||
|
||||
PR tree-optimization/85700
|
||||
* gimple-fold.c (gimple_fold_builtin_strncat): Adjust comment.
|
||||
* tree-ssa-strlen.c (is_strlen_related_p): Handle integer subtraction.
|
||||
(maybe_diag_stxncpy_trunc): Distinguish strncat from strncpy.
|
||||
|
||||
2018-06-25 Martin Sebor <msebor@redhat.com>
|
||||
|
||||
* doc/extend.texi (Zero-length arrays): Update and clarify.
|
||||
|
|
|
|||
|
|
@ -2051,10 +2051,12 @@ gimple_fold_builtin_strncat (gimple_stmt_iterator *gsi)
|
|||
if (!nowarn && cmpsrc == 0)
|
||||
{
|
||||
tree fndecl = gimple_call_fndecl (stmt);
|
||||
|
||||
/* To avoid certain truncation the specified bound should also
|
||||
not be equal to (or less than) the length of the source. */
|
||||
location_t loc = gimple_location (stmt);
|
||||
|
||||
/* To avoid possible overflow the specified bound should also
|
||||
not be equal to the length of the source, even when the size
|
||||
of the destination is unknown (it's not an uncommon mistake
|
||||
to specify as the bound to strncpy the length of the source). */
|
||||
if (warning_at (loc, OPT_Wstringop_overflow_,
|
||||
"%G%qD specified bound %E equals source length",
|
||||
stmt, fndecl, len))
|
||||
|
|
|
|||
|
|
@ -1,3 +1,8 @@
|
|||
2018-06-25 Martin Sebor <msebor@redhat.com>
|
||||
|
||||
PR tree-optimization/85700
|
||||
* gcc.dg/Wstringop-truncation-4.c: New test.
|
||||
|
||||
2018-06-25 Fritz Reese <fritzoreese@gmail.com>
|
||||
|
||||
PR fortran/82972
|
||||
|
|
|
|||
|
|
@ -0,0 +1,63 @@
|
|||
/* PR tree-optimization/85700 - Spurious -Wstringop-truncation warning
|
||||
with strncat
|
||||
{ dg-do compile }
|
||||
{ dg-options "-O2 -Wno-stringop-overflow -Wstringop-truncation -ftrack-macro-expansion=0" } */
|
||||
|
||||
#define NOIPA __attribute__ ((noipa))
|
||||
#define strncat __builtin_strncat
|
||||
#define strlen __builtin_strlen
|
||||
|
||||
extern char a4[4], b4[4], ax[];
|
||||
|
||||
NOIPA void cat_a4_s1_1 (void)
|
||||
{
|
||||
/* There is no truncation here but since the bound of 1 equals
|
||||
the length of the source string it's likely a mistake that
|
||||
could cause overflow so it's diagnosed by -Wstringop-overflow */
|
||||
strncat (a4, "1", 1);
|
||||
}
|
||||
|
||||
NOIPA void cat_a4_s1_2 (void)
|
||||
{
|
||||
strncat (a4, "1", 2);
|
||||
}
|
||||
|
||||
NOIPA void cat_a4_s1_3 (void)
|
||||
{
|
||||
strncat (a4, "1", 3);
|
||||
}
|
||||
|
||||
NOIPA void cat_a4_s1_4 (void)
|
||||
{
|
||||
/* There is no truncation here but since the bound of 1 equals
|
||||
the length of the source string it's likely a mistake that
|
||||
could cause overflow so it's diagnosed by -Wstringop-overflow */
|
||||
strncat (a4, "1", 4);
|
||||
}
|
||||
|
||||
NOIPA void cat_a4_s1_5 (void)
|
||||
{
|
||||
/* A bound in excess of the destination size is diagnosed by
|
||||
-Wstringop-overflow. */
|
||||
strncat (a4, "1", 5);
|
||||
}
|
||||
|
||||
NOIPA void cat_a4_s1_dlen (void)
|
||||
{
|
||||
strncat (a4, "1", sizeof a4 - strlen (a4) - 1);
|
||||
}
|
||||
|
||||
NOIPA void cat_a4_s2_dlen (void)
|
||||
{
|
||||
strncat (a4, "12", sizeof a4 - strlen (a4) - 1); /* { dg-bogus "\\\[-Wstringop-truncation]" } */
|
||||
}
|
||||
|
||||
NOIPA void cat_a4_b4_dlen (void)
|
||||
{
|
||||
strncat (a4, b4, sizeof a4 - strlen (a4) - 1); /* { dg-bogus "\\\[-Wstringop-truncation]" } */
|
||||
}
|
||||
|
||||
NOIPA void cat_ax_b4_dlen (void)
|
||||
{
|
||||
strncat (ax, b4, 32 - strlen (ax) - 1); /* { dg-bogus "\\\[-Wstringop-truncation]" } */
|
||||
}
|
||||
|
|
@ -2014,6 +2014,12 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt)
|
|||
|
||||
gcall *call = as_a <gcall *> (stmt);
|
||||
|
||||
/* Set to true for strncat whose bound is derived from the length
|
||||
of the destination (the expected usage pattern). */
|
||||
bool cat_dstlen_bounded = false;
|
||||
if (DECL_FUNCTION_CODE (func) == BUILT_IN_STRNCAT)
|
||||
cat_dstlen_bounded = is_strlen_related_p (dst, cnt);
|
||||
|
||||
if (lenrange[0] == cntrange[1] && cntrange[0] == cntrange[1])
|
||||
return warning_n (callloc, OPT_Wstringop_truncation,
|
||||
cntrange[0].to_uhwi (),
|
||||
|
|
@ -2024,46 +2030,50 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt)
|
|||
"copying %E bytes from a string of the same "
|
||||
"length",
|
||||
call, func, cnt);
|
||||
else if (wi::geu_p (lenrange[0], cntrange[1]))
|
||||
else if (!cat_dstlen_bounded)
|
||||
{
|
||||
/* The shortest string is longer than the upper bound of
|
||||
the count so the truncation is certain. */
|
||||
if (cntrange[0] == cntrange[1])
|
||||
return warning_n (callloc, OPT_Wstringop_truncation,
|
||||
cntrange[0].to_uhwi (),
|
||||
"%G%qD output truncated copying %E byte "
|
||||
"from a string of length %wu",
|
||||
"%G%qD output truncated copying %E bytes "
|
||||
"from a string of length %wu",
|
||||
call, func, cnt, lenrange[0].to_uhwi ());
|
||||
if (wi::geu_p (lenrange[0], cntrange[1]))
|
||||
{
|
||||
/* The shortest string is longer than the upper bound of
|
||||
the count so the truncation is certain. */
|
||||
if (cntrange[0] == cntrange[1])
|
||||
return warning_n (callloc, OPT_Wstringop_truncation,
|
||||
cntrange[0].to_uhwi (),
|
||||
"%G%qD output truncated copying %E byte "
|
||||
"from a string of length %wu",
|
||||
"%G%qD output truncated copying %E bytes "
|
||||
"from a string of length %wu",
|
||||
call, func, cnt, lenrange[0].to_uhwi ());
|
||||
|
||||
return warning_at (callloc, OPT_Wstringop_truncation,
|
||||
"%G%qD output truncated copying between %wu "
|
||||
"and %wu bytes from a string of length %wu",
|
||||
call, func, cntrange[0].to_uhwi (),
|
||||
cntrange[1].to_uhwi (), lenrange[0].to_uhwi ());
|
||||
}
|
||||
else if (wi::geu_p (lenrange[1], cntrange[1]))
|
||||
{
|
||||
/* The longest string is longer than the upper bound of
|
||||
the count so the truncation is possible. */
|
||||
if (cntrange[0] == cntrange[1])
|
||||
return warning_n (callloc, OPT_Wstringop_truncation,
|
||||
cntrange[0].to_uhwi (),
|
||||
"%G%qD output may be truncated copying %E "
|
||||
"byte from a string of length %wu",
|
||||
"%G%qD output may be truncated copying %E "
|
||||
"bytes from a string of length %wu",
|
||||
call, func, cnt, lenrange[1].to_uhwi ());
|
||||
return warning_at (callloc, OPT_Wstringop_truncation,
|
||||
"%G%qD output truncated copying between %wu "
|
||||
"and %wu bytes from a string of length %wu",
|
||||
call, func, cntrange[0].to_uhwi (),
|
||||
cntrange[1].to_uhwi (), lenrange[0].to_uhwi ());
|
||||
}
|
||||
else if (wi::geu_p (lenrange[1], cntrange[1]))
|
||||
{
|
||||
/* The longest string is longer than the upper bound of
|
||||
the count so the truncation is possible. */
|
||||
if (cntrange[0] == cntrange[1])
|
||||
return warning_n (callloc, OPT_Wstringop_truncation,
|
||||
cntrange[0].to_uhwi (),
|
||||
"%G%qD output may be truncated copying %E "
|
||||
"byte from a string of length %wu",
|
||||
"%G%qD output may be truncated copying %E "
|
||||
"bytes from a string of length %wu",
|
||||
call, func, cnt, lenrange[1].to_uhwi ());
|
||||
|
||||
return warning_at (callloc, OPT_Wstringop_truncation,
|
||||
"%G%qD output may be truncated copying between %wu "
|
||||
"and %wu bytes from a string of length %wu",
|
||||
call, func, cntrange[0].to_uhwi (),
|
||||
cntrange[1].to_uhwi (), lenrange[1].to_uhwi ());
|
||||
return warning_at (callloc, OPT_Wstringop_truncation,
|
||||
"%G%qD output may be truncated copying between "
|
||||
"%wu and %wu bytes from a string of length %wu",
|
||||
call, func, cntrange[0].to_uhwi (),
|
||||
cntrange[1].to_uhwi (), lenrange[1].to_uhwi ());
|
||||
}
|
||||
}
|
||||
|
||||
if (cntrange[0] != cntrange[1]
|
||||
if (!cat_dstlen_bounded
|
||||
&& cntrange[0] != cntrange[1]
|
||||
&& wi::leu_p (cntrange[0], lenrange[0])
|
||||
&& wi::leu_p (cntrange[1], lenrange[0] + 1))
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue