(root)/
gcc-13.2.0/
gcc/
testsuite/
c-c++-common/
Warray-bounds-2.c
       1  /* Test to exercise that -Warray-bounds warnings for memory and string
       2     functions are issued even when they are declared in system headers
       3     (i.e., not just when they are explicitly declared in the source
       4     file.)
       5     Also verify that the warnings are issued even for calls where the
       6     source of the excessive array bound is in a different function than
       7     the call.
       8     { dg-do compile }
       9     { dg-options "-O2 -Warray-bounds -Wno-stringop-overflow -fno-tree-vrp" } */
      10  
      11  #if __has_include (<stddef.h>)
      12  #  include <stddef.h>
      13  #else
      14  /* For cross-compilers.  */
      15  typedef __PTRDIFF_TYPE__   ptrdiff_t;
      16  typedef __SIZE_TYPE__      size_t;
      17  #endif
      18  
      19  #if __has_include (<string.h>)
      20  #  include <string.h>
      21  #  undef memcpy
      22  #  undef strcat
      23  #  undef strcpy
      24  #  undef strncpy
      25  #else
      26  extern void* memcpy (void*, const void*, size_t);
      27  extern char* strcat (char*, const char*);
      28  extern char* strcpy (char*, const char*);
      29  extern char* strncpy (char*, const char*, size_t);
      30  #endif
      31  
      32  
      33  #define MAX  (__SIZE_MAX__ / 2)
      34  
      35  void sink (void*);
      36  
      37  struct __attribute__ ((packed)) Array
      38  {
      39    char a13[13];
      40    char a15[15];
      41    char a17[17];
      42  };
      43  
      44  /* Exercise memcpy out-of-bounds offsets with an array of known size.  */
      45  
      46  static void
      47  wrap_memcpy_src_xsize (char *d, const char *s, ptrdiff_t i, size_t n)
      48  {
      49    memcpy (d, s + i, n);   /* { dg-warning "offset 46 is out of the bounds \\\[0, 45] of object .ar. with type .(struct )?Array." "memcpy" } */
      50  }
      51  
      52  void call_memcpy_src_xsize (char *d, size_t n)
      53  {
      54    struct Array ar;
      55    sink (&ar);
      56    wrap_memcpy_src_xsize (d, ar.a13, 46, n);
      57    sink (&ar);
      58  }
      59  
      60  /* Exercise memcpy out-of-bounds offsets with an array of unknown size.  */
      61  
      62  static void
      63  wrap_memcpy_src_diff_max (char *d, const char *s, ptrdiff_t i, size_t n)
      64  {
      65    memcpy (d, s + i, n);   /* { dg-warning "pointer overflow between offset \[0-9\]+ and size 3" "memcpy" } */
      66  }
      67  
      68  void call_memcpy_src_diff_max (char *d, const char *s, size_t n)
      69  {
      70    wrap_memcpy_src_diff_max (d, s, MAX, 3);
      71  }
      72  
      73  static void
      74  wrap_memcpy_dst_xsize (char *d, const char *s, ptrdiff_t i, size_t n)
      75  {
      76    memcpy (d + i, s, n);   /* { dg-warning "offset 47 is out of the bounds \\\[0, 45] of object .ar1. with type .(struct )?Array." "memcpy" } */
      77  }
      78  
      79  void call_memcpy_dst_xsize (const char *s, size_t n)
      80  {
      81    struct Array ar1;       /* { dg-message ".ar1. declared here" } */
      82    sink (&ar1);
      83    wrap_memcpy_dst_xsize (ar1.a15, s, 34, n);
      84    sink (&ar1);
      85  }
      86  
      87  static void
      88  wrap_memcpy_dst_diff_max (char *d, const char *s, ptrdiff_t i, size_t n)
      89  {
      90    memcpy (d + i, s, n);   /* { dg-warning "offset -?\[0-9\]+ is out of the bounds \\\[0, 45] of object .ar2. with type .(struct )?Array." "memcpy" } */
      91  }
      92  
      93  void call_memcpy_dst_diff_max (const char *s, size_t n)
      94  {
      95    struct Array ar2;       /* { dg-message ".ar2. declared here" } */
      96    sink (&ar2);
      97    wrap_memcpy_dst_diff_max (ar2.a15, s, MAX, n);
      98    sink (&ar2);
      99  }
     100  
     101  
     102  static void wrap_strcat_src_xsize (char *d, const char *s, ptrdiff_t i)
     103  {
     104    strcat (d, s + i);   /* { dg-warning "offset 46 is out of the bounds \\\[0, 45] of object .ar3. with type .(struct )?Array." "strcat" } */
     105  }
     106  
     107  void call_strcat_src_xsize (char *d)
     108  {
     109    struct Array ar3;       /* { dg-message ".ar3. declared here" } */
     110    sink (&ar3);
     111    wrap_strcat_src_xsize (d, ar3.a15, 15 + 17 + 1);
     112    sink (&ar3);
     113  }
     114  
     115  static void wrap_strcat_dst_xsize (char *d, const char *s, ptrdiff_t i)
     116  {
     117    strcat (d + i, s);   /* { dg-warning "offset 47 is out of the bounds \\\[0, 45] of object .ar4. with type .(struct )?Array." "strcat" } */
     118  }
     119  
     120  void call_strcat_dst_xsize (const char *s)
     121  {
     122    struct Array ar4;       /* { dg-message ".ar4. declared here" } */
     123    sink (&ar4);
     124    wrap_strcat_dst_xsize (ar4.a15, s, 15 + 17 + 2);
     125    sink (&ar4);
     126  }
     127  
     128  
     129  static void wrap_strcpy_src_xsize (char *d, const char *s, ptrdiff_t i)
     130  {
     131    strcpy (d, s + i);   /* { dg-warning "offset 48 is out of the bounds \\\[0, 45] of object .ar5. with type .(struct )?Array." "strcpy" } */
     132  }
     133  
     134  void call_strcpy_src_xsize (char *d)
     135  {
     136    struct Array ar5;       /* { dg-message ".ar5. declared here" } */
     137    sink (&ar5);
     138    wrap_strcpy_src_xsize (d, ar5.a15, 15 + 17 + 3);
     139    sink (&ar5);
     140  }
     141  
     142  static void wrap_strcpy_dst_xsize (char *d, const char *s, ptrdiff_t i)
     143  {
     144    strcpy (d + i, s);   /* { dg-warning "offset 49 is out of the bounds \\\[0, 45] of object .ar6. with type .(struct )?Array." "strcpy" } */
     145  }
     146  
     147  void call_strcpy_dst_xsize (const char *s)
     148  {
     149    struct Array ar6;       /* { dg-message ".ar6. declared here" } */
     150    sink (&ar6);
     151    wrap_strcpy_dst_xsize (ar6.a15, s, 15 + 17 + 4);
     152    sink (&ar6);
     153  }
     154  
     155  
     156  /* Exercise strncpy out-of-bounds offsets with an array of known size.  */
     157  
     158  static void
     159  wrap_strncpy_src_xsize (char *d, const char *s, ptrdiff_t i, size_t n)
     160  {
     161    strncpy (d, s + i, n);   /* { dg-warning "offset 46 is out of the bounds \\\[0, 45] of object .ar7. with type '(struct )?Array." "strncpy" } */
     162  }
     163  
     164  void call_strncpy_src_xsize (char *d, size_t n)
     165  {
     166    struct Array ar7;       /* { dg-message ".ar7. declared here" } */
     167    sink (&ar7);
     168    wrap_strncpy_src_xsize (d, ar7.a17, 17 + 1, n);
     169    sink (&ar7);
     170  }
     171  
     172  /* Exercise strncpy out-of-bounds offsets with an array of unknown size.  */
     173  
     174  static void
     175  wrap_strncpy_src_diff_max_m1 (char *d, const char *s, ptrdiff_t i, size_t n)
     176  {
     177    /* Unlike in the similar call to memcpy(), there is no pointer
     178       overflow here because the size N is not added to the source
     179       offset MAX - 1 (only 1 is for the access to its first element,
     180       which is tested below).  */
     181    strncpy (d, s + i, n);
     182  }
     183  
     184  void call_strncpy_src_diff_max_m1 (char *d, const char *s, size_t n)
     185  {
     186    wrap_strncpy_src_diff_max_m1 (d, s, MAX - 1, 3);
     187  }
     188  
     189  static void
     190  wrap_strncpy_src_diff_max (char *d, const char *s, ptrdiff_t i, size_t n)
     191  {
     192    strncpy (d, s + i, n);  /* { dg-warning "pointer overflow between offset \[0-9\]+ and size \\\[1, 0]" } */
     193  }
     194  
     195  void call_strncpy_src_diff_max (char *d, const char *s, size_t n)
     196  {
     197    wrap_strncpy_src_diff_max (d, s, MAX, 3);
     198  }
     199  
     200  static void
     201  wrap_strncpy_dst_xsize (char *d, const char *s, ptrdiff_t i, size_t n)
     202  {
     203    strncpy (d + i, s, n);   /* { dg-warning "offset 47 is out of the bounds \\\[0, 45] of object .ar8. with type .(struct )?Array." "strncpy" } */
     204  }
     205  
     206  void call_strncpy_dst_xsize (const char *s, size_t n)
     207  {
     208    struct Array ar8;       /* { dg-message ".ar8. declared here" } */
     209    sink (&ar8);
     210    wrap_strncpy_dst_xsize (ar8.a17, s, 17 + 2, n);
     211    sink (&ar8);
     212  }
     213  
     214  static void
     215  wrap_strncpy_dst_diff_max (char *d, const char *s, ptrdiff_t i, size_t n)
     216  {
     217    strncpy (d + i, s, n);   /* { dg-warning "offset -\[0-9\]+ is out of the bounds \\\[0, 45] of object .ar9. with type .(struct )?Array." "strncpy" } */
     218  }
     219  
     220  void call_strncpy_dst_diff_max (const char *s, size_t n)
     221  {
     222    struct Array ar9;       /* { dg-message ".ar9. declared here" "strncpy" } */
     223    sink (&ar9);
     224    wrap_strncpy_dst_diff_max (ar9.a17, s, MAX, n);
     225    sink (&ar9);
     226  }
     227  
     228  static void
     229  wrap_strncpy_dstarray_diff_neg (char *d, const char *s, ptrdiff_t i, size_t n)
     230  {
     231    strncpy (d + i, s, n);   /* { dg-warning "offset -\[0-9\]+ is out of the bounds \\\[0, 90] of object .ar10. with type .(struct )?Array ?\\\[2]." "strncpy" } */
     232  }
     233  
     234  void call_strncpy_dstarray_diff_neg (const char *s, size_t n)
     235  {
     236    struct Array ar10[2];    /* { dg-message ".ar10. declared here" } */
     237    sink (&ar10);
     238  
     239    int off = (char*)ar10[1].a17 - (char*)ar10 + 1;
     240    wrap_strncpy_dstarray_diff_neg (ar10[1].a17, s, -off, n);
     241  
     242    sink (&ar10);
     243  }