middle-end/104854: Limit strncmp overread warnings
Commit Message
The size argument in strncmp only describe the maximum length to which
to compare two strings and is not an indication of sizes of the two
source strings. Do not warn if it is larger than the two input strings
because it is entirely likely that the size argument is a conservative
maximum to accommodate inputs of different lengths and only a subset is
reachable through the current code path.
gcc/ChangeLog:
middle-end/104854
* gimple-ssa-warn-access.cc
(pass_waccess::warn_zero_sized_strncmp_inputs): New function.
(pass_waccess::check_strncmp): Use it.
gcc/testsuite/ChangeLog:
middle-end/104854
* gcc.dg/Wstringop-overread.c (test_strncmp_array): Don't expect
failures for non-zero sizes.
Signed-off-by: Siddhesh Poyarekar <siddhesh@gotplt.org>
---
x86_64 bootstrap in progress.
gcc/gimple-ssa-warn-access.cc | 39 +++++++++++++----------
gcc/testsuite/gcc.dg/Wstringop-overread.c | 2 +-
2 files changed, 23 insertions(+), 18 deletions(-)
@@ -2137,6 +2137,9 @@ private:
/* Return true if use follows an invalidating statement. */
bool use_after_inval_p (gimple *, gimple *, bool = false);
+ /* Emit an overread warning for zero sized inputs to strncmp. */
+ void warn_zero_sized_strncmp_inputs (gimple *, tree *, access_data *);
+
/* A pointer_query object to store information about pointers and
their targets in. */
pointer_query m_ptr_qry;
@@ -2619,8 +2622,20 @@ pass_waccess::check_stxncpy (gcall *stmt)
data.mode, &data, m_ptr_qry.rvals);
}
-/* Check a call STMT to stpncpy() or strncpy() for overflow and warn
- if it does. */
+/* Warn for strncmp on a zero sized source or when an argument isn't
+ nul-terminated. */
+void
+pass_waccess::warn_zero_sized_strncmp_inputs (gimple *stmt, tree *bndrng,
+ access_data *pad)
+{
+ tree func = get_callee_fndecl (stmt);
+ location_t loc = gimple_location (stmt);
+ maybe_warn_for_bound (OPT_Wstringop_overread, loc, stmt, func, bndrng,
+ size_zero_node, pad);
+}
+
+/* Check a call STMT to strncmp () for overflow and warn if it does. This is
+ limited to checking for NUL terminated arrays for now. */
void
pass_waccess::check_strncmp (gcall *stmt)
@@ -2703,21 +2718,11 @@ pass_waccess::check_strncmp (gcall *stmt)
else if (rem2 == 0 || (rem2 < rem1 && lendata2.decl))
rem1 = rem2;
- /* Point PAD at the array to reference in the note if a warning
- is issued. */
- access_data *pad = len1 ? &adata2 : &adata1;
- offset_int maxrem = wi::max (rem1, rem2, UNSIGNED);
- if (lendata1.decl || lendata2.decl
- || maxrem < wi::to_offset (bndrng[0]))
- {
- /* Warn when either argument isn't nul-terminated or the maximum
- remaining space in the two arrays is less than the bound. */
- tree func = get_callee_fndecl (stmt);
- location_t loc = gimple_location (stmt);
- maybe_warn_for_bound (OPT_Wstringop_overread, loc, stmt, func,
- bndrng, wide_int_to_tree (sizetype, maxrem),
- pad);
- }
+ if (rem1 == 0)
+ warn_zero_sized_strncmp_inputs (stmt, bndrng, &adata1);
+ if (rem2 == 0)
+ warn_zero_sized_strncmp_inputs (stmt, bndrng, &adata2);
+
}
/* Determine and check the sizes of the source and the destination
@@ -431,7 +431,7 @@ void test_strncmp_array (const char *s, int i)
T (strncmp (a1, b1, 0));
T (strncmp (a1, b1, 1));
- T (strncmp (a1, b1, 2)); // { dg-warning "'strncmp' specified bound 2 exceeds source size 1" }
+ T (strncmp (a1, b1, 2));
}