https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97342

            Bug ID: 97342
           Summary: bogus -Wstringop-overflow with nonzero signed and
                    unsigned offsets
           Product: gcc
           Version: 11.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: middle-end
          Assignee: unassigned at gcc dot gnu.org
          Reporter: msebor at gcc dot gnu.org
  Target Milestone: ---

The combination of signed and unsigned offsets into an array of elements larger
than 1 triggers a false positive -Wstringop-overflow.

$ cat q.c && gcc -O2 -S q.c
void sink (void*, ...);

void f (unsigned i, int j)
{
  i |= 1;   // [1, UINT_MAX]
  j |= 1;   // [INT_MIN + 1, -1] U [1, INT_MAX]

  int a[5];            // index
  int *p1 = a + i;     //  1-5
  int *p2 = p1 + j;    //  0-5

  __builtin_memset (p2, 0, 5 * sizeof *a);

  sink (p1, p2);
}
q.c: In function ‘f’:
q.c:12:3: warning: ‘__builtin_memset’ writing 20 bytes into a region of size 16
overflows the destination [-Wstringop-overflow=]
   12 |   __builtin_memset (p2, 0, 5 * sizeof *a);
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
q.c:8:7: note: at offset [4, 17179869176] into destination object ‘a’
    8 |   int a[5];            // index
      |       ^

The optimized dump below suggests the "anti-range" the signed offset is in
isn't being handled correctly.

f (unsigned intD.9 iD.1932, intD.6 jD.1933)
{
  unsigned intD.9 i_5(D) = iD.1932;
  intD.6 j_7(D) = jD.1933;
  intD.6 * p2D.1938;
  intD.6 * p1D.1937;
  intD.6 aD.1936[5];
  long unsigned intD.10 _1;
  long unsigned intD.10 _2;
  long unsigned intD.10 _3;
  long unsigned intD.10 _4;

;;   basic block 2, loop depth 0, count 1073741824 (estimated locally), maybe
hot
;;    prev block 0, next block 1, flags: (NEW, REACHABLE, VISITED)
;;    pred:       ENTRY [always]  count:1073741824 (estimated locally)
(FALLTHRU,EXECUTABLE)
  # RANGE [1, 4294967295]
  i_6 = i_5(D) | 1;
  # RANGE [-2147483647, 2147483647]
  j_8 = j_7(D) | 1;
  # RANGE [1, 4294967295] NONZERO 4294967295
  _1 = (long unsigned intD.10) i_6;
  # RANGE [4, 17179869180] NONZERO 17179869180
  _2 = _1 * 4;
  # PT = { D.1936 } (escaped)
  # ALIGN = 4, MISALIGN = 0
  p1_9 = &aD.1936 + _2;
  # RANGE ~[2147483648, 18446744071562067968]
  _3 = (long unsigned intD.10) j_8;
  # RANGE [0, 18446744073709551612] NONZERO 18446744073709551612
  _4 = _3 * 4;
  # PT = { D.1936 } (escaped)
  # ALIGN = 4, MISALIGN = 0
  p2_10 = p1_9 + _4;
  # .MEM_12 = VDEF <.MEM_11(D)>
  # USE = nonlocal null { D.1936 } (escaped)
  # CLB = nonlocal null { D.1936 } (escaped)
  memsetD.894 (p2_10, 0, 20);

Reply via email to