1  /* PR 96903 - bogus warning on memcpy at negative offset from array end
       2     { dg-do compile }
       3     { dg-options "-O2 -Wall -Wno-array-bounds -ftrack-macro-expansion=0" } */
       4  
       5  #include "range.h"
       6  
       7  #define INT_MAX    __INT_MAX__
       8  #define INT_MIN    -(INT_MAX - 1)
       9  #define UINT_MAX   (2U * INT_MAX + 1)
      10  
      11  typedef __SIZE_TYPE__ size_t;
      12  
      13  void* memset (void *, int, size_t);
      14  
      15  void sink (void*, ...);
      16  
      17  extern char a11[11];
      18  struct S { char a11[11], b; };
      19  extern struct S sa11;
      20  
      21  #define T2(dst, off1, off2, n) do {		\
      22      char *_p0 = dst;				\
      23      char *_p1 = _p0 + (off1);			\
      24      char *_p2 = _p1 + (off2);			\
      25      memset (_p2, 0, n);				\
      26      sink (dst, _p0, _p1, _p2);			\
      27    } while (0);
      28  
      29  #define T1(dst, off, n) T2 (dst, off, 0, n)
      30  
      31  
      32  void nowarn_memset_array_cst (void)
      33  {
      34    char *p = &a11[11];
      35  
      36    T1 (p, -11, 11);
      37    T1 (p, -10, 10);
      38    T1 (p,  -9,  9);
      39    T1 (p,  -8,  8);
      40    T1 (p,  -3,  3);
      41    T1 (p,  -2,  2);
      42    T1 (p,  -1,  1);
      43    T1 (p,   0,  0);
      44  
      45    T2 (p, -6, -5, 11);
      46    T2 (p, -6, -4, 10);
      47    T2 (p, -6, -3,  9);
      48    T2 (p, -6, -2,  8);
      49    T2 (p, -6, -1,  7);
      50    T2 (p, -5, -6, 11);
      51    T2 (p, -5, -5, 10);
      52  }
      53  
      54  void nowarn_memset_array_rng_int (void)
      55  {
      56    char *p = &a11[11];
      57  
      58    int i11 = SR (11, INT_MAX);
      59    int i10 = SR (10, INT_MAX);
      60    int i9  = SR ( 9, INT_MAX);
      61    int i3  = SR ( 3, INT_MAX);
      62    int i2  = SR ( 2, INT_MAX);
      63    int i1  = SR ( 1, INT_MAX);
      64    int i0  = SR ( 0, INT_MAX);
      65  
      66    int m11 = SR (INT_MIN, -11);
      67    int m10 = SR (INT_MIN, -10);
      68    int m9  = SR (INT_MIN,  -9);
      69    int m3  = SR (INT_MIN,  -3);
      70    int m2  = SR (INT_MIN,  -2);
      71    int m1  = SR (INT_MIN,  -1);
      72    int m0  = SR (INT_MIN,  -0);
      73  
      74    T1 (p, m11, i11);
      75    T1 (p, m10, i10);
      76    T1 (p,  m9,  i9);
      77    T1 (p,  m3,  i3);
      78    T1 (p,  m2,  i2);
      79    T1 (p,  m1,  i1);
      80    T1 (p,  m0,  i0);
      81  
      82    T1 (p, m11, i11);
      83    T1 (p, m10, i10);
      84    T1 (p,  m9,  i9);
      85    T1 (p,  m3,  i3);
      86    T1 (p,  m2,  i2);
      87    T1 (p,  m1,  i1);
      88    T1 (p,  m0,  i0);
      89  }
      90  
      91  
      92  void nowarn_memset_array_rng (void)
      93  {
      94    char *p = &a11[11];
      95  
      96    T2 (p, SR (-11, -10), SR ( -2,  -1), UR (11, 12));
      97    T2 (p, SR (-10,  -9), SR ( -1,   0), UR (11, 13));
      98    T2 (p, SR ( -9,  -8), SR ( -2,  -1), UR (11, 14));
      99    T2 (p, SR ( -8,  -7), SR ( -3,  -2), UR (11, 15));
     100    T2 (p, SR ( -7,  -6), SR ( -4,  -3), UR (11, 16));
     101    T2 (p, SR ( -6,  -5), SR ( -5,  -4), UR (11, 17));
     102    T2 (p, SR ( -5,  -4), SR ( -6,  -5), UR (11, 18));
     103    T2 (p, SR ( -4,  -3), SR ( -7,  -6), UR (11, 19));
     104    T2 (p, SR ( -3,  -2), SR ( -8,  -7), UR (11, INT_MAX));
     105    T2 (p, SR ( -2,  -1), SR ( -9,  -8), UR (11, UINT_MAX));
     106    T2 (p, SR ( -1,   0), SR (-10,  -9), UR (11, DIFF_MAX));
     107    T2 (p, SR (  0,   1), SR (-11, -10), UR (11, SIZE_MAX));
     108  
     109    T2 (p, SR (DIFF_MIN, -10), SR (DIFF_MIN, -1), UR (10, 12));
     110  
     111    T2 (p, SR (-11, -10), SR ( -3,  -1), UR (10, 12))
     112    T2 (p, SR (-11, -10), SR ( -3,  -1), UR (10, 12))
     113  }
     114  
     115  
     116  void warn_memset_array_rng (void)
     117  {
     118    char *p = &a11[11];
     119    size_t n11_12 = UR (11, 12);
     120    size_t n10_12 = UR (10, 12);
     121  
     122    T2 (p, SR (-11, -10), SR ( -3,  -2), n11_12);    // { dg-warning "writing between 11 and 12 bytes into a region of size 0" }
     123    T2 (p, SR (-11, -10), SR ( -3,  -2), n10_12);    // { dg-warning "writing between 10 and 12 bytes into a region of size 0" }
     124  }
     125  
     126  
     127  void nowarn_memset_anti_range (void)
     128  {
     129    size_t n11 = UR (11, SIZE_MAX);
     130  
     131    char *p = &a11[11];
     132  
     133    T1 (p, (int)SAR (INT_MIN,      -12), n11);
     134    T1 (p, (int)SAR (    -13,      -13), n11);
     135    T1 (p, (int)SAR (    -13,      -12), n11);
     136    T1 (p, (int)SAR (    -10,        1), n11);
     137    T1 (p, (int)SAR (    -10,       11), n11);
     138    T1 (p, (int)SAR (    -10,  INT_MAX), n11);
     139    T1 (p, (int)SAR (     -1,       -1), n11);
     140    T1 (p, (int)SAR (     -1,        0), n11);
     141    T1 (p, (int)SAR (     -1,       11), n11);
     142    T1 (p, (int)SAR (     -1,  INT_MAX), n11);
     143  
     144    T1 (p, SAR (DIFF_MIN,       -12), n11);
     145    T1 (p, SAR (     -13,       -13), n11);
     146    T1 (p, SAR (     -13,       -12), n11);
     147    T1 (p, SAR (     -10,         1), n11);   // { dg-bogus "-Wstringop-overflow" }
     148    T1 (p, SAR (     -10,        11), n11);   // { dg-bogus "-Wstringop-overflow" }
     149    T1 (p, SAR (     -10,  DIFF_MAX), n11);
     150    T1 (p, SAR (     -1,         -1), n11);   // { dg-bogus "-Wstringop-overflow" }
     151    T1 (p, SAR (     -1,          0), n11);   // { dg-bogus "-Wstringop-overflow" }
     152    T1 (p, SAR (     -1,         11), n11);   // { dg-bogus "-Wstringop-overflow" }
     153    T1 (p, SAR (     -1,   DIFF_MAX), n11);
     154  }
     155  
     156  void warn_memset_reversed_range (void)
     157  {
     158    size_t n11 = UR (11, SIZE_MAX);
     159  
     160    char *p = &a11[11];
     161  
     162    /* Since the offset is excessive, either starting before &a11[0]
     163       ot just past &a[11], the region size in the warning should
     164       probably be zero, but accept other sizes too.
     165  
     166       The problem isn't detected anymore because the offset is in
     167       the anti-range ~[INT_MIN, -11] which isn't handled.  */
     168    T1 (p, SAR (INT_MIN, -11), n11);      // { dg-warning "writing 11 or more bytes into a region of size \\d+" "" { xfail *-*-* } }
     169  
     170    /* The following are represented as ordinary ranges with reversed bounds
     171       and those are handled. */
     172    T1 (p, SAR (INT_MIN,  11), n11);      // { dg-warning "writing 11 or more bytes into a region of size 0" }
     173    T1 (p, SAR (INT_MIN,   1), n11);      // { dg-warning "writing 11 or more bytes into a region of size 0" }
     174    T1 (p, SAR (INT_MIN,   0), n11);      // { dg-warning "writing 11 or more bytes into a region of size 0" }
     175    /* Also represented as a true anti-range.  */
     176    T1 (p, SAR (    -12, -11), n11);      // { dg-warning "writing 11 or more bytes into a region of size \\d+" "" { xfail *-*-* } }
     177    T1 (p, SAR (    -12,  -1), n11);      // { dg-warning "writing 11 or more bytes into a region of size 0" }
     178    T1 (p, SAR (    -11,   0), n11);      // { dg-warning "writing 11 or more bytes into a region of size 0" }
     179    T1 (p, SAR (    -11,  11), n11);      // { dg-warning "writing 11 or more bytes into a region of size 0" }
     180  }