aboutsummaryrefslogtreecommitdiff
path: root/gcc/calls.c
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2020-08-28 13:13:28 -0600
committerMartin Sebor <msebor@redhat.com>2020-08-28 13:18:28 -0600
commitd14c547abd484d3540b692bb8048c4a6efe92c8b (patch)
treed3ba650daec2ba98a7b37f8f98ca5ef42c994ae9 /gcc/calls.c
parent26c24398d3615aef43e599f87911c1ecc3bd2841 (diff)
downloadgcc-d14c547abd484d3540b692bb8048c4a6efe92c8b.zip
gcc-d14c547abd484d3540b692bb8048c4a6efe92c8b.tar.gz
gcc-d14c547abd484d3540b692bb8048c4a6efe92c8b.tar.bz2
Add -Wstringop-overread for reading past the end by string functions.
gcc/ChangeLog: * attribs.c (init_attr_rdwr_indices): Use global access_mode. * attribs.h (struct attr_access): Same. * builtins.c (fold_builtin_strlen): Add argument. (compute_objsize): Declare. (get_range): Declare. (check_read_access): New function. (access_ref::access_ref): Define ctor. (warn_string_no_nul): Add arguments. Handle -Wstrintop-overread. (check_nul_terminated_array): Handle source strings of different ranges of sizes. (expand_builtin_strlen): Remove warning code, call check_read_access instead. Declare locals closer to their initialization. (expand_builtin_strnlen): Same. (maybe_warn_for_bound): New function. (warn_for_access): Remove argument. Handle -Wstrintop-overread. (inform_access): Change argument type. (get_size_range): New function. (check_access): Remove unused arguments. Add new arguments. Handle -Wstrintop-overread. Move warning code to helpers and call them. Call check_nul_terminated_array. (check_memop_access): Remove unnecessary and provide additional arguments in calls. (expand_builtin_memchr): Call check_read_access. (expand_builtin_strcat): Remove unnecessary and provide additional arguments in calls. (expand_builtin_strcpy): Same. (expand_builtin_strcpy_args): Same. Avoid testing no-warning bit. (expand_builtin_stpcpy_1): Remove unnecessary and provide additional arguments in calls. (expand_builtin_stpncpy): Same. (check_strncat_sizes): Same. (expand_builtin_strncat): Remove unnecessary and provide additional arguments in calls. Adjust comments. (expand_builtin_strncpy): Remove unnecessary and provide additional arguments in calls. (expand_builtin_memcmp): Remove warning code. Call check_access. (expand_builtin_strcmp): Call check_access instead of check_nul_terminated_array. (expand_builtin_strncmp): Handle -Wstrintop-overread. (expand_builtin_fork_or_exec): Call check_access instead of check_nul_terminated_array. (expand_builtin): Same. (fold_builtin_1): Pass additional argument. (fold_builtin_n): Same. (fold_builtin_strpbrk): Remove calls to check_nul_terminated_array. (expand_builtin_memory_chk): Add comments. (maybe_emit_chk_warning): Remove unnecessary and provide additional arguments in calls. (maybe_emit_sprintf_chk_warning): Same. Adjust comments. * builtins.h (warn_string_no_nul): Add arguments. (struct access_ref): Add member and ctor argument. (struct access_data): Add members and ctor. (check_access): Adjust signature. * calls.c (maybe_warn_nonstring_arg): Return an indication of whether a warning was issued. Issue -Wstrintop-overread instead of -Wstringop-overflow. (append_attrname): Adjust to naming changes. (maybe_warn_rdwr_sizes): Same. Remove unnecessary and provide additional arguments in calls. * calls.h (maybe_warn_nonstring_arg): Return bool. * doc/invoke.texi (-Wstringop-overread): Document new option. * gimple-fold.c (gimple_fold_builtin_strcpy): Provide an additional argument in call. (gimple_fold_builtin_stpcpy): Same. * tree-ssa-uninit.c (maybe_warn_pass_by_reference): Adjust to naming changes. * tree.h (enum access_mode): New type. gcc/c-family/ChangeLog: * c.opt (Wstringop-overread): New option. gcc/testsuite/ChangeLog: * c-c++-common/Warray-bounds-7.c: Adjust expected warnings. * c-c++-common/Wrestrict.c: Remove xfail. * c-c++-common/attr-nonstring-3.c: Adjust text of expected warnings. * c-c++-common/attr-nonstring-6.c: Suppress -Wstringop-overread instead of -Wstringop-overflow. * c-c++-common/attr-nonstring-8.c: Adjust text of expected warnings. * g++.dg/torture/Wsizeof-pointer-memaccess1.C: Also suppress -Wstringop-overread. * g++.dg/torture/Wsizeof-pointer-memaccess2.C: Same. * gcc.dg/Warray-bounds-39.c: Adjust expected warnings. * gcc.dg/Warray-bounds-40.c: Also suppress -Wstringop-overread. * gcc.dg/Warray-bounds-58.c: Remove xfail. Also expect -Wstringop-overread. Adjust text of expected warnings. * gcc.dg/Wsizeof-pointer-memaccess1.c: Also suppress -Wstringop-overread. * gcc.dg/Wstringop-overflow-22.c: Adjust text of expected warnings. * gcc.dg/Wstringop-overflow-33.c: Expect -Wstringop-overread. * gcc.dg/Wstringop-overflow-9.c: Expect -Wstringop-overread. * gcc.dg/attr-nonstring-2.c: Adjust text of expected warnings. * gcc.dg/attr-nonstring-3.c: Same. * gcc.dg/attr-nonstring-4.c: Same. * gcc.dg/attr-nonstring.c: Expect -Wstringop-overread. * gcc.dg/builtin-stringop-chk-5.c: Adjust comment. * gcc.dg/builtin-stringop-chk-8.c: Enable -Wstringop-overread instead of -Wstringop-overflow. * gcc.dg/pr78902.c: Also expect -Wstringop-overread. * gcc.dg/pr79214.c: Adjust text of expected warnings. * gcc.dg/strcmpopt_10.c: Suppress valid -Wno-stringop-overread. * gcc.dg/strlenopt-57.c: Also expect -Wstringop-overread. * gcc.dg/torture/Wsizeof-pointer-memaccess1.c: Also suppress valid -Wno-stringop-overread. * gcc.dg/tree-ssa/builtins-folding-gimple-ub.c: Same. * gcc.dg/uninit-33.c: Same. * gcc.dg/warn-strnlen-no-nul-2.c: Adjust text of expected warning. * gcc.dg/warn-strnlen-no-nul.c: Same. * gcc.target/i386/strcmpopt_6.c: Suppress -Wstringop-overread. * gcc.dg/Wstringop-overread-2.c: New test. * gcc.dg/Wstringop-overread.c: New test.
Diffstat (limited to 'gcc/calls.c')
-rw-r--r--gcc/calls.c79
1 files changed, 47 insertions, 32 deletions
diff --git a/gcc/calls.c b/gcc/calls.c
index a11da66..8ac94db 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -1274,7 +1274,7 @@ get_size_range (tree exp, tree range[2], bool allow_zero /* = false */)
if (range_type == VR_VARYING)
{
if (integral)
- {
+ {
/* Use the full range of the type of the expression when
no value range information is available. */
range[0] = TYPE_MIN_VALUE (exptype);
@@ -1559,22 +1559,23 @@ get_attr_nonstring_decl (tree expr, tree *ref)
return NULL_TREE;
}
-/* Warn about passing a non-string array/pointer to a function that
- expects a nul-terminated string argument. */
+/* Warn about passing a non-string array/pointer to a built-in function
+ that expects a nul-terminated string argument. Returns true if
+ a warning has been issued.*/
-void
+bool
maybe_warn_nonstring_arg (tree fndecl, tree exp)
{
if (!fndecl || !fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
- return;
+ return false;
- if (TREE_NO_WARNING (exp) || !warn_stringop_overflow)
- return;
+ if (TREE_NO_WARNING (exp) || !warn_stringop_overread)
+ return false;
/* Avoid clearly invalid calls (more checking done below). */
unsigned nargs = call_expr_nargs (exp);
if (!nargs)
- return;
+ return false;
/* The bound argument to a bounded string function like strncpy. */
tree bound = NULL_TREE;
@@ -1666,22 +1667,27 @@ maybe_warn_nonstring_arg (tree fndecl, tree exp)
if (bndrng[0])
{
- /* Diagnose excessive bound prior the adjustment below and
+ /* Diagnose excessive bound prior to the adjustment below and
regardless of attribute nonstring. */
tree maxobjsize = max_object_size ();
if (tree_int_cst_lt (maxobjsize, bndrng[0]))
{
+ bool warned = false;
if (tree_int_cst_equal (bndrng[0], bndrng[1]))
- warning_at (loc, OPT_Wstringop_overflow_,
- "%K%qD specified bound %E "
- "exceeds maximum object size %E",
- exp, fndecl, bndrng[0], maxobjsize);
+ warned = warning_at (loc, OPT_Wstringop_overread,
+ "%K%qD specified bound %E "
+ "exceeds maximum object size %E",
+ exp, fndecl, bndrng[0], maxobjsize);
else
- warning_at (loc, OPT_Wstringop_overflow_,
- "%K%qD specified bound [%E, %E] "
- "exceeds maximum object size %E",
- exp, fndecl, bndrng[0], bndrng[1], maxobjsize);
- return;
+ warned = warning_at (loc, OPT_Wstringop_overread,
+ "%K%qD specified bound [%E, %E] "
+ "exceeds maximum object size %E",
+ exp, fndecl, bndrng[0], bndrng[1],
+ maxobjsize);
+ if (warned)
+ TREE_NO_WARNING (exp) = true;
+
+ return warned;
}
}
@@ -1710,6 +1716,7 @@ maybe_warn_nonstring_arg (tree fndecl, tree exp)
}
}
+ bool any_arg_warned = false;
/* Iterate over the built-in function's formal arguments and check
each const char* against the actual argument. If the actual
argument is declared attribute non-string issue a warning unless
@@ -1820,19 +1827,19 @@ maybe_warn_nonstring_arg (tree fndecl, tree exp)
if (wi::ltu_p (asize, wibnd))
{
if (bndrng[0] == bndrng[1])
- warned = warning_at (loc, OPT_Wstringop_overflow_,
+ warned = warning_at (loc, OPT_Wstringop_overread,
"%qD argument %i declared attribute "
"%<nonstring%> is smaller than the specified "
"bound %wu",
fndecl, argno + 1, wibnd.to_uhwi ());
else if (wi::ltu_p (asize, wi::to_offset (bndrng[0])))
- warned = warning_at (loc, OPT_Wstringop_overflow_,
+ warned = warning_at (loc, OPT_Wstringop_overread,
"%qD argument %i declared attribute "
"%<nonstring%> is smaller than "
"the specified bound [%E, %E]",
fndecl, argno + 1, bndrng[0], bndrng[1]);
else
- warned = warning_at (loc, OPT_Wstringop_overflow_,
+ warned = warning_at (loc, OPT_Wstringop_overread,
"%qD argument %i declared attribute "
"%<nonstring%> may be smaller than "
"the specified bound [%E, %E]",
@@ -1842,14 +1849,22 @@ maybe_warn_nonstring_arg (tree fndecl, tree exp)
; /* Avoid warning for calls to strncat() when the bound
is equal to the size of the non-string argument. */
else if (!bound)
- warned = warning_at (loc, OPT_Wstringop_overflow_,
+ warned = warning_at (loc, OPT_Wstringop_overread,
"%qD argument %i declared attribute %<nonstring%>",
fndecl, argno + 1);
if (warned)
- inform (DECL_SOURCE_LOCATION (decl),
- "argument %qD declared here", decl);
+ {
+ inform (DECL_SOURCE_LOCATION (decl),
+ "argument %qD declared here", decl);
+ any_arg_warned = true;
+ }
}
+
+ if (any_arg_warned)
+ TREE_NO_WARNING (exp) = true;
+
+ return any_arg_warned;
}
/* Issue an error if CALL_EXPR was flagged as requiring
@@ -1896,11 +1911,11 @@ append_attrname (const std::pair<int, attr_access> &access,
size_t len = strlen (attrstr);
const char* const atname
- = (access.second.mode == attr_access::read_only
+ = (access.second.mode == access_read_only
? "read_only"
- : (access.second.mode == attr_access::write_only
+ : (access.second.mode == access_write_only
? "write_only"
- : (access.second.mode == attr_access::read_write
+ : (access.second.mode == access_read_write
? "read_write" : "none")));
const char *sep = len ? ", " : "";
@@ -2045,7 +2060,7 @@ maybe_warn_rdwr_sizes (rdwr_map *rwm, tree fndecl, tree fntype, tree exp)
tree objsize = compute_objsize (ptr, 0);
tree srcsize;
- if (access.second.mode == attr_access::write_only)
+ if (access.second.mode == access_write_only)
{
/* For a write-only argument there is no source. */
srcsize = NULL_TREE;
@@ -2055,8 +2070,8 @@ maybe_warn_rdwr_sizes (rdwr_map *rwm, tree fndecl, tree fntype, tree exp)
/* For read-only and read-write attributes also set the source
size. */
srcsize = objsize;
- if (access.second.mode == attr_access::read_only
- || access.second.mode == attr_access::none)
+ if (access.second.mode == access_read_only
+ || access.second.mode == access_none)
{
/* For a read-only attribute there is no destination so
clear OBJSIZE. This emits "reading N bytes" kind of
@@ -2070,8 +2085,8 @@ maybe_warn_rdwr_sizes (rdwr_map *rwm, tree fndecl, tree fntype, tree exp)
iteration so that accesses via different arguments are
diagnosed. */
TREE_NO_WARNING (exp) = false;
- check_access (exp, NULL_TREE, NULL_TREE, size, /*maxread=*/ NULL_TREE,
- srcsize, objsize, access.second.mode != attr_access::none);
+ check_access (exp, size, /*maxread=*/ NULL_TREE, srcsize, objsize,
+ access.second.mode);
if (TREE_NO_WARNING (exp))
/* If check_access issued a warning above, append the relevant