+2020-04-21 Martin Sebor <msebor@redhat.com>
+
+ 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.
+
2020-04-21 John David Anglin <danglin@gcc.gnu.org>
* config/pa/som.h (ASM_WEAKEN_LABEL): Delete.
}
else if (srcref->sizrange[0] == 0 && srcref->sizrange[1] == maxobjsize)
{
- /* When the source size is unknown set it to the size of
- the destination. */
+ /* When the size of the source access is unknown set it to the size
+ of the destination first and adjust it later if necessary. */
srcref->sizrange[0] = dstref->sizrange[0];
srcref->sizrange[1] = dstref->sizrange[1];
{
/* Read access by strncpy is constrained by the third
argument but except for a zero bound is at least one. */
- offset_int size = wi::umax (srcref->basesize, 1);
- offset_int bound = wi::umin (size, bounds[0]);
- if (bound < srcref->sizrange[0])
- srcref->sizrange[0] = bound;
- bound = wi::umin (srcref->basesize, bounds[1]);
+ srcref->sizrange[0] = bounds[1] > 0 ? 1 : 0;
+ offset_int bound = wi::umin (srcref->basesize, bounds[1]);
if (bound < srcref->sizrange[1])
srcref->sizrange[1] = bound;
}
-
/* For string functions, adjust the size range of the source
reference by the inverse boundaries of the offset (because
the higher the offset into the string the shorter its
&& srcref->offrange[1] < srcref->sizrange[0])
srcref->sizrange[0] -= srcref->offrange[1];
else
- srcref->sizrange[0] = 0;
+ srcref->sizrange[0] = 1;
if (srcref->offrange[0] > 0)
{
ovloff[0] = HOST_WIDE_INT_MAX;
ovloff[1] = HOST_WIDE_INT_MIN;
- /* Adjustment to the lower bound of the offset of the overlap to
- account for a subset of unbounded string calls where the size
- of the destination string depends on the length of the source
- which in turn depends on the offset into it. */
- bool sub1;
-
if (stxcpy_p)
{
- sub1 = acs.dstoff[0] <= acs.srcoff[0];
-
/* Iterate over the extreme locations (on the horizontal axis formed
by their offsets) and sizes of two regions and find their smallest
and largest overlap and the corresponding offsets. */
}
else
{
- sub1 = !depends_p;
-
/* Iterate over the extreme locations (on the horizontal axis
- formed by their offsets) and sizes of two regions and find
- their smallest and largest overlap and the corresponding
+ formed by their offsets) and sizes of the two regions and
+ find their smallest and largest overlap and the corresponding
offsets. */
for (unsigned io = 0; io != 2; ++io)
for (unsigned jo = 0; jo != 2; ++jo)
for (unsigned js = 0; js != 2; ++js)
{
- if (depends_p)
- {
- /* For st{p,r}ncpy the size of the source sequence
- depends on the offset into it. */
- if (js)
- break;
- js = !jo;
- }
-
const offset_int b[2] = {
acs.srcoff[jo], acs.srcoff[jo] + acs.srcsiz[js]
};
ovlsiz[0] = siz[0].to_shwi ();
ovlsiz[1] = siz[1].to_shwi ();
+ /* Adjust the overlap offset range to reflect the overlap size range. */
if (ovlsiz[0] == 0 && ovlsiz[1] > 1)
- ovloff[0] = ovloff[1] + ovlsiz[1] - 1 - sub1;
+ ovloff[1] = ovloff[0] + ovlsiz[1] - 1;
return true;
}
+2020-04-21 Martin Sebor <msebor@redhat.com>
+
+ 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.
+
2020-04-21 Szabolcs Nagy <szabolcs.nagy@arm.com>
PR target/94514
/* 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);
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" } */
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. */
/* 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);
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);
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. */
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);
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);
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
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" } */
--- /dev/null
+/* PR middle-end/94647 - bogus -Warray-bounds on strncpy into a larger
+ member array from a smaller array
+ { dg-do compile }
+ { dg-options "-O2 -Wall" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+extern char* strncpy (char*, const char*, size_t);
+
+
+char a4[4], a8[8];
+
+void nowarn_nonmeber (void)
+{
+ /* The following would deserve a warning if A4 were known not to be
+ nul-terminated (or declared with attribute nonstring). */
+ strncpy (a8, a4, sizeof a8);
+}
+struct S
+{
+ char a4[4], a8[8];
+};
+
+void nowarn_member (struct S *p, struct S *q)
+{
+ /* The following would deserve a warning if A4 were known either
+ not to be nul-terminated (e.g., declared nonstring) or to be
+ uninitialized. */
+ strncpy (p->a8, p->a4, sizeof p->a8); // { dg-bogus "\\\[-Warray-bounds" }
+}
void __attribute__ ((noclone, noinline))
test_arr_strcpy_2 (void)
{
- strcpy (b.a, &b.a[i]);
+ strcpy (b.a, &b.a[i]); /* { dg-warning "\\\[-Wrestrict" } */
}
void test_strncpy_warn (char *d)
{
- strncpy (d + 1, d + 3, 5); /* { dg-warning "accessing 5 bytes at offsets 1 and 3 overlaps 2 bytes at offset 3" } */
+ strncpy (d + 1, d + 3, 5); /* { dg-warning "accessing 5 bytes at offsets 1 and 3 overlaps between 1 and 2 bytes at offset 3" } */
}
void test_strncpy_nowarn (char *d)
ptrdiff_t i = UR (2, DIFF_MAX + (size_t)2);
- strcpy (d, d + i); /* { dg-warning "accessing between 0 and 4 bytes at offsets 0 and \\\[2, 7] may overlap up to 2 bytes at offset 2" } */
+ strcpy (d, d + i); /* { dg-warning "accessing between 1 and 4 bytes at offsets 0 and \\\[2, 7] may overlap up to 2 bytes at offset \\\[2, 3]" } */
sink (d);
}
size_t i = UR (2, DIFF_MAX + (size_t)2);
- strcpy (d, d + i); /* { dg-warning "accessing between 0 and 4 bytes at offsets 0 and \\\[2, 7] may overlap up to 2 bytes at offset 2" } */
+ strcpy (d, d + i); /* { dg-warning "accessing between 1 and 4 bytes at offsets 0 and \\\[2, 7] may overlap up to 2 bytes at offset \\\[2, 3]" } */
sink (d);
}