PR middle-end/94647 - bogus -Warray-bounds on strncpy into a larger member array...
authorMartin Sebor <msebor@redhat.com>
Tue, 21 Apr 2020 16:59:24 +0000 (10:59 -0600)
committerMartin Sebor <msebor@redhat.com>
Tue, 21 Apr 2020 17:11:06 +0000 (11:11 -0600)
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.

gcc/ChangeLog
gcc/gimple-ssa-warn-restrict.c
gcc/testsuite/ChangeLog
gcc/testsuite/c-c++-common/Warray-bounds-2.c
gcc/testsuite/c-c++-common/Warray-bounds-3.c
gcc/testsuite/c-c++-common/Wrestrict.c
gcc/testsuite/gcc.dg/Warray-bounds-59.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/Wrestrict-10.c
gcc/testsuite/gcc.dg/Wrestrict-5.c
gcc/testsuite/gcc.dg/Wrestrict-6.c

index 8595d0e..6e226cc 100644 (file)
@@ -1,3 +1,11 @@
+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.
index a6a9635..19d2ec0 100644 (file)
@@ -831,8 +831,8 @@ builtin_access::builtin_access (gimple *call, builtin_memref &dst,
     }
   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];
 
@@ -842,15 +842,11 @@ builtin_access::builtin_access (gimple *call, builtin_memref &dst,
            {
              /* 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
@@ -859,7 +855,7 @@ builtin_access::builtin_access (gimple *call, builtin_memref &dst,
              && 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)
            {
@@ -1060,16 +1056,8 @@ builtin_access::generic_overlap ()
   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.  */
@@ -1102,11 +1090,9 @@ builtin_access::generic_overlap ()
     }
   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)
@@ -1119,15 +1105,6 @@ builtin_access::generic_overlap ()
            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]
                  };
@@ -1154,8 +1131,9 @@ builtin_access::generic_overlap ()
   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;
 }
index 0c10340..bd19696 100644 (file)
@@ -1,3 +1,14 @@
+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
index 7f925c3..8c6e0a6 100644 (file)
@@ -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);
index ab84c60..aae4999 100644 (file)
@@ -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" } */
index 1903f50..eb074a1 100644 (file)
@@ -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" } */
 
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-59.c b/gcc/testsuite/gcc.dg/Warray-bounds-59.c
new file mode 100644 (file)
index 0000000..99b18fc
--- /dev/null
@@ -0,0 +1,30 @@
+/* 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" }
+}
index 8bdabdb..7dcbf89 100644 (file)
@@ -63,7 +63,7 @@ test_arr_strcpy_1 (void)
 void __attribute__ ((noclone, noinline))
 test_arr_strcpy_2 (void)
 {
-  strcpy (b.a, &b.a[i]);
+  strcpy (b.a, &b.a[i]);            /* { dg-warning "\\\[-Wrestrict" } */
 }
 
 
index 513b426..21e1901 100644 (file)
@@ -26,7 +26,7 @@ void test_memcpy_nowarn (char *d)
 
 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)
index cc7185f..d1ef1a3 100644 (file)
@@ -21,7 +21,7 @@ void warn_2_smax_p2 (void)
 
   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);
 }
@@ -47,7 +47,7 @@ void warn_2u_smax_p2 (void)
 
   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);
 }