summaryrefslogtreecommitdiff
path: root/gcc/testsuite/c-c++-common
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2020-04-21 10:59:24 -0600
committerMartin Sebor <msebor@redhat.com>2020-04-21 11:11:06 -0600
commit3942060c4b3168307b9e2870d81e7ca15b49760a (patch)
tree63775e1c15a45fc845647576c47d8e22cd3a4620 /gcc/testsuite/c-c++-common
parentfb22faf48f6eb518932f24005f8606e5f19a7304 (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.c16
-rw-r--r--gcc/testsuite/c-c++-common/Warray-bounds-3.c9
-rw-r--r--gcc/testsuite/c-c++-common/Wrestrict.c45
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" } */