diff options
author | Martin Sebor <msebor@redhat.com> | 2018-06-25 20:33:28 +0000 |
---|---|---|
committer | Martin Sebor <msebor@gcc.gnu.org> | 2018-06-25 14:33:28 -0600 |
commit | eec5f615cbad2de5ff10fbaa8c92f68cc5c6be00 (patch) | |
tree | 6d97fc1ae9f1316ba96cf9579500332267bb075a /gcc | |
parent | 2bcd87a7b5bf793a00e99a5d7fdef4277afa7dc6 (diff) | |
download | gcc-eec5f615cbad2de5ff10fbaa8c92f68cc5c6be00.zip gcc-eec5f615cbad2de5ff10fbaa8c92f68cc5c6be00.tar.gz gcc-eec5f615cbad2de5ff10fbaa8c92f68cc5c6be00.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/gimple-fold.c | 8 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/Wstringop-truncation-4.c | 63 | ||||
-rw-r--r-- | gcc/tree-ssa-strlen.c | 84 |
5 files changed, 127 insertions, 40 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 07db821..5334c36 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,12 @@ 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. 2018-06-25 Michael Meissner <meissner@linux.ibm.com> diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index a01bce7..b025935 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -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)) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f2d9caf..4606474 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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 diff --git a/gcc/testsuite/gcc.dg/Wstringop-truncation-4.c b/gcc/testsuite/gcc.dg/Wstringop-truncation-4.c new file mode 100644 index 0000000..f394863 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wstringop-truncation-4.c @@ -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]" } */ +} diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c index 92545b9..2da82a8 100644 --- a/gcc/tree-ssa-strlen.c +++ b/gcc/tree-ssa-strlen.c @@ -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])) - { - /* 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])) + else if (!cat_dstlen_bounded) { - /* 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 ()); + 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 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)) { |