diff options
author | Martin Sebor <msebor@redhat.com> | 2019-02-11 17:44:05 +0000 |
---|---|---|
committer | Martin Sebor <msebor@gcc.gnu.org> | 2019-02-11 10:44:05 -0700 |
commit | 287ef129b68d25d219b167163a2494d82bee5820 (patch) | |
tree | cdd2b8ec87767d99ab4bcddece5ee1e1a452fe6f /gcc/gimple-ssa-warn-restrict.c | |
parent | 28a8cef1e240989c199dfd8538c826c134098f85 (diff) | |
download | gcc-287ef129b68d25d219b167163a2494d82bee5820.zip gcc-287ef129b68d25d219b167163a2494d82bee5820.tar.gz gcc-287ef129b68d25d219b167163a2494d82bee5820.tar.bz2 |
PR tree-optimization/88771 - Misleading -Werror=array-bounds error
gcc/ChangeLog:
PR tree-optimization/88771
* gimple-ssa-warn-restrict.c (pass_wrestrict::gate): Also enable
when -Wstringop-overflow is set.
(builtin_memref::builtin_memref): Adjust excessive upper bound
only when lower bound is not excessive.
(maybe_diag_overlap): Detect and diagnose excessive bounds via
-Wstringop-ovefflow.
(maybe_diag_offset_bounds): Rename...
(maybe_diag_access_bounds): ...to this.
(check_bounds_or_overlap): Adjust for name change above.
gcc/testsuite/ChangeLog:
PR tree-optimization/88771
* gcc.dg/Wstringop-overflow-8.c: New test.
* gcc.dg/Wstringop-overflow-9.c: New test.
* gcc.dg/Warray-bounds-40.c: New test.
* gcc.dg/builtin-stpncpy.c: Adjust.
* gcc.dg/builtin-stringop-chk-4.c: Adjust.
* g++.dg/opt/memcpy1.C: Adjust.
From-SVN: r268775
Diffstat (limited to 'gcc/gimple-ssa-warn-restrict.c')
-rw-r--r-- | gcc/gimple-ssa-warn-restrict.c | 67 |
1 files changed, 53 insertions, 14 deletions
diff --git a/gcc/gimple-ssa-warn-restrict.c b/gcc/gimple-ssa-warn-restrict.c index b069f3a..6643b89 100644 --- a/gcc/gimple-ssa-warn-restrict.c +++ b/gcc/gimple-ssa-warn-restrict.c @@ -75,7 +75,7 @@ class pass_wrestrict : public gimple_opt_pass bool pass_wrestrict::gate (function *fun ATTRIBUTE_UNUSED) { - return warn_array_bounds != 0 || warn_restrict != 0; + return warn_array_bounds || warn_restrict || warn_stringop_overflow; } /* Class to walk the basic blocks of a function in dominator order. */ @@ -256,7 +256,7 @@ builtin_memref::builtin_memref (tree expr, tree size) sizrange[1] = wi::to_offset (range[1]); /* get_size_range returns SIZE_MAX for the maximum size. Constrain it to the real maximum of PTRDIFF_MAX. */ - if (sizrange[1] > maxobjsize) + if (sizrange[0] <= maxobjsize && sizrange[1] > maxobjsize) sizrange[1] = maxobjsize; } else @@ -1567,18 +1567,56 @@ maybe_diag_overlap (location_t loc, gimple *call, builtin_access &acs) return true; } -/* Validate REF offsets in an expression passed as an argument to a CALL - to a built-in function FUNC to make sure they are within the bounds - of the referenced object if its size is known, or PTRDIFF_MAX otherwise. - Both initial values of the offsets and their final value computed by - the function by incrementing the initial value by the size are +/* Validate REF size and offsets in an expression passed as an argument + to a CALL to a built-in function FUNC to make sure they are within + the bounds of the referenced object if its size is known, or + PTRDIFF_MAX otherwise. DO_WARN is true when a diagnostic should + be issued, false otherwise. + Both initial values of the offsets and their final value computed + by the function by incrementing the initial value by the size are validated. Return true if the offsets are not valid and a diagnostic - has been issued. */ + has been issued, or would have been issued if DO_WARN had been true. */ static bool -maybe_diag_offset_bounds (location_t loc, gimple *call, tree func, int strict, +maybe_diag_access_bounds (location_t loc, gimple *call, tree func, int strict, const builtin_memref &ref, bool do_warn) { + const offset_int maxobjsize = tree_to_shwi (max_object_size ()); + + /* Check for excessive size first and regardless of warning options + since the result is used to make codegen decisions. */ + if (ref.sizrange[0] > maxobjsize) + { + /* Return true without issuing a warning. */ + if (!do_warn) + return true; + + if (ref.ref && TREE_NO_WARNING (ref.ref)) + return false; + + if (warn_stringop_overflow) + { + if (EXPR_HAS_LOCATION (ref.ptr)) + loc = EXPR_LOCATION (ref.ptr); + + loc = expansion_point_location_if_in_system_header (loc); + + if (ref.sizrange[0] == ref.sizrange[1]) + return warning_at (loc, OPT_Wstringop_overflow_, + "%G%qD specified bound %wu " + "exceeds maximum object size %wu", + call, func, ref.sizrange[0].to_uhwi (), + maxobjsize.to_uhwi ()); + + return warning_at (loc, OPT_Wstringop_overflow_, + "%G%qD specified bound between %wu and %wu " + "exceeds maximum object size %wu", + call, func, ref.sizrange[0].to_uhwi (), + ref.sizrange[1].to_uhwi (), + maxobjsize.to_uhwi ()); + } + } + /* Check for out-bounds pointers regardless of warning options since the result is used to make codegen decisions. */ offset_int ooboff[] = { ref.offrange[0], ref.offrange[1] }; @@ -1616,11 +1654,12 @@ maybe_diag_offset_bounds (location_t loc, gimple *call, tree func, int strict, if (oobref == error_mark_node) { if (ref.sizrange[0] == ref.sizrange[1]) - sprintf (rangestr[1], "%lli", (long long) ref.sizrange[0].to_shwi ()); + sprintf (rangestr[1], "%llu", + (unsigned long long) ref.sizrange[0].to_shwi ()); else sprintf (rangestr[1], "[%lli, %lli]", - (long long) ref.sizrange[0].to_shwi (), - (long long) ref.sizrange[1].to_shwi ()); + (unsigned long long) ref.sizrange[0].to_uhwi (), + (unsigned long long) ref.sizrange[1].to_uhwi ()); tree type; @@ -1854,8 +1893,8 @@ check_bounds_or_overlap (gimple *call, tree dst, tree src, tree dstsize, /* Validate offsets first to make sure they are within the bounds of the destination object if its size is known, or PTRDIFF_MAX otherwise. */ - if (maybe_diag_offset_bounds (loc, call, func, strict, dstref, do_warn) - || maybe_diag_offset_bounds (loc, call, func, strict, srcref, do_warn)) + if (maybe_diag_access_bounds (loc, call, func, strict, dstref, do_warn) + || maybe_diag_access_bounds (loc, call, func, strict, srcref, do_warn)) { if (do_warn) gimple_set_no_warning (call, true); |