diff options
author | Martin Sebor <msebor@redhat.com> | 2021-07-07 14:05:25 -0600 |
---|---|---|
committer | Martin Sebor <msebor@redhat.com> | 2021-07-07 14:06:59 -0600 |
commit | a110855667782dac7b674d3e328b253b3b3c919b (patch) | |
tree | 4d7212fdc8b29304d8defd03eefdb6ca842daa2f /gcc/builtins.c | |
parent | 6278065af07634278ba30029d92a82b089969baa (diff) | |
download | gcc-a110855667782dac7b674d3e328b253b3b3c919b.zip gcc-a110855667782dac7b674d3e328b253b3b3c919b.tar.gz gcc-a110855667782dac7b674d3e328b253b3b3c919b.tar.bz2 |
Correct handling of variable offset minus constant in -Warray-bounds [PR100137]
Resolves:
PR tree-optimization/100137 - -Warray-bounds false positive on varying offset plus negative
PR tree-optimization/99121 - ICE in -Warray-bounds on a multidimensional
PR tree-optimization/97027 - missing warning on buffer overflow storing a larger scalar into a smaller array
gcc/ChangeLog:
PR tree-optimization/100137
PR tree-optimization/99121
PR tree-optimization/97027
* builtins.c (access_ref::access_ref): Also set offmax.
(access_ref::offset_in_range): Define new function.
(access_ref::add_offset): Set offmax.
(access_ref::inform_access): Handle access_none.
(handle_mem_ref): Clear ostype.
(compute_objsize_r): Handle ASSERT_EXPR.
* builtins.h (struct access_ref): Add offmax member.
* gimple-array-bounds.cc (array_bounds_checker::check_mem_ref): Use
compute_objsize() and simplify.
gcc/testsuite/ChangeLog:
PR tree-optimization/100137
PR tree-optimization/99121
PR tree-optimization/97027
* c-c++-common/Warray-bounds-3.c: Remove xfail
* c-c++-common/Warray-bounds-4.c: Add an expected warning.
* c-c++-common/Warray-bounds-9.c: New test.
* c-c++-common/Warray-bounds-10.c: New test.
* g++.dg/asan/asan_test.C: Suppress expected warnings.
* g++.dg/pr95768.C: Same.
* g++.dg/warn/Warray-bounds-10.C: Adjust text of expected messages.
* g++.dg/warn/Warray-bounds-11.C: Same.
* g++.dg/warn/Warray-bounds-12.C: Same.
* g++.dg/warn/Warray-bounds-13.C: Same.
* g++.dg/warn/Warray-bounds-17.C: Same.
* g++.dg/warn/Warray-bounds-20.C: Same.
* gcc.dg/Warray-bounds-29.c: Same.
* gcc.dg/Warray-bounds-30.c: Add xfail.
* gcc.dg/Warray-bounds-31.c: Adjust text of expected messages.
* gcc.dg/Warray-bounds-32.c: Same.
* gcc.dg/Warray-bounds-52.c: Same.
* gcc.dg/Warray-bounds-53.c: Same.
* gcc.dg/Warray-bounds-58.c: Remove xfail.
* gcc.dg/Warray-bounds-63.c: Adjust text of expected messages.
* gcc.dg/Warray-bounds-66.c: Same.
* gcc.dg/Warray-bounds-69.c: Same.
* gcc.dg/Wstringop-overflow-34.c: Same.
* gcc.dg/Wstringop-overflow-47.c: Same.
* gcc.dg/Wstringop-overflow-61.c: Same.
* gcc.dg/Warray-bounds-77.c: New test.
* gcc.dg/Warray-bounds-78.c: New test.
* gcc.dg/Warray-bounds-79.c: New test.
Diffstat (limited to 'gcc/builtins.c')
-rw-r--r-- | gcc/builtins.c | 69 |
1 files changed, 61 insertions, 8 deletions
diff --git a/gcc/builtins.c b/gcc/builtins.c index e52fe42..39ab139 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -206,6 +206,7 @@ access_ref::access_ref (tree bound /* = NULL_TREE */, { /* Set to valid. */ offrng[0] = offrng[1] = 0; + offmax[0] = offmax[1] = 0; /* Invalidate. */ sizrng[0] = sizrng[1] = -1; @@ -457,6 +458,21 @@ access_ref::size_remaining (offset_int *pmin /* = NULL */) const return sizrng[1] - or0; } +/* Return true if the offset and object size are in range for SIZE. */ + +bool +access_ref::offset_in_range (const offset_int &size) const +{ + if (size_remaining () < size) + return false; + + if (base0) + return offmax[0] >= 0 && offmax[1] <= sizrng[1]; + + offset_int maxoff = wi::to_offset (TYPE_MAX_VALUE (ptrdiff_type_node)); + return offmax[0] > -maxoff && offmax[1] < maxoff; +} + /* Add the range [MIN, MAX] to the offset range. For known objects (with zero-based offsets) at least one of whose offset's bounds is in range, constrain the other (or both) to the bounds of the object (i.e., zero @@ -493,6 +509,8 @@ void access_ref::add_offset (const offset_int &min, const offset_int &max) if (max >= 0) { offrng[0] = 0; + if (offmax[0] > 0) + offmax[0] = 0; return; } @@ -509,6 +527,12 @@ void access_ref::add_offset (const offset_int &min, const offset_int &max) offrng[0] = 0; } + /* Set the minimum and maximmum computed so far. */ + if (offrng[1] < 0 && offrng[1] < offmax[0]) + offmax[0] = offrng[1]; + if (offrng[0] > 0 && offrng[0] > offmax[1]) + offmax[1] = offrng[0]; + if (!base0) return; @@ -4571,23 +4595,46 @@ access_ref::inform_access (access_mode mode) const return; } + if (mode == access_read_only) + { + if (allocfn == NULL_TREE) + { + if (*offstr) + inform (loc, "at offset %s into source object %qE of size %s", + offstr, ref, sizestr); + else + inform (loc, "source object %qE of size %s", ref, sizestr); + + return; + } + + if (*offstr) + inform (loc, + "at offset %s into source object of size %s allocated by %qE", + offstr, sizestr, allocfn); + else + inform (loc, "source object of size %s allocated by %qE", + sizestr, allocfn); + return; + } + if (allocfn == NULL_TREE) { if (*offstr) - inform (loc, "at offset %s into source object %qE of size %s", + inform (loc, "at offset %s into object %qE of size %s", offstr, ref, sizestr); else - inform (loc, "source object %qE of size %s", ref, sizestr); + inform (loc, "object %qE of size %s", ref, sizestr); return; } if (*offstr) inform (loc, - "at offset %s into source object of size %s allocated by %qE", + "at offset %s into object of size %s allocated by %qE", offstr, sizestr, allocfn); else - inform (loc, "source object of size %s allocated by %qE", + inform (loc, "object of size %s allocated by %qE", sizestr, allocfn); } @@ -5433,16 +5480,16 @@ handle_mem_ref (tree mref, int ostype, access_ref *pref, if (VECTOR_TYPE_P (TREE_TYPE (mref))) { - /* Hack: Give up for MEM_REFs of vector types; those may be - synthesized from multiple assignments to consecutive data - members (see PR 93200 and 96963). + /* Hack: Handle MEM_REFs of vector types as those to complete + objects; those may be synthesized from multiple assignments + to consecutive data members (see PR 93200 and 96963). FIXME: Vectorized assignments should only be present after vectorization so this hack is only necessary after it has run and could be avoided in calls from prior passes (e.g., tree-ssa-strlen.c). FIXME: Deal with this more generally, e.g., by marking up such MEM_REFs at the time they're created. */ - return false; + ostype = 0; } tree mrefop = TREE_OPERAND (mref, 0); @@ -5796,6 +5843,12 @@ compute_objsize_r (tree ptr, int ostype, access_ref *pref, tree rhs = gimple_assign_rhs1 (stmt); + if (code == ASSERT_EXPR) + { + rhs = TREE_OPERAND (rhs, 0); + return compute_objsize_r (rhs, ostype, pref, snlim, qry); + } + if (code == POINTER_PLUS_EXPR && TREE_CODE (TREE_TYPE (rhs)) == POINTER_TYPE) { |