Avoid issuing a bogus warning when the source of strncpy is bound by a constant and is known to be less than the size of the destination.
Testsuite run is underway (not complete yet, but no new errors so far) and a bootstrap is also underway, I'll report status once they're both done. gcc/ * gcc/tree-ssa-strlen.c (handle_builtin_stxncpy): Check bounds of source length if available. gcc/testsuite/ * gcc.dg/builtin-stringop-chk-10.c: New test case. --- gcc/testsuite/gcc.dg/builtin-stringop-chk-10.c | 17 +++++++++++++++++ gcc/tree-ssa-strlen.c | 24 ++++++++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/builtin-stringop-chk-10.c diff --git a/gcc/testsuite/gcc.dg/builtin-stringop-chk-10.c b/gcc/testsuite/gcc.dg/builtin-stringop-chk-10.c new file mode 100644 index 00000000000..13e4bd2f049 --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-stringop-chk-10.c @@ -0,0 +1,17 @@ +/* Bogus -Wstringop-overflow on strncpy when size is based on strlen but is + bound by a constant. + { dg-do compile } + { dg-options "-O2 -Wstringop-overflow" } */ + +char dst[1024]; + +void +f1 (const char *src) +{ + unsigned long limit = 512; + unsigned long len = __builtin_strlen (src); /* { dg-bogus "length computed here" } */ + if (len > limit) + len = limit; + + __builtin_strncpy (dst, src, len); /* { dg-bogus "specified bound depends on the length of the source argument" } */ +} diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c index 72f6a17cd32..49a31a551f5 100644 --- a/gcc/tree-ssa-strlen.c +++ b/gcc/tree-ssa-strlen.c @@ -2125,6 +2125,30 @@ handle_builtin_stxncpy (built_in_function, gimple_stmt_iterator *gsi) return; } + /* When LEN is MIN_EXPR of strlen and a constant, then the copy is bound by + that constant. If the destination size is also constant then compare with + it to avoid a bogus warning. */ + if (TREE_CODE (len) == SSA_NAME) + { + gimple *def_stmt = SSA_NAME_DEF_STMT (len); + + if (is_gimple_assign (def_stmt) + && gimple_assign_rhs_code (def_stmt) == MIN_EXPR) + { + /* RHS1 is the strlen, so check if RHS2 and DSTSIZE are constant. */ + tree rhs2 = gimple_assign_rhs2 (def_stmt); + tree dstsize = compute_objsize (dst, 1); + + if (TREE_CODE (rhs2) == INTEGER_CST + && TREE_CODE (dstsize) == INTEGER_CST + && int_cst_value (rhs2) < int_cst_value (dstsize)) + { + gimple_set_no_warning (stmt, true); + return; + } + } + } + /* Retrieve the strinfo data for the string S that LEN was computed from as some function F of strlen (S) (i.e., LEN need not be equal to strlen(S)). */ -- 2.14.3