(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.dg/
Wstringop-overflow.c
       1  /* PR middle-end/77608 - missing protection on trivially detectable runtime
       2     buffer overflow
       3     { dg-do compile }
       4     { dg-options "-O2 -Wstringop-overflow -ftrack-macro-expansion=0" }  */
       5  
       6  #define SIZE_MAX   __SIZE_MAX__
       7  #define DIFF_MAX   __PTRDIFF_MAX__
       8  #define DIFF_MIN   (-DIFF_MAX - 1)
       9  
      10  typedef __SIZE_TYPE__ size_t;
      11  
      12  extern void* memcpy (void*, const void*, size_t);
      13  extern char* strcpy (char*, const char*);
      14  extern char* strncpy (char*, const char*, size_t);
      15  
      16  void sink (void*);
      17  
      18  static size_t unsigned_value (void)
      19  {
      20    extern volatile size_t unsigned_value_source;
      21    return unsigned_value_source;
      22  }
      23  
      24  static size_t unsigned_range (size_t min, size_t max)
      25  {
      26    size_t val = unsigned_value ();
      27    return val < min || max < val ? min : val;
      28  }
      29  
      30  #define UR(min, max) unsigned_range (min, max)
      31  
      32  
      33  char a7[7];
      34  
      35  struct MemArray { char a9[9]; char a1[1]; };
      36  
      37  void test_memcpy_array (const void *s)
      38  {
      39  #define T(d, s, n) (memcpy ((d), (s), (n)), sink (d))
      40  
      41    T (a7 + UR (0, 1), s, 7);
      42    T (a7 + UR (0, 7), s, 7);
      43    T (a7 + UR (0, 8), s, 7);
      44    T (a7 + UR (0, DIFF_MAX), s, 7);
      45    T (a7 + UR (0, SIZE_MAX), s, 7);
      46  
      47    T (a7 + UR (1, 2), s, 7);   /* { dg-warning "writing 7 bytes into a region of size 6" } */
      48    T (a7 + UR (2, 3), s, 7);   /* { dg-warning "writing 7 bytes into a region of size 5" } */
      49    T (a7 + UR (6, 9), s, 7);   /* { dg-warning "writing 7 bytes into a region of size 1" } */
      50    T (a7 + UR (7, 9), s, 7);   /* { dg-warning "writing 7 bytes into a region of size 0" } */
      51    T (a7 + UR (8, 9), s, 7);   /* { dg-warning "writing 7 bytes into a region of size 0" } */
      52  
      53    T (a7 + UR (9, 10), s, 7);  /* { dg-warning "writing 7 bytes into a region of size 0" } */
      54    T (a7 + UR (DIFF_MAX, DIFF_MAX + (size_t)1), s, 7);  /* { dg-warning "writing 7 bytes into a region of size 0" } */
      55    T (a7 + UR (DIFF_MAX, SIZE_MAX), s, 7);  /* { dg-warning "writing 7 bytes into a region of size 0" } */
      56  
      57    /* This is valid.  */
      58    char *d = a7 + 7;
      59    T (d + UR (-8, -7), s, 7);
      60  }
      61  
      62  /* Verify the absence of warnings for memcpy writing beyond object
      63     boundaries. */
      64  
      65  void test_memcpy_memarray (struct MemArray *p, const void *s)
      66  {
      67  #undef T
      68  #define T(d, s, n) (memcpy ((d), (s), (n)), sink (d))
      69  
      70    /* The following are valid.  */
      71    T (p->a9 + UR (0, 1), s, 9);
      72    T (p->a9 + UR (0, 7), s, 9);
      73    T (p->a9 + UR (0, 8), s, 9);
      74    T (p->a9 + UR (0, DIFF_MAX), s, 9);
      75    T (p->a9 + UR (0, SIZE_MAX), s, 9);
      76  
      77    /* The following are invalid.  Unfortunately, there is apparently enough
      78       code out there that abuses memcpy to write past the end of one member
      79       and into the members that follow so the following are not diagnosed
      80       by design.  It sure would be nice not to have to cater to hacks like
      81       these...  */
      82    T (p->a9 + UR (1, 2), s, 9);
      83    T (p->a9 + UR (1, 2), s, 123);
      84  }
      85  
      86  
      87  void test_strcpy_array (void)
      88  {
      89  #undef T
      90  #define T(d, s) (strcpy ((d), (s)), sink (d))
      91  
      92    T (a7 + UR (0, 1), "012345");
      93    T (a7 + UR (0, 7), "012345");
      94    T (a7 + UR (0, 8), "012345");
      95    T (a7 + UR (0, DIFF_MAX), "012345");
      96    T (a7 + UR (0, SIZE_MAX), "012345");
      97  
      98    T (a7 + UR (1, 2), "012345");   /* { dg-warning "writing 7 bytes into a region of size 6" } */
      99    T (a7 + UR (2, 3), "012345");   /* { dg-warning "writing 7 bytes into a region of size 5" } */
     100    T (a7 + UR (6, 9), "012345");   /* { dg-warning "writing 7 bytes into a region of size 1" } */
     101    T (a7 + UR (7, 9), "012345");   /* { dg-warning "writing 7 bytes into a region of size 0" } */
     102    T (a7 + UR (8, 9), "012345");   /* { dg-warning "writing 7 bytes into a region of size 0" } */
     103  
     104    T (a7 + UR (9, 10), "012345");  /* { dg-warning "writing 7 bytes into a region of size 0" } */
     105    T (a7 + UR (DIFF_MAX, DIFF_MAX + (size_t)1), "012345");  /* { dg-warning "writing 7 bytes into a region of size 0" } */
     106    T (a7 + UR (DIFF_MAX, SIZE_MAX), "012345");  /* { dg-warning "writing 7 bytes into a region of size 0" } */
     107  
     108    char *d = a7 + 7;
     109  
     110    T (d + UR (-8, -7), "012345");
     111  }
     112  
     113  void test_strncpy_memarray (struct MemArray *p, const void *s)
     114  {
     115  #undef T
     116  #define T(d, s, n) (strncpy ((d), (s), (n)), sink (d))
     117  
     118    T (p->a9 + UR (0, 1), s, 9);
     119    T (p->a9 + UR (0, 7), s, 9);
     120    T (p->a9 + UR (0, 8), s, 9);
     121    T (p->a9 + UR (0, DIFF_MAX), s, 9);
     122    T (p->a9 + UR (0, SIZE_MAX), s, 9);
     123  
     124    T (p->a9 + UR (1, 2), s, 9);    /* { dg-warning "writing 9 bytes into a region of size 8" } */
     125    T (p->a9 + UR (2, 3), s, 9);    /* { dg-warning "writing 9 bytes into a region of size 7" } */
     126    T (p->a9 + UR (6, 9), s, 9);    /* { dg-warning "writing 9 bytes into a region of size 3" } */
     127    T (p->a9 + UR (9, 10), s, 9);   /* { dg-warning "writing 9 bytes into a region of size 0" } */
     128    T (p->a9 + UR (10, 11), s, 9);  /* { dg-warning "writing 9 bytes into a region of size 0" } */
     129  
     130    T (p->a9 + UR (DIFF_MAX, DIFF_MAX + (size_t)1), s, 1);  /* { dg-warning "writing 1 byte into a region of size 0" } */
     131    T (p->a9 + UR (DIFF_MAX, SIZE_MAX), s, 3);  /* { dg-warning "writing 3 bytes into a region of size 0" } */
     132  }