(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.dg/
Wstringop-overflow-37.c
       1  /* Verify that -Wstringop-overflow detects writing past the end of each
       2     individual element of a multidimensional array.
       3    { dg-do compile }
       4    { dg-options "-O2 -Wall -Wno-array-bounds -Wno-stringop-truncation" } */
       5  
       6  #define CONCAT(x, y)    x ## y
       7  #define CAT(name, line) CONCAT (name, line)
       8  #define UNIQ_NAME(name) CAT (name, __LINE__)
       9  
      10  typedef __SIZE_TYPE__ size_t;
      11  
      12  extern void* malloc (size_t);
      13  extern char* strncpy (char*, const char*, size_t);
      14  
      15  extern char a2_2_8[2][2][8];
      16  
      17  void nowarn_a2_2_8 (const char *s)
      18  {
      19    // The following trigger -Wstringop-truncation.
      20    strncpy (a2_2_8[0][0], s, 8);
      21    strncpy (a2_2_8[0][1], s, 8);
      22    strncpy (a2_2_8[1][0], s, 8);
      23    strncpy (a2_2_8[1][1], s, 8);
      24  }
      25  
      26  void warn_a2_2_8 (const char *s)
      27  {
      28    strncpy (a2_2_8[0][0], s, 9);         // { dg-warning "writing 9 bytes into a region of size 8 " }
      29    strncpy (a2_2_8[0][1], s, 9);         // { dg-warning "writing 9 bytes into a region of size 8 " }
      30    strncpy (a2_2_8[1][0], s, 9);         // { dg-warning "writing 9 bytes into a region of size 8 " }
      31    strncpy (a2_2_8[1][1], s, 9);         // { dg-warning "writing 9 bytes into a region of size 8 " }
      32  }
      33  
      34  
      35  extern char a2_3_5[2][3][5];
      36  
      37  void nowarn_a2_3_5 (const char *s)
      38  {
      39    // The following trigger -Wstringop-truncation.
      40    strncpy (a2_3_5[0][0], s, 5);
      41    strncpy (a2_3_5[0][1], s, 5);
      42    strncpy (a2_3_5[0][2], s, 5);
      43    strncpy (a2_3_5[1][0], s, 5);
      44    strncpy (a2_3_5[1][1], s, 5);
      45    strncpy (a2_3_5[1][2], s, 5);
      46  }
      47  
      48  void warn_a2_3_5 (const char *s)
      49  {
      50    strncpy (a2_3_5[0][0], s, 6);         // { dg-warning "writing 6 bytes into a region of size 5 " }
      51    strncpy (a2_3_5[0][1], s, 7);         // { dg-warning "writing 7 bytes into a region of size 5 " }
      52    strncpy (a2_3_5[1][0], s, 8);         // { dg-warning "writing 8 bytes into a region of size 5 " }
      53    strncpy (a2_3_5[1][1], s, 9);         // { dg-warning "writing 9 bytes into a region of size 5 " }
      54  }
      55  
      56  
      57  void* nowarn_malloc_3_5 (const char *s, unsigned n)
      58  {
      59    if (n < 3 || 5 < n)
      60      n = 3;
      61    char *p = (char*)malloc (n);
      62    strncpy (p + 1, s, 4);
      63    return p;
      64  }
      65  
      66  void* warn_malloc_3_5 (const char *s, unsigned n)
      67  {
      68    if (n < 3 || 5 < n)
      69      n = 3;
      70    char *p = (char*)malloc (n);          // { dg-message "at offset 1 into destination object of size \\\[3, 5] allocated by 'malloc'" "note" }
      71    // The size below should be a range like the one above.
      72    strncpy (p + 1, s, 5);                // { dg-warning "writing 5 bytes into a region of size 4 " }
      73    return p;
      74  }
      75  
      76  
      77  typedef __attribute__ ((alloc_size (1, 2))) void* UsrAlloc (int, int);
      78  
      79  void* nowarn_use_alloc_3_5 (UsrAlloc *usr_alloc, const char *s, unsigned n)
      80  {
      81    if (n < 3 || 5 < n)
      82      n = 3;
      83    char *p = (char*)usr_alloc (n, 3);
      84    strncpy (p + 1, s, 14);
      85    return p;
      86  }
      87  
      88  void* warn_usr_alloc_3_5 (UsrAlloc *usr_alloc, const char *s, unsigned n)
      89  {
      90    if (n < 3 || 5 < n)
      91      n = 3;
      92    char *p = (char*)usr_alloc (n, 3);    // { dg-message "at offset 1 into destination object of size \\\[9, 15] allocated by 'usr_alloc'" "note" }
      93    // The size below should be a range like the one above.
      94    strncpy (p + 1, s, 15);               // { dg-warning "writing 15 bytes into a region of size 14 " }
      95    return p;
      96  }
      97  
      98  struct S
      99  {
     100    char a2_3_4[2][3][4];
     101    char a3_4_5[3][4][5];
     102  };
     103  
     104  extern struct S sa[];
     105  
     106  void nowarn_sa_cstidx_cstsize (const char* const s[])
     107  {
     108    strncpy (sa[0].a2_3_4[0][0], s[0], 4);
     109    strncpy (sa[0].a2_3_4[0][1], s[1], 4);
     110    strncpy (sa[0].a2_3_4[0][2], s[2], 4);
     111  
     112    strncpy (sa[0].a2_3_4[1][0], s[3], 4);
     113    strncpy (sa[0].a2_3_4[1][1], s[4], 4);
     114    strncpy (sa[0].a2_3_4[1][2], s[5], 4);
     115  
     116    strncpy (sa[1].a2_3_4[0][0], s[6], 4);
     117    strncpy (sa[1].a2_3_4[0][1], s[7], 4);
     118    strncpy (sa[1].a2_3_4[0][2], s[8], 4);
     119  
     120    strncpy (sa[1].a2_3_4[1][0], s[9], 4);
     121    strncpy (sa[1].a2_3_4[1][1], s[10], 4);
     122    strncpy (sa[1].a2_3_4[1][2], s[11], 4);
     123  }
     124  
     125  void warn_sa_cstidx_cstsize (const char* const s[])
     126  {
     127    strncpy (sa[0].a2_3_4[0][0], s[0], 5);    // { dg-warning "writing 5 bytes into a region of size 4 " }
     128    strncpy (sa[0].a2_3_4[0][1], s[1], 6);    // { dg-warning "writing 6 bytes into a region of size 4 " }
     129    strncpy (sa[0].a2_3_4[0][2], s[2], 7);    // { dg-warning "writing 7 bytes into a region of size 4 " }
     130  
     131    strncpy (sa[0].a2_3_4[1][0], s[3], 5);    // { dg-warning "writing 5 bytes into a region of size 4 " }
     132    strncpy (sa[0].a2_3_4[1][1], s[4], 6);    // { dg-warning "writing 6 bytes into a region of size 4 " }
     133    strncpy (sa[0].a2_3_4[1][2], s[5], 7);    // { dg-warning "writing 7 bytes into a region of size 4 " }
     134  
     135    strncpy (sa[1].a2_3_4[0][0], s[6], 5);    // { dg-warning "writing 5 bytes into a region of size 4 " }
     136    strncpy (sa[1].a2_3_4[0][1], s[7], 6);    // { dg-warning "writing 6 bytes into a region of size 4 " }
     137    strncpy (sa[1].a2_3_4[0][2], s[8], 7);    // { dg-warning "writing 7 bytes into a region of size 4 " }
     138  
     139    strncpy (sa[1].a2_3_4[1][0], s[9], 5);    // { dg-warning "writing 5 bytes into a region of size 4 " }
     140    strncpy (sa[1].a2_3_4[1][1], s[10], 6);   // { dg-warning "writing 6 bytes into a region of size 4 " }
     141    strncpy (sa[1].a2_3_4[1][2], s[11], 7);   // { dg-warning "writing 7 bytes into a region of size 4 " }
     142  }
     143  
     144  void nowarn_sa_cstidx_varsize (const char* const s[], unsigned n)
     145  {
     146    strncpy (sa[0].a2_3_4[0][0], s[0], n);
     147    strncpy (sa[0].a2_3_4[0][1], s[1], n);
     148    strncpy (sa[0].a2_3_4[0][2], s[2], n);
     149  
     150    strncpy (sa[0].a2_3_4[1][0], s[3], n);
     151    strncpy (sa[0].a2_3_4[1][1], s[4], n);
     152    strncpy (sa[0].a2_3_4[1][2], s[5], n);
     153  
     154    strncpy (sa[1].a2_3_4[0][0], s[6], n);
     155    strncpy (sa[1].a2_3_4[0][1], s[7], n);
     156    strncpy (sa[1].a2_3_4[0][2], s[8], n);
     157  
     158    strncpy (sa[1].a2_3_4[1][0], s[9], n);
     159    strncpy (sa[1].a2_3_4[1][1], s[10], n);
     160    strncpy (sa[1].a2_3_4[1][2], s[11], n);
     161  }
     162  
     163  void nowarn_sa_loop (const char* const s[], unsigned n)
     164  {
     165    for (unsigned i0 = 0; i0 != 5; ++i0)
     166      for (unsigned i1 = 0; i1 != 3; ++i1)
     167        for (unsigned i2 = 0; i2 != 2; ++i2)
     168  	strncpy (sa[i0].a2_3_4[i1][i2], s[i2], n);
     169  }
     170  
     171  
     172  /* Verify that a note after the warning points to the accessed object
     173     and mentions the starting offset of the access.  Another alternative
     174     might be for the offset to be the starting offset of the overflow.
     175     As it is, it's not clear to which of the two the offset refers.  */
     176  
     177  void test_note (const char *s)
     178  {
     179    extern void sink (void*);
     180  
     181    {
     182      char a[1][1][2];                    // { dg-message "destination object" "note" }
     183      strncpy (a[0][0], s, 3);            // { dg-warning "writing 3 bytes into a region of size 2 " }
     184      sink (a);
     185    }
     186  
     187    {
     188      char a[1][1][2];                    // { dg-message "at offset 2 into " "note" }
     189      strncpy (a[0][1], s, 3);            // { dg-warning "writing 3 bytes into a region of size 0 " }
     190      sink (a);
     191    }
     192  
     193    {
     194      char a[1][2][2];                    // { dg-message "destination object" "note" }
     195      strncpy (a[0][0], s, 3);            // { dg-warning "writing 3 bytes into a region of size 2 " }
     196      sink (a);
     197    }
     198  
     199    {
     200      char a[1][2][2];                    // { dg-message "at offset 2 into " "note" }
     201      strncpy (a[0][1], s, 3);            // { dg-warning "writing 3 bytes into a region of size 2 " }
     202      sink (a);
     203    }
     204  
     205    {
     206      char a[1][2][2];                    // { dg-message "at offset 4 into " "note" }
     207      strncpy (a[1][0], s, 3);            // { dg-warning "writing 3 bytes into a region of size 0 " }
     208      sink (a);
     209    }
     210  
     211    {
     212      char a[2][1][2];                    // { dg-message "at offset 2 into " "note" }
     213      strncpy (a[0][1], s, 3);            // { dg-warning "writing 3 bytes into a region of size 0 " }
     214      sink (a);
     215    }
     216  
     217    {
     218      char a[2][1][2];                    // { dg-message "at offset 2 into " "note" }
     219      strncpy (a[1][0], s, 3);            // { dg-warning "writing 3 bytes into a region of size 2 " }
     220      sink (a);
     221    }
     222  
     223    {
     224      char a[2][2][3];                    // { dg-message "at offset 9 into " "note" }
     225      strncpy (a[1][1], s, 4);            // { dg-warning "writing 4 bytes into a region of size 3 " }
     226      sink (a);
     227    }
     228  
     229    {
     230      char a[2][3][3];                    // { dg-message "at offset 12 into " "note" }
     231      strncpy (a[1][1], s, 5);            // { dg-warning "writing 5 bytes into a region of size 3 " }
     232      sink (a);
     233    }
     234  
     235    {
     236      char a[2][3][3];                    // { dg-message "at offset 12 into " "note" }
     237      strncpy (a[1][1], s, 6);            // { dg-warning "writing 6 bytes into a region of size 3 " }
     238      sink (a);
     239    }
     240  
     241    {
     242      char a[2][3][3];                    // { dg-message "at offset 15 into " "note" }
     243      strncpy (a[1][2], s, 7);            // { dg-warning "writing 7 bytes into a region of size 3 " }
     244      sink (a);
     245    }
     246  
     247  }