diff options
author | Martin Sebor <msebor@redhat.com> | 2020-04-21 10:59:24 -0600 |
---|---|---|
committer | Martin Sebor <msebor@redhat.com> | 2020-04-21 11:11:06 -0600 |
commit | 3942060c4b3168307b9e2870d81e7ca15b49760a (patch) | |
tree | 63775e1c15a45fc845647576c47d8e22cd3a4620 /gcc/testsuite/c-c++-common | |
parent | fb22faf48f6eb518932f24005f8606e5f19a7304 (diff) |
PR middle-end/94647 - bogus -Warray-bounds on strncpy into a larger member array from a smaller array
gcc/ChangeLog:
PR middle-end/94647
* gimple-ssa-warn-restrict.c (builtin_access::builtin_access): Correct
the computation of the lower bound of the source access size.
(builtin_access::generic_overlap): Remove a hack for setting ranges
of overlap offsets.
gcc/testsuite/ChangeLog:
PR middle-end/94647
* c-c++-common/Warray-bounds-2.c: Adjust a test case and add a new one.
* c-c++-common/Warray-bounds-3.c: Add tests for missing warnings.
* c-c++-common/Wrestrict.c: Invert bounds in printed ranges.
* gcc.dg/Warray-bounds-59.c: New test.
* gcc.dg/Wrestrict-10.c: Add a missing warning.
* gcc.dg/Wrestrict-5.c: Adjust text of expected warning.
* gcc.dg/Wrestrict-6.c: Expect to see a range of overlap offsets.
Diffstat (limited to 'gcc/testsuite/c-c++-common')
-rw-r--r-- | gcc/testsuite/c-c++-common/Warray-bounds-2.c | 16 | ||||
-rw-r--r-- | gcc/testsuite/c-c++-common/Warray-bounds-3.c | 9 | ||||
-rw-r--r-- | gcc/testsuite/c-c++-common/Wrestrict.c | 45 |
3 files changed, 48 insertions, 22 deletions
diff --git a/gcc/testsuite/c-c++-common/Warray-bounds-2.c b/gcc/testsuite/c-c++-common/Warray-bounds-2.c index 7f925c34bae..8c6e0a62b15 100644 --- a/gcc/testsuite/c-c++-common/Warray-bounds-2.c +++ b/gcc/testsuite/c-c++-common/Warray-bounds-2.c @@ -172,14 +172,26 @@ void call_strncpy_src_xsize (char *d, size_t n) /* Exercise strncpy out-of-bounds offsets with an array of unknown size. */ static void -wrap_strncpy_src_diff_max (char *d, const char *s, ptrdiff_t i, size_t n) +wrap_strncpy_src_diff_max_m1 (char *d, const char *s, ptrdiff_t i, size_t n) { /* Unlike in the similar call to memcpy(), there is no pointer overflow here because the size N is not added to the source - offset. */ + offset MAX - 1 (only 1 is for the access to its first element, + which is tested below). */ strncpy (d, s + i, n); } +void call_strncpy_src_diff_max_m1 (char *d, const char *s, size_t n) +{ + wrap_strncpy_src_diff_max_m1 (d, s, MAX - 1, 3); +} + +static void +wrap_strncpy_src_diff_max (char *d, const char *s, ptrdiff_t i, size_t n) +{ + strncpy (d, s + i, n); /* { dg-warning "pointer overflow between offset 9223372036854775807 and size \\\[1, 0]" } */ +} + void call_strncpy_src_diff_max (char *d, const char *s, size_t n) { wrap_strncpy_src_diff_max (d, s, MAX, 3); diff --git a/gcc/testsuite/c-c++-common/Warray-bounds-3.c b/gcc/testsuite/c-c++-common/Warray-bounds-3.c index ab84c602625..aae4999ea13 100644 --- a/gcc/testsuite/c-c++-common/Warray-bounds-3.c +++ b/gcc/testsuite/c-c++-common/Warray-bounds-3.c @@ -287,15 +287,16 @@ void test_strcpy_bounds (char *d, const char *s) TI (char, 1, "", a, a + SR (0, DIFF_MAX - 1)); TI (char, 2, "0", a, a + SR (0, DIFF_MAX - 1)); TI (char, 2, "0", a, a + SR (1, DIFF_MAX - 1)); - /* The following needs a warning for reading past the end. */ - TI (char, 2, "0", a, a + SR (2, DIFF_MAX - 1)); + /* The warning below isn't the most accurate because while reading + from it is invalid, the offset that refers just past the end of + the source array is strictly valid. */ + TI (char, 2, "0", a, a + SR (2, DIFF_MAX - 1)); /* { dg-warning "offset 2 is out of the bounds \\\[0, 2] of object \[^\n\r\]+ with type 'char ?\\\[2]'" } */ TI (char, 2, "0", a, a + SR (3, DIFF_MAX - 1)); /* { dg-warning "offset \\\[3, \[0-9\]+] is out of the bounds \\\[0, 2] of object \[^\n\r\]+ with type .char ?\\\[2\\\]." "strcpy" } */ TI (char, 3, "01", a, a + SR (0, DIFF_MAX - 1)); TI (char, 3, "01", a, a + SR (1, DIFF_MAX - 1)); TI (char, 3, "01", a, a + SR (2, DIFF_MAX - 1)); - /* The following needs a warning for reading past the end. */ - TI (char, 3, "01", a, a + SR (3, DIFF_MAX - 1)); + TI (char, 3, "01", a, a + SR (3, DIFF_MAX - 1)); /* { dg-warning "offset 3 is out of the bounds \\\[0, 3] of object \[^\n\r\]+ with type 'char ?\\\[3]'" } */ TI (char, 3, "01", a, a + SR (4, DIFF_MAX - 1)); /* { dg-warning "offset \\\[4, \[0-9\]+] is out of the bounds \\\[0, 3] of object \[^\n\r\]+ with type .char ?\\\[3\\\]." "strcpy" } */ TI (char, 4, "012", a, a + SR (DIFF_MAX - 2, DIFF_MAX - 1)); /* { dg-warning "offset \\\[\[0-9\]+, \[0-9\]+] is out of the bounds \\\[0, 4] of object \[^\n\r\]+ with type .char ?\\\[4\\\]." "strcpy" } */ diff --git a/gcc/testsuite/c-c++-common/Wrestrict.c b/gcc/testsuite/c-c++-common/Wrestrict.c index 1903f502abd..eb074a13e7d 100644 --- a/gcc/testsuite/c-c++-common/Wrestrict.c +++ b/gcc/testsuite/c-c++-common/Wrestrict.c @@ -684,7 +684,7 @@ void test_strcpy_range (void) r = SR (2, 5); T (8, "01", a + r, a); /* { dg-warning "accessing 3 bytes at offsets \\\[2, 5] and 0 may overlap 1 byte at offset 2" } */ - T (8, "012", a + r, a); /* { dg-warning "accessing 4 bytes at offsets \\\[2, 5] and 0 may overlap up to 2 bytes at offset \\\[3, 2]" "strcpy" } */ + T (8, "012", a + r, a); /* { dg-warning "accessing 4 bytes at offsets \\\[2, 5] and 0 may overlap up to 2 bytes at offset \\\[2, 3]" "strcpy" } */ /* The highest offset to which to copy without overflowing the 8-byte destination is 3 and that overlaps 2 bytes. */ @@ -697,7 +697,7 @@ void test_strcpy_range (void) /* With a 10-byte buffer it's possible to copy all 5 bytes without overlap at (a + 5). Copying at offsets 2 through 4 overflows between 3 and 1 bytes, respectively. */ - T (10, "0123", a + r, a); /* { dg-warning "accessing 5 bytes at offsets \\\[2, 5] and 0 may overlap up to 3 bytes at offset \\\[4, 2]" "strcpy" } */ + T (10, "0123", a + r, a); /* { dg-warning "accessing 5 bytes at offsets \\\[2, 5] and 0 may overlap up to 3 bytes at offset \\\[2, 4]" "strcpy" } */ r = SR (3, 4); @@ -727,7 +727,7 @@ void test_strcpy_range (void) overlap, so the warning is a "may overlap" and the size of the overlap is 1 byte. */ T (8, "012345", a, a + r); /* { dg-warning "accessing between 3 and 4 bytes at offsets 0 and \\\[3, 4] may overlap 1 byte at offset 3" "strcpy" } */ - T (8, "0123456", a, a + r); /* { dg-warning "accessing between 4 and 5 bytes at offsets 0 and \\\[3, 4] may overlap up to 2 bytes at offset 3" "strcpy" } */ + T (8, "0123456", a, a + r); /* { dg-warning "accessing between 4 and 5 bytes at offsets 0 and \\\[3, 4] may overlap up to 2 bytes at offset \\\[3, 4]" "strcpy" } */ r = SR (3, DIFF_MAX - 3); T (8, "01", a + r, a); @@ -752,8 +752,8 @@ void test_strcpy_range (void) T (8, "012", a + r, a); /* { dg-warning "accessing 4 bytes at offsets \\\[0, 8] and 0 may overlap up to 4 bytes" "strcpy" } */ T (8, "", a, a + r); /* { dg-warning "accessing 1 byte at offsets 0 and \\\[0, 8] may overlap" "strcpy" } */ - T (8, "0", a, a + r); /* { dg-warning "accessing between 0 and 2 bytes at offsets 0 and \\\[0, 8] may overlap up to 2 bytes" "strcpy" } */ - T (8, "012", a, a + r); /* { dg-warning "accessing between 0 and 4 bytes at offsets 0 and \\\[0, 8] may overlap up to 4 bytes" "strcpy" } */ + T (8, "0", a, a + r); /* { dg-warning "accessing between 1 and 2 bytes at offsets 0 and \\\[0, 8] may overlap up to 2 bytes" "strcpy" } */ + T (8, "012", a, a + r); /* { dg-warning "accessing between 1 and 4 bytes at offsets 0 and \\\[0, 8] may overlap up to 4 bytes" "strcpy" } */ } /* Exercise strcpy with destination and/or source of unknown lengthu. */ @@ -868,18 +868,21 @@ void test_strncpy_range (char *d, size_t n) T ("0123", a, a + i, 0); T ("0123", a, a + i, 1); T ("0123", a, a + i, 2); /* { dg-warning "accessing 2 bytes at offsets 0 and \\\[1, 5] may overlap 1 byte at offset 1" "strncpy" } */ - T ("0123", a, a + i, 3); /* { dg-warning "accessing 3 bytes at offsets 0 and \\\[1, 5] may overlap up to 2 bytes at offset \\\[2, 1]" "strncpy" } */ - T ("0123", a, a + i, 4); /* { dg-warning "accessing 4 bytes at offsets 0 and \\\[1, 5] may overlap up to 3 bytes at offset \\\[3, 1]" "strncpy" } */ - T ("0123", a, a + i, 5); /* { dg-warning "accessing 5 bytes at offsets 0 and \\\[1, 5] may overlap up to 4 bytes at offset \\\[4, 1]" "strncpy" } */ + T ("0123", a, a + i, 3); /* { dg-warning "accessing 3 bytes at offsets 0 and \\\[1, 5] may overlap up to 2 bytes at offset \\\[1, 2]" "strncpy" } */ + T ("0123", a, a + i, 4); /* { dg-warning "accessing 4 bytes at offsets 0 and \\\[1, 5] may overlap up to 3 bytes at offset \\\[1, 3]" "strncpy" } */ + T ("0123", a, a + i, 5); /* { dg-warning "accessing 5 bytes at offsets 0 and \\\[1, 5] may overlap up to 4 bytes at offset \\\[1, 4]" "strncpy" } */ i = SR (2, 5); T ("0123", a, a + i, 0); T ("0123", a, a + i, 1); T ("0123", a, a + i, 2); T ("0123", a, a + i, 3); /* { dg-warning "accessing 3 bytes at offsets 0 and \\\[2, 5] may overlap 1 byte at offset 2" "strncpy" } */ - T ("0123", a, a + i, 4); /* { dg-warning "accessing 4 bytes at offsets 0 and \\\[2, 5] may overlap up to 2 bytes at offset \\\[3, 2]" "strncpy" } */ - T ("0123", a, a + i, 5); /* { dg-warning "accessing 5 bytes at offsets 0 and \\\[2, 5] may overlap up to 3 bytes at offset \\\[4, 2]" "strncpy" } */ - T ("0123", a, a + i, 6); /* { dg-warning "accessing 6 bytes at offsets 0 and \\\[2, 5] may overlap up to 3 bytes at offset \\\[4, 2]" "strncpy" } */ + T ("0123", a, a + i, 4); /* { dg-warning "accessing 4 bytes at offsets 0 and \\\[2, 5] may overlap up to 2 bytes at offset \\\[2, 3]" "strncpy" } */ + T ("0123", a, a + i, 5); /* { dg-warning "accessing 5 bytes at offsets 0 and \\\[2, 5] may overlap up to 3 bytes at offset \\\[2, 4]" "strncpy" } */ + /* When i == 5 the following overlaps at least 1 byte: the nul at a[5] + (if a + 5 is the empty string). If a + 5 is not empty then it overlaps + it plus as many non-nul characters after it, up to the total of 6. */ + T ("0123", a, a + i, 6); /* { dg-warning "accessing 6 bytes at offsets 0 and \\\[2, 5] overlaps between 1 and 3 bytes at offset \\\[2, 5]" "strncpy" } */ i = SR (3, 5); T ("0123", a, a + i, 0); @@ -887,8 +890,14 @@ void test_strncpy_range (char *d, size_t n) T ("0123", a, a + i, 2); T ("0123", a, a + i, 3); T ("0123", a, a + i, 4); /* { dg-warning "accessing 4 bytes at offsets 0 and \\\[3, 5] may overlap 1 byte at offset 3" "strncpy" } */ - T ("0123", a, a + i, 5); /* { dg-warning "accessing 5 bytes at offsets 0 and \\\[3, 5] may overlap up to 2 bytes at offset \\\[4, 3]" "strncpy" } */ - T ("0123", a, a + i, 6); /* { dg-warning "accessing 6 bytes at offsets 0 and \\\[3, 5] may overlap up to 2 bytes at offset \\\[4, 3]" "strncpy" } */ + T ("0123", a, a + i, 5); /* { dg-warning "accessing 5 bytes at offsets 0 and \\\[3, 5] may overlap up to 2 bytes at offset \\\[3, 4]" "strncpy" } */ + + /* The following copy overlaps at most 2 bytes. When i == 3 it overlaps + the 2 bytes at "3", when i == 4 just the final nul. When i == 5 it + also overlaps 1 byte, the nul at a[5]. Although the overlap offset + range suggests the overlap is up to three bytes, it correctly reflects + the union of the two cases. */ + T ("0123", a, a + i, 6); /* { dg-warning "accessing 6 bytes at offsets 0 and \\\[3, 5] overlaps between 1 and 2 bytes at offset \\\[3, 5]" "strncpy" } */ i = SR (4, 5); T ("0123", a, a + i, 0); @@ -897,7 +906,11 @@ void test_strncpy_range (char *d, size_t n) T ("0123", a, a + i, 3); T ("0123", a, a + i, 4); T ("0123", a, a + i, 5); /* { dg-warning "accessing 5 bytes at offsets 0 and \\\[4, 5] may overlap 1 byte at offset 4" "strncpy" } */ - T ("0123", a, a + i, 6); /* { dg-warning "accessing 6 bytes at offsets 0 and \\\[4, 5] may overlap 1 byte at offset 4" "strncpy" } */ + /* Regardless of the value of i, the following overlaps exactlty + one byte: the nul at a[4]. There is no overlap at a[5] because + the source is not read past the nul so the offset below isn't + entirely correct. */ + T ("0123", a, a + i, 6); /* { dg-warning "accessing 6 bytes at offsets 0 and \\\[4, 5] overlaps 1 byte at offset \\\[4, 5]" "strncpy" } */ /* Verify offset and size both in some range. The strncpy checking is more strict than that of memcpy and triggers even when the @@ -911,10 +924,10 @@ void test_strncpy_range (char *d, size_t n) i = 5: 567* none 567*. none 567*.. overlaps 1 at offset 5 */ - T ("01234567", a, a + i, UR (4, 6)); /* { dg-warning "accessing between 4 and 6 bytes at offsets 0 and \\\[4, 5] may overlap up to 2 bytes at offset \\\[5, 4]" "strncpy" } */ + T ("01234567", a, a + i, UR (4, 6)); /* { dg-warning "accessing between 4 and 6 bytes at offsets 0 and \\\[4, 5] may overlap up to 2 bytes at offset \\\[4, 5]" "strncpy" } */ /* Ditto for objects of unknown sizes. */ - T ("01234567", d, d + i, UR (4, 6)); /* { dg-warning "accessing between 4 and 6 bytes at offsets 0 and \\\[4, 5] may overlap up to 2 bytes at offset \\\[5, 4]" "strncpy" } */ + T ("01234567", d, d + i, UR (4, 6)); /* { dg-warning "accessing between 4 and 6 bytes at offsets 0 and \\\[4, 5] may overlap up to 2 bytes at offset \\\[4, 5]" "strncpy" } */ T ("01234567", a, a + i, UR (6, 7)); /* { dg-warning "accessing between 6 and 7 bytes at offsets 0 and \\\[4, 5] overlaps between 1 and 3 bytes at offset \\\[4, 5]" "strncpy" } */ |