diff options
author | Martin Sebor <msebor@redhat.com> | 2020-10-09 14:48:43 -0600 |
---|---|---|
committer | Martin Sebor <msebor@redhat.com> | 2020-10-12 09:05:55 -0600 |
commit | 83685efd5fd1623cfc4e4c435ce2773d95d458d1 (patch) | |
tree | 5a6514717cd82b39bcec8872ba61871599c5684a /gcc/testsuite/gcc.dg/Wstringop-overflow-46.c | |
parent | de05c19d5fd661ae16dd75a895b49d32d12f5edc (diff) | |
download | gcc-83685efd5fd1623cfc4e4c435ce2773d95d458d1.zip gcc-83685efd5fd1623cfc4e4c435ce2773d95d458d1.tar.gz gcc-83685efd5fd1623cfc4e4c435ce2773d95d458d1.tar.bz2 |
Generalize compute_objsize to return maximum size/offset instead of failing (PR middle-end/97023).
Also resolves:
PR middle-end/97342 - bogus -Wstringop-overflow with nonzero signed and unsigned offsets
PR middle-end/97023 - missing warning on buffer overflow in chained mempcpy
PR middle-end/96384 - bogus -Wstringop-overflow= storing into multidimensional array with index in range
gcc/ChangeLog:
PR middle-end/97342
PR middle-end/97023
PR middle-end/96384
* builtins.c (access_ref::access_ref): Initialize new member. Use
new enum.
(access_ref::size_remaining): Define new member function.
(inform_access): Handle expressions referencing objects.
(gimple_call_alloc_size): Call get_size_range instead of get_range.
(gimple_call_return_array): New function.
(get_range): Rename...
(get_offset_range): ...to this. Improve detection of ranges from
types of expressions.
(gimple_call_return_array): Adjust calls to get_range per above.
(compute_objsize): Same. Set maximum size or offset instead of
failing for unknown objects and handle more kinds of expressions.
(compute_objsize): Call access_ref::size_remaining.
(compute_objsize): Have transitional wrapper fail for pointers
into unknown objects.
(expand_builtin_strncmp): Call access_ref::size_remaining and
handle new cases.
* builtins.h (access_ref::size_remaining): Declare new member function.
(access_ref::set_max_size_range): Define new member function.
(access_ref::add_ofset, access_ref::add_max_ofset): Same.
(access_ref::add_base0): New data member.
* calls.c (get_size_range): Change argument type. Handle new
condition.
* calls.h (get_size_range): Adjust signature.
(enum size_range_flags): Define new type.
* gimple-ssa-warn-restrict.c (builtin_memref::builtin_memref): Correct
argument to get_size_range.
* tree-ssa-strlen.c (get_range): Handle anti-ranges.
(maybe_warn_overflow): Check DECL_P before assuming it's one.
gcc/testsuite/ChangeLog:
PR middle-end/97342
PR middle-end/97023
PR middle-end/96384
* c-c++-common/Wrestrict.c: Adjust comment.
* gcc.dg/Wstringop-overflow-34.c: Remove xfail.
* gcc.dg/Wstringop-overflow-43.c: Remove xfails. Adjust regex patterns.
* gcc.dg/pr51683.c: Prune out expected warning.
* gcc.target/i386/pr60693.c: Same.
* g++.dg/warn/Wplacement-new-size-8.C: New test.
* gcc.dg/Wstringop-overflow-41.c: New test.
* gcc.dg/Wstringop-overflow-44.s: New test.
* gcc.dg/Wstringop-overflow-45.c: New test.
* gcc.dg/Wstringop-overflow-46.c: New test.
* gcc.dg/Wstringop-overflow-47.c: New test.
* gcc.dg/Wstringop-overflow-49.c: New test.
* gcc.dg/Wstringop-overflow-50.c: New test.
* gcc.dg/Wstringop-overflow-51.c: New test.
* gcc.dg/Wstringop-overflow-52.c: New test.
* gcc.dg/Wstringop-overflow-53.c: New test.
* gcc.dg/Wstringop-overflow-54.c: New test.
* gcc.dg/Wstringop-overflow-55.c: New test.
* gcc.dg/Wstringop-overread-5.c: New test.
Diffstat (limited to 'gcc/testsuite/gcc.dg/Wstringop-overflow-46.c')
-rw-r--r-- | gcc/testsuite/gcc.dg/Wstringop-overflow-46.c | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-46.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-46.c new file mode 100644 index 0000000..a4d78b2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-46.c @@ -0,0 +1,97 @@ +/* PR middle-end/97023 - missing warning on buffer overflow in chained mempcpy + Verify that out of bounds writes by built-ins to objects through pointers + returned by memchr() are diagnosed. + { dg-do compile } + { dg-options "-O2" } */ + +#include "range.h" + +void* malloc (size_t); +void* memchr (void*, int, size_t); +void* memset (void*, int, size_t); + +void sink (void*, ...); + +void nowarn_memchr_cst_memset_cst (const void *s) +{ + char *p = malloc (4); + sink (p); + + p = memchr (p, '1', 4); + memset (p, 0, 4); +} + +void nowarn_memchr_uint_memset_cst (const void *s, unsigned n) +{ + char *p = malloc (4); + sink (p); + + p = memchr (p, '1', n); + memset (p, 0, 4); +} + +void nowarn_memchr_sz_memset_cst (const void *s, size_t n) +{ + char *p = malloc (4); + sink (p); + + p = memchr (p, '1', n); + memset (p, 0, 4); +} + +void nowarn_memchr_anti_range_memset_cst (const void *s, size_t n) +{ + char *p = malloc (4); + sink (p); + + if (n == 0) + n = 1; + + p = memchr (p, '1', n); + memset (p, 0, 4); +} + +void warn_memchr_cst_memset_cst (const void *s) +{ + char *p = malloc (4); // { dg-message "at offset \\\[0, 4] into destination object of size 4 " "note" } + sink (p); + + p = memchr (p, '1', 4); + memset (p, 0, 5); // { dg-warning "writing 5 bytes into a region of size 4 " } +} + +void warn_memchr_var_memset_cst (const void *s, unsigned n) +{ + char *p = malloc (4); // { dg-message "at offset \\\[0, 4] into destination object of size 4 " "note" } + sink (p); + + p = memchr (p, '1', n); + memset (p, 0, 5); // { dg-warning "writing 5 bytes into a region of size 4 " } +} + +void warn_memchr_var_memset_range (const void *s, unsigned n) +{ + /* The offsets in the first two notes are bounded by the size of + the allocated object. The real upper bound of the offset in + the last note includes the upper bound f the offset of the pointer + returned from the previous memchr() call, but it ends up getting + constrained to the bounds of the allocated object so it's the same + as in the first two notes. The exact value probably isn't too + important. */ + char *p0 = malloc (UR (5, 7)); + // { dg-message "at offset \\\[0, 7] into destination object of size \\\[5, 7]" "note" { target *-*-* } .-1 } + // { dg-message "at offset \\\[1, 7] into destination object of size \\\[5, 7]" "note" { target *-*-* } .-2 } + // { dg-message "at offset \\\[2, 7] into destination object of size \\\[5, 7]" "note" { target *-*-* } .-3 } + + sink (p0); + char *p1 = memchr (p0, '1', n); + memset (p1, 0, UR (8, 9)); // { dg-warning "writing between 8 and 9 bytes into a region of size 7 " } + + sink (p0); + p1 = memchr (p0 + 1, '2', n); + memset (p1, 0, UR (7, 9)); // { dg-warning "writing between 7 and 9 bytes into a region of size 6 " } + + sink (p0); + char *p2 = memchr (p1 + 1, '3', n); + memset (p2, 0, UR (6, 9)); // { dg-warning "writing between 6 and 9 bytes into a region of size 5 " } +} |