(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.dg/
Warray-bounds-45.c
       1  /* PR middle-end/91631 - buffer overflow into an array member of a declared
       2     object not detected
       3     Test to verify that past-the-end accesses by string functions to member
       4     arrays by-reference objects are diagnosed.
       5     { dg-do compile }
       6     { dg-options "-O2 -Wall -Wno-unused-local-typedefs -ftrack-macro-expansion=0" }  */
       7  
       8  extern char* strcpy (char*, const char*);
       9  extern char* strcat (char*, const char*);
      10  
      11  void sink (void*, ...);
      12  
      13  #define S36 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
      14  
      15  #define S(N)   (S36 + sizeof (S36) - N - 1)
      16  
      17  /* In the test macro, prevent the strcpy to memcpy transformation
      18     by using a local array initialized with the string literal.  Without
      19     it, GCC transforms the strcpy call with memcpy which (unfortunately)
      20     permits accesses that cross subobject boundaries.  */
      21  #define T(dst, ncpy, ncat)			\
      22    do {						\
      23      const char a[] = S36;			\
      24      strcpy (dst, a + sizeof a - ncpy - 1);	\
      25      const char b[] = S36;			\
      26      strcat (dst, b + sizeof b - ncat - 1);	\
      27      sink (dst);					\
      28    } while (0)
      29  
      30  
      31  struct MemArrays
      32  {
      33    char a7[7];             // { dg-message "'a7' declared here" }
      34    char a4[4];             // { dg-message "'a4' declared here" }
      35    char a3[3];             // { dg-message "'a3' declared here" }
      36  };
      37  
      38  struct MemArrays gma;
      39  
      40  void strcat_value (void)
      41  {
      42    T (gma.a7, 1, 1);
      43    T (gma.a7, 1, 5);
      44    T (gma.a7, 1, 6);       // { dg-warning "'strcat' offset 7 from the object at 'gma' is out of the bounds of referenced subobject 'a7' with type 'char\\\[7]' at offset 0" }
      45    T (gma.a7, 1, 7);       // { dg-warning "'strcat' offset \\\[7, 8] from the object at 'gma' is out of the bounds of referenced subobject 'a7' with type 'char\\\[7]' at offset 0" }
      46  
      47    T (gma.a7, 2, 1);
      48    T (gma.a7, 2, 4);
      49    T (gma.a7, 2, 5);       // { dg-warning "'strcat' offset 7 from the object at 'gma' is out of the bounds of referenced subobject 'a7' with type 'char\\\[7]' at offset 0" }
      50    T (gma.a7, 2, 6);       // { dg-warning "'strcat' offset \\\[7, 8] from the object at 'gma' is out of the bounds of referenced subobject 'a7' with type 'char\\\[7]' at offset 0" }
      51  
      52    T (gma.a7, 5, 1);
      53    T (gma.a7, 5, 2);       // { dg-warning "'strcat' offset 7 from the object at 'gma' is out of the bounds of referenced subobject 'a7' with type 'char\\\[7]' at offset 0" }
      54  
      55    T (gma.a4, 1, 1);
      56    T (gma.a4, 1, 2);
      57    T (gma.a4, 1, 3);       // { dg-warning "'strcat' offset 11 from the object at 'gma' is out of the bounds of referenced subobject 'a4' with type 'char\\\[4]' at offset 7" }
      58     T (gma.a4, 1, 4);       // { dg-warning "'strcat' offset \\\[11, 12] from the object at 'gma' is out of the bounds of referenced subobject 'a4' with type 'char\\\[4]' at offset 7" }
      59  
      60    T (gma.a4, 2, 3);       // { dg-warning "'strcat' offset \\\[11, 12] from the object at 'gma' is out of the bounds of referenced subobject 'a4' with type 'char\\\[4]' at offset 7" }
      61  
      62    T (gma.a3, 1, 1);
      63    T (gma.a3, 1, 2);       // { dg-warning "'strcat' offset 14 from the object at 'gma' is out of the bounds of referenced subobject 'a3' with type 'char\\\[3]' at offset 11" }
      64  }
      65  
      66  
      67  void strcat_ref (struct MemArrays *pma)
      68  {
      69    T (pma->a7, 1, 1);
      70    T (pma->a7, 1, 5);
      71    T (pma->a7, 1, 6);      // { dg-warning "'strcat' offset 7 from the object at 'pma' is out of the bounds of referenced subobject 'a7' with type 'char\\\[7]' at offset 0" }
      72    T (pma->a7, 1, 7);      // { dg-warning "'strcat' offset \\\[7, 8] from the object at 'pma' is out of the bounds of referenced subobject 'a7' with type 'char\\\[7]' at offset 0" }
      73  
      74    T (pma->a7, 2, 1);
      75    T (pma->a7, 2, 4);
      76    T (pma->a7, 2, 5);      // { dg-warning "'strcat' offset 7 from the object at 'pma' is out of the bounds of referenced subobject 'a7' with type 'char\\\[7]' at offset 0" }
      77    T (pma->a7, 2, 6);      // { dg-warning "'strcat' offset \\\[7, 8] from the object at 'pma' is out of the bounds of referenced subobject 'a7' with type 'char\\\[7]' at offset 0" }
      78  
      79    T (pma->a4, 1, 1);
      80    T (pma->a4, 1, 2);
      81    T (pma->a4, 1, 3);      // { dg-warning "'strcat' offset 11 from the object at 'pma' is out of the bounds of referenced subobject 'a4' with type 'char\\\[4]' at offset 7" }
      82     T (pma->a4, 1, 4);      // { dg-warning "'strcat' offset \\\[11, 12] from the object at 'pma' is out of the bounds of referenced subobject 'a4' with type 'char\\\[4]' at offset 7" }
      83  
      84    T (pma->a4, 2, 3);      // { dg-warning "'strcat' offset \\\[11, 12] from the object at 'pma' is out of the bounds of referenced subobject 'a4' with type 'char\\\[4]' at offset 7" }
      85  
      86    T (pma->a3, 1, 1);
      87    T (pma->a3, 1, 2);      // { dg-warning "'strcat' offset 14 from the object at 'pma' is out of the bounds of referenced subobject 'a3' with type 'char\\\[3]' at offset 11" }
      88  }
      89  
      90  
      91  #define T2(dst1, dst2, ncpy, ncat)		\
      92    do {						\
      93      const char a[] = S36;			\
      94      strcpy (dst1, a + sizeof a - ncpy - 1);	\
      95      const char b[] = S36;			\
      96      strcat (dst2, b + sizeof b - ncat - 1);	\
      97      sink (dst1, dst2);				\
      98    } while (0)
      99  
     100  struct ArraysOfMemArrays
     101  {
     102    struct MemArrays ma3[3];
     103  } a3[3];
     104  
     105  void strcat_arrays_of_arrays_value (void)
     106  {
     107    T2 (a3[0].ma3[0].a7, a3[0].ma3[0].a7, 6, 6);   // { dg-warning "\\\[-Warray-bounds" }
     108    T2 (a3[0].ma3[0].a7, a3[0].ma3[1].a7, 6, 6);
     109    T2 (a3[0].ma3[0].a7, a3[0].ma3[2].a7, 6, 6);
     110  
     111    T2 (a3[0].ma3[1].a7, a3[0].ma3[0].a7, 6, 6);
     112    T2 (a3[0].ma3[1].a7, a3[0].ma3[1].a7, 6, 6);   // { dg-warning "\\\[-Warray-bounds" }
     113    T2 (a3[0].ma3[1].a7, a3[0].ma3[2].a7, 6, 6);
     114  
     115    T2 (a3[0].ma3[2].a7, a3[0].ma3[0].a7, 6, 6);
     116    T2 (a3[0].ma3[2].a7, a3[0].ma3[1].a7, 6, 6);
     117    T2 (a3[0].ma3[2].a7, a3[0].ma3[2].a7, 6, 6);   // { dg-warning "\\\[-Warray-bounds" }
     118  
     119    T2 (a3[0].ma3[0].a7, a3[1].ma3[0].a7, 6, 6);
     120    T2 (a3[0].ma3[0].a7, a3[1].ma3[1].a7, 6, 6);
     121    T2 (a3[0].ma3[0].a7, a3[1].ma3[2].a7, 6, 6);
     122  
     123    T2 (a3[0].ma3[1].a7, a3[1].ma3[0].a7, 6, 6);
     124    T2 (a3[0].ma3[1].a7, a3[1].ma3[1].a7, 6, 6);
     125    T2 (a3[0].ma3[1].a7, a3[1].ma3[2].a7, 6, 6);
     126  
     127    T2 (a3[0].ma3[2].a7, a3[1].ma3[0].a7, 6, 6);
     128    T2 (a3[0].ma3[2].a7, a3[1].ma3[1].a7, 6, 6);
     129    T2 (a3[0].ma3[2].a7, a3[1].ma3[2].a7, 6, 6);
     130  
     131    T2 (a3[0].ma3[0].a7, a3[2].ma3[0].a7, 6, 6);
     132    T2 (a3[0].ma3[0].a7, a3[2].ma3[1].a7, 6, 6);
     133    T2 (a3[0].ma3[0].a7, a3[2].ma3[2].a7, 6, 6);
     134  
     135    T2 (a3[0].ma3[1].a7, a3[2].ma3[0].a7, 6, 6);
     136    T2 (a3[0].ma3[1].a7, a3[2].ma3[1].a7, 6, 6);
     137    T2 (a3[0].ma3[1].a7, a3[2].ma3[2].a7, 6, 6);
     138  
     139    T2 (a3[0].ma3[2].a7, a3[2].ma3[0].a7, 6, 6);
     140    T2 (a3[0].ma3[2].a7, a3[2].ma3[1].a7, 6, 6);
     141    T2 (a3[0].ma3[2].a7, a3[2].ma3[2].a7, 6, 6);
     142  
     143  
     144    T2 (a3[1].ma3[0].a7, a3[0].ma3[0].a7, 6, 6);
     145    T2 (a3[1].ma3[0].a7, a3[0].ma3[1].a7, 6, 6);
     146    T2 (a3[1].ma3[0].a7, a3[0].ma3[2].a7, 6, 6);
     147  
     148    T2 (a3[1].ma3[1].a7, a3[0].ma3[0].a7, 6, 6);
     149    T2 (a3[1].ma3[1].a7, a3[0].ma3[1].a7, 6, 6);
     150    T2 (a3[1].ma3[1].a7, a3[0].ma3[2].a7, 6, 6);
     151  
     152    T2 (a3[1].ma3[2].a7, a3[0].ma3[0].a7, 6, 6);
     153    T2 (a3[1].ma3[2].a7, a3[0].ma3[1].a7, 6, 6);
     154    T2 (a3[1].ma3[2].a7, a3[0].ma3[2].a7, 6, 6);
     155  
     156    T2 (a3[1].ma3[0].a7, a3[1].ma3[0].a7, 6, 6);   // { dg-warning "\\\[-Warray-bounds" }
     157    T2 (a3[1].ma3[0].a7, a3[1].ma3[1].a7, 6, 6);
     158    T2 (a3[1].ma3[0].a7, a3[1].ma3[2].a7, 6, 6);
     159  
     160    T2 (a3[1].ma3[1].a7, a3[1].ma3[0].a7, 6, 6);
     161    T2 (a3[1].ma3[1].a7, a3[1].ma3[1].a7, 6, 6);   // { dg-warning "\\\[-Warray-bounds" }
     162    T2 (a3[1].ma3[1].a7, a3[1].ma3[2].a7, 6, 6);
     163  
     164    T2 (a3[1].ma3[2].a7, a3[1].ma3[0].a7, 6, 6);
     165    T2 (a3[1].ma3[2].a7, a3[1].ma3[1].a7, 6, 6);
     166    T2 (a3[1].ma3[2].a7, a3[1].ma3[2].a7, 6, 6);   // { dg-warning "\\\[-Warray-bounds" }
     167  
     168    T2 (a3[1].ma3[0].a7, a3[2].ma3[0].a7, 6, 6);
     169    T2 (a3[1].ma3[0].a7, a3[2].ma3[1].a7, 6, 6);
     170    T2 (a3[1].ma3[0].a7, a3[2].ma3[2].a7, 6, 6);
     171  
     172    T2 (a3[1].ma3[1].a7, a3[2].ma3[0].a7, 6, 6);
     173    T2 (a3[1].ma3[1].a7, a3[2].ma3[1].a7, 6, 6);
     174    T2 (a3[1].ma3[1].a7, a3[2].ma3[2].a7, 6, 6);
     175  
     176    T2 (a3[1].ma3[2].a7, a3[2].ma3[0].a7, 6, 6);
     177    T2 (a3[1].ma3[2].a7, a3[2].ma3[1].a7, 6, 6);
     178    T2 (a3[1].ma3[2].a7, a3[2].ma3[2].a7, 6, 6);
     179  
     180  
     181    T2 (a3[2].ma3[0].a7, a3[0].ma3[0].a7, 6, 6);
     182    T2 (a3[2].ma3[0].a7, a3[0].ma3[1].a7, 6, 6);
     183    T2 (a3[2].ma3[0].a7, a3[0].ma3[2].a7, 6, 6);
     184  
     185    T2 (a3[2].ma3[1].a7, a3[0].ma3[0].a7, 6, 6);
     186    T2 (a3[2].ma3[1].a7, a3[0].ma3[1].a7, 6, 6);
     187    T2 (a3[2].ma3[1].a7, a3[0].ma3[2].a7, 6, 6);
     188  
     189    T2 (a3[2].ma3[2].a7, a3[0].ma3[0].a7, 6, 6);
     190    T2 (a3[2].ma3[2].a7, a3[0].ma3[1].a7, 6, 6);
     191    T2 (a3[2].ma3[2].a7, a3[0].ma3[2].a7, 6, 6);
     192  
     193    T2 (a3[2].ma3[0].a7, a3[1].ma3[0].a7, 6, 6);
     194    T2 (a3[2].ma3[0].a7, a3[1].ma3[1].a7, 6, 6);
     195    T2 (a3[2].ma3[0].a7, a3[1].ma3[2].a7, 6, 6);
     196  
     197    T2 (a3[2].ma3[1].a7, a3[1].ma3[0].a7, 6, 6);
     198    T2 (a3[2].ma3[1].a7, a3[1].ma3[1].a7, 6, 6);
     199    T2 (a3[2].ma3[1].a7, a3[1].ma3[2].a7, 6, 6);
     200  
     201    T2 (a3[2].ma3[2].a7, a3[1].ma3[0].a7, 6, 6);
     202    T2 (a3[2].ma3[2].a7, a3[1].ma3[1].a7, 6, 6);
     203    T2 (a3[2].ma3[2].a7, a3[1].ma3[2].a7, 6, 6);
     204  
     205    T2 (a3[2].ma3[0].a7, a3[2].ma3[0].a7, 6, 6);   // { dg-warning "\\\[-Warray-bounds" }
     206    T2 (a3[2].ma3[0].a7, a3[2].ma3[1].a7, 6, 6);
     207    T2 (a3[2].ma3[0].a7, a3[2].ma3[2].a7, 6, 6);
     208  
     209    T2 (a3[2].ma3[1].a7, a3[2].ma3[0].a7, 6, 6);
     210    T2 (a3[2].ma3[1].a7, a3[2].ma3[1].a7, 6, 6);   // { dg-warning "\\\[-Warray-bounds" }
     211    T2 (a3[2].ma3[1].a7, a3[2].ma3[2].a7, 6, 6);
     212  
     213    T2 (a3[2].ma3[2].a7, a3[2].ma3[0].a7, 6, 6);
     214    T2 (a3[2].ma3[2].a7, a3[2].ma3[1].a7, 6, 6);
     215    T2 (a3[2].ma3[2].a7, a3[2].ma3[2].a7, 6, 6);   // { dg-warning "\\\[-Warray-bounds" }
     216  }
     217  
     218  
     219  void strcat_arrays_of_arrays_ref (struct ArraysOfMemArrays *p)
     220  {
     221    T2 (p[0].ma3[0].a7, p[0].ma3[0].a7, 6, 6);   // { dg-warning "\\\[-Warray-bounds" }
     222    T2 (p[0].ma3[0].a7, p[0].ma3[1].a7, 6, 6);
     223    T2 (p[0].ma3[0].a7, p[0].ma3[2].a7, 6, 6);
     224  
     225    T2 (p[0].ma3[1].a7, p[0].ma3[0].a7, 6, 6);
     226    T2 (p[0].ma3[1].a7, p[0].ma3[1].a7, 6, 6);   // { dg-warning "\\\[-Warray-bounds" }
     227    T2 (p[0].ma3[1].a7, p[0].ma3[2].a7, 6, 6);
     228  
     229    T2 (p[0].ma3[2].a7, p[0].ma3[0].a7, 6, 6);
     230    T2 (p[0].ma3[2].a7, p[0].ma3[1].a7, 6, 6);
     231    T2 (p[0].ma3[2].a7, p[0].ma3[2].a7, 6, 6);   // { dg-warning "\\\[-Warray-bounds" }
     232  
     233    T2 (p[0].ma3[0].a7, p[1].ma3[0].a7, 6, 6);
     234    T2 (p[0].ma3[0].a7, p[1].ma3[1].a7, 6, 6);
     235    T2 (p[0].ma3[0].a7, p[1].ma3[2].a7, 6, 6);
     236  
     237    T2 (p[0].ma3[1].a7, p[1].ma3[0].a7, 6, 6);
     238    T2 (p[0].ma3[1].a7, p[1].ma3[1].a7, 6, 6);
     239    T2 (p[0].ma3[1].a7, p[1].ma3[2].a7, 6, 6);
     240  
     241    T2 (p[0].ma3[2].a7, p[1].ma3[0].a7, 6, 6);
     242    T2 (p[0].ma3[2].a7, p[1].ma3[1].a7, 6, 6);
     243    T2 (p[0].ma3[2].a7, p[1].ma3[2].a7, 6, 6);
     244  
     245    T2 (p[0].ma3[0].a7, p[2].ma3[0].a7, 6, 6);
     246    T2 (p[0].ma3[0].a7, p[2].ma3[1].a7, 6, 6);
     247    T2 (p[0].ma3[0].a7, p[2].ma3[2].a7, 6, 6);
     248  
     249    T2 (p[0].ma3[1].a7, p[2].ma3[0].a7, 6, 6);
     250    T2 (p[0].ma3[1].a7, p[2].ma3[1].a7, 6, 6);
     251    T2 (p[0].ma3[1].a7, p[2].ma3[2].a7, 6, 6);
     252  
     253    T2 (p[0].ma3[2].a7, p[2].ma3[0].a7, 6, 6);
     254    T2 (p[0].ma3[2].a7, p[2].ma3[1].a7, 6, 6);
     255    T2 (p[0].ma3[2].a7, p[2].ma3[2].a7, 6, 6);
     256  
     257  
     258    T2 (p[1].ma3[0].a7, p[0].ma3[0].a7, 6, 6);
     259    T2 (p[1].ma3[0].a7, p[0].ma3[1].a7, 6, 6);
     260    T2 (p[1].ma3[0].a7, p[0].ma3[2].a7, 6, 6);
     261  
     262    T2 (p[1].ma3[1].a7, p[0].ma3[0].a7, 6, 6);
     263    T2 (p[1].ma3[1].a7, p[0].ma3[1].a7, 6, 6);
     264    T2 (p[1].ma3[1].a7, p[0].ma3[2].a7, 6, 6);
     265  
     266    T2 (p[1].ma3[2].a7, p[0].ma3[0].a7, 6, 6);
     267    T2 (p[1].ma3[2].a7, p[0].ma3[1].a7, 6, 6);
     268    T2 (p[1].ma3[2].a7, p[0].ma3[2].a7, 6, 6);
     269  
     270    T2 (p[1].ma3[0].a7, p[1].ma3[0].a7, 6, 6);   // { dg-warning "\\\[-Warray-bounds" }
     271    T2 (p[1].ma3[0].a7, p[1].ma3[1].a7, 6, 6);
     272    T2 (p[1].ma3[0].a7, p[1].ma3[2].a7, 6, 6);
     273  
     274    T2 (p[1].ma3[1].a7, p[1].ma3[0].a7, 6, 6);
     275    T2 (p[1].ma3[1].a7, p[1].ma3[1].a7, 6, 6);   // { dg-warning "\\\[-Warray-bounds" }
     276    T2 (p[1].ma3[1].a7, p[1].ma3[2].a7, 6, 6);
     277  
     278    T2 (p[1].ma3[2].a7, p[1].ma3[0].a7, 6, 6);
     279    T2 (p[1].ma3[2].a7, p[1].ma3[1].a7, 6, 6);
     280    T2 (p[1].ma3[2].a7, p[1].ma3[2].a7, 6, 6);   // { dg-warning "\\\[-Warray-bounds" }
     281  
     282    T2 (p[1].ma3[0].a7, p[2].ma3[0].a7, 6, 6);
     283    T2 (p[1].ma3[0].a7, p[2].ma3[1].a7, 6, 6);
     284    T2 (p[1].ma3[0].a7, p[2].ma3[2].a7, 6, 6);
     285  
     286    T2 (p[1].ma3[1].a7, p[2].ma3[0].a7, 6, 6);
     287    T2 (p[1].ma3[1].a7, p[2].ma3[1].a7, 6, 6);
     288    T2 (p[1].ma3[1].a7, p[2].ma3[2].a7, 6, 6);
     289  
     290    T2 (p[1].ma3[2].a7, p[2].ma3[0].a7, 6, 6);
     291    T2 (p[1].ma3[2].a7, p[2].ma3[1].a7, 6, 6);
     292    T2 (p[1].ma3[2].a7, p[2].ma3[2].a7, 6, 6);
     293  
     294  
     295    T2 (p[2].ma3[0].a7, p[0].ma3[0].a7, 6, 6);
     296    T2 (p[2].ma3[0].a7, p[0].ma3[1].a7, 6, 6);
     297    T2 (p[2].ma3[0].a7, p[0].ma3[2].a7, 6, 6);
     298  
     299    T2 (p[2].ma3[1].a7, p[0].ma3[0].a7, 6, 6);
     300    T2 (p[2].ma3[1].a7, p[0].ma3[1].a7, 6, 6);
     301    T2 (p[2].ma3[1].a7, p[0].ma3[2].a7, 6, 6);
     302  
     303    T2 (p[2].ma3[2].a7, p[0].ma3[0].a7, 6, 6);
     304    T2 (p[2].ma3[2].a7, p[0].ma3[1].a7, 6, 6);
     305    T2 (p[2].ma3[2].a7, p[0].ma3[2].a7, 6, 6);
     306  
     307    T2 (p[2].ma3[0].a7, p[1].ma3[0].a7, 6, 6);
     308    T2 (p[2].ma3[0].a7, p[1].ma3[1].a7, 6, 6);
     309    T2 (p[2].ma3[0].a7, p[1].ma3[2].a7, 6, 6);
     310  
     311    T2 (p[2].ma3[1].a7, p[1].ma3[0].a7, 6, 6);
     312    T2 (p[2].ma3[1].a7, p[1].ma3[1].a7, 6, 6);
     313    T2 (p[2].ma3[1].a7, p[1].ma3[2].a7, 6, 6);
     314  
     315    T2 (p[2].ma3[2].a7, p[1].ma3[0].a7, 6, 6);
     316    T2 (p[2].ma3[2].a7, p[1].ma3[1].a7, 6, 6);
     317    T2 (p[2].ma3[2].a7, p[1].ma3[2].a7, 6, 6);
     318  
     319    T2 (p[2].ma3[0].a7, p[2].ma3[0].a7, 6, 6);   // { dg-warning "\\\[-Warray-bounds" }
     320    T2 (p[2].ma3[0].a7, p[2].ma3[1].a7, 6, 6);
     321    T2 (p[2].ma3[0].a7, p[2].ma3[2].a7, 6, 6);
     322  
     323    T2 (p[2].ma3[1].a7, p[2].ma3[0].a7, 6, 6);
     324    T2 (p[2].ma3[1].a7, p[2].ma3[1].a7, 6, 6);   // { dg-warning "\\\[-Warray-bounds" }
     325    T2 (p[2].ma3[1].a7, p[2].ma3[2].a7, 6, 6);
     326  
     327    T2 (p[2].ma3[2].a7, p[2].ma3[0].a7, 6, 6);
     328    T2 (p[2].ma3[2].a7, p[2].ma3[1].a7, 6, 6);
     329    T2 (p[2].ma3[2].a7, p[2].ma3[2].a7, 6, 6);   // { dg-warning "\\\[-Warray-bounds" }
     330  }