(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.dg/
Wstringop-overflow-27.c
       1  /* PR middle-end/91582 - missing heap overflow detection for strcpy
       2     PR middle-end/85484 - missing -Wstringop-overflow for strcpy with
       3     a string of non-const length
       4     { dg-do compile }
       5     { dg-options "-O2 -Wall -Wno-array-bounds" }
       6     { dg-require-effective-target alloca } */
       7  
       8  typedef __SIZE_TYPE__ size_t;
       9  
      10  extern void* calloc (size_t, size_t);
      11  extern void* malloc (size_t);
      12  extern void* memcpy (void*, const void*, size_t);
      13  extern void* memset (void*, int, size_t);
      14  extern char* strcpy (char*, const char*);
      15  extern size_t strlen (const char*);
      16  
      17  void sink (void*);
      18  
      19  
      20  void test_memcpy_nowarn (const void *s, int i, size_t n)
      21  {
      22    sink (memcpy (calloc (1, 1), s, 1));
      23    sink (memcpy (calloc (1, 2), s, 1));
      24    sink (memcpy (calloc (2, 1), s, 1));
      25    sink (memcpy (calloc (3, 1), s, 2));
      26    sink (memcpy (calloc (3, 1), "12", 2));
      27    sink (memcpy (calloc (3, 1), s, 3));
      28    sink (memcpy (calloc (3, 1), "12", 3));
      29    sink (memcpy (calloc (i, 1), s, 1));
      30    sink (memcpy (calloc (n, 1), s, 1));
      31    sink (memcpy (calloc (1, n), "", 1));
      32    sink (memcpy (calloc (1, i), "", 1));
      33    sink (memcpy (calloc (i, 1), "123", 3));
      34    sink (memcpy (calloc (n, 1), "123", 3));
      35    sink (memcpy (calloc (1, i), "123456", 7));
      36    sink (memcpy (calloc (1, n), "123456", 7));
      37    sink (memcpy (calloc (n, 1), s, 12345));
      38    sink (memcpy (calloc (1, n), s, n - 1));
      39    sink (memcpy (calloc (n, 1), s, n));
      40  
      41    sink (memcpy ((char*)calloc (1, 1) + i, "123", 1));
      42    sink (memcpy ((char*)calloc (n, 1) + i, "123", n));
      43  
      44    sink (memcpy ((char*)calloc (1, 1) + i, s, 1));
      45    sink (memcpy ((char*)calloc (n, 1) + i, s, n));
      46  
      47    sink (memcpy (malloc (1), s, 1));
      48    sink (memcpy (malloc (2), s, 1));
      49    sink (memcpy (malloc (3), s, 2));
      50    sink (memcpy (malloc (3), "12", 2));
      51    sink (memcpy (malloc (3), s, 3));
      52    sink (memcpy (malloc (3), "12", 3));
      53    sink (memcpy (malloc (n), s, 1));
      54    sink (memcpy (malloc (n), "", 1));
      55    sink (memcpy (malloc (n), "123", 3));
      56    sink (memcpy (malloc (n), "123456", 7));
      57    sink (memcpy (malloc (n), s, 12345));
      58    sink (memcpy (malloc (n), s, n - 1));
      59    sink (memcpy (malloc (n), s, n));
      60  
      61    {
      62      const int a[] = { 1, 2, 3, 4 };
      63      void *p = (char*)malloc (sizeof a);
      64      memcpy (p, a, sizeof a);
      65      sink (p);
      66    }
      67  
      68    {
      69      const int a[] = { 1, 2, 3, 4, 5 };
      70      size_t nelts = sizeof a / sizeof *a;
      71      int vla[nelts];
      72      memcpy (vla, a, nelts * sizeof *vla);
      73      sink (vla);
      74    }
      75  }
      76  
      77  
      78  void test_memcpy_warn (const int *s, size_t n)
      79  {
      80    {
      81      void *p = (char*)malloc (0);
      82      memcpy (p, s, 1);                    // { dg-warning "writing 1 byte into a region of size 0" }
      83      sink (p);
      84    }
      85  
      86    {
      87      void *p = (char*)malloc (1);
      88      memcpy (p, s, 2);                    // { dg-warning "writing 2 bytes into a region of size 1" }
      89      sink (p);
      90    }
      91  
      92    {
      93      void *p = (char*)malloc (2);
      94      memcpy (p, s, 3);                    // { dg-warning "writing 3 bytes into a region of size 2" }
      95      sink (p);
      96    }
      97  
      98    {
      99      void *p = (char*)malloc (3);
     100      memcpy (p, s, 4);                    // { dg-warning "writing 4 bytes into a region of size 3" }
     101      sink (p);
     102    }
     103  
     104    {
     105      const int a[] = { 1, 2, 3, 4 };
     106      void *p = (char*)malloc (sizeof *a);
     107      memcpy (p, a, sizeof a);              // { dg-warning "" }
     108      sink (p);
     109    }
     110  
     111    {
     112      const int a[] = { 1, 2, 3, 4, 5 };
     113      size_t nelts = sizeof a / sizeof *a;
     114      char vla[nelts];
     115      memcpy (vla, a, nelts * sizeof *a);   // { dg-warning "" }
     116      sink (vla);
     117    }
     118  
     119    {
     120      void *p = malloc (n);
     121      memcpy (p, s, n * sizeof *s);         // { dg-warning "\\\[-Wstringop-overflow" "" { xfail *-*-* } }
     122      sink (p);
     123    }
     124  }
     125  
     126  void test_memset_nowarn (int x, size_t n)
     127  {
     128    sink (memset (calloc (1, 1), x, 1));
     129    sink (memset (calloc (1, 2), x, 1));
     130    sink (memset (calloc (2, 1), x, 1));
     131    sink (memset (calloc (3, 1), x, 2));
     132    sink (memset (calloc (3, 1), x, 3));
     133    sink (memset (calloc (n, 1), x, 1));
     134    sink (memset (calloc (n, 1), x, 12345));
     135    sink (memset (calloc (1, n), x, n - 1));
     136    sink (memset (calloc (n, 1), x, n));
     137  
     138    sink (memset (malloc (1), x, 1));
     139    sink (memset (malloc (2), x, 1));
     140    sink (memset (malloc (3), x, 2));
     141    sink (memset (malloc (3), x, 3));
     142    sink (memset (malloc (n), x, 1));
     143    sink (memset (malloc (n), x, 12345));
     144    sink (memset (malloc (n), x, n - 1));
     145    sink (memset (malloc (n), x, n));
     146  
     147    {
     148      const int a[] = { 1, 2, 3, 4 };
     149      void *p = (char*)malloc (sizeof a);
     150      memset (p, x, sizeof a);
     151      sink (p);
     152    }
     153  
     154    {
     155      const int a[] = { 1, 2, 3, 4, 5 };
     156      size_t nelts = sizeof a / sizeof *a;
     157      int vla[nelts];
     158      memset (vla, x, nelts * sizeof *vla);
     159      sink (vla);
     160    }
     161  }
     162  
     163  
     164  void test_memset_warn (int x, size_t n)
     165  {
     166    {
     167      void *p = (char*)malloc (0);
     168      memset (p, x, 1);                    // { dg-warning "writing 1 byte into a region of size 0" }
     169      sink (p);
     170    }
     171  
     172    {
     173      void *p = (char*)malloc (1);
     174      memset (p, x, 2);                    // { dg-warning "writing 2 bytes into a region of size 1" }
     175      sink (p);
     176    }
     177  
     178    {
     179      void *p = (char*)malloc (2);
     180      memset (p, x, 3);                    // { dg-warning "writing 3 bytes into a region of size 2" }
     181      sink (p);
     182    }
     183  
     184    {
     185      void *p = (char*)malloc (3);
     186      memset (p, x, 4);                    // { dg-warning "writing 4 bytes into a region of size 3" }
     187      sink (p);
     188    }
     189  
     190    {
     191      const int a[] = { 1, 2, 3, 4 };
     192      void *p = (char*)malloc (sizeof *a);
     193      memset (p, 0, sizeof a);              // { dg-warning "" }
     194      sink (p);
     195    }
     196  
     197    {
     198      const int a[] = { 1, 2, 3, 4, 5 };
     199      size_t nelts = sizeof a / sizeof *a;
     200      char vla[nelts];
     201      memset (vla, 0, nelts * sizeof *a);   // { dg-warning "" }
     202      sink (vla);
     203    }
     204  
     205    {
     206      void *p = malloc (n);
     207      memset (p, x, n * sizeof (int));      // { dg-warning "\\\[-Wstringop-overflow" "" { xfail *-*-* } }
     208      sink (p);
     209    }
     210  }
     211  
     212  
     213  void test_strcpy_nowarn (const char *s)
     214  {
     215    {
     216      const char a[] = "12";
     217      int n = strlen (a);
     218      char *t = (char*)calloc (2, n);
     219      strcpy (t, a);
     220      sink (t);
     221    }
     222  
     223    {
     224      const char a[] = "123";
     225      unsigned n = strlen (a) + 1;
     226      char *t = (char*)calloc (n, 1);
     227      strcpy (t, a);
     228      sink (t);
     229    }
     230  
     231    {
     232      const char a[] = "1234";
     233      size_t n = strlen (a) * 2;
     234      char *t = (char*)malloc (n);
     235      strcpy (t, a);
     236      sink (t);
     237    }
     238  
     239    {
     240      const char a[] = "1234";
     241      size_t len = strlen (a) + 1;
     242      char vla[len];
     243      strcpy (vla, a);
     244      sink (vla);
     245    }
     246  
     247    {
     248      size_t n = strlen (s) + 1;
     249      char *t = (char*)malloc (n);
     250      strcpy (t, s);
     251      sink (t);
     252    }
     253  }
     254  
     255  
     256  void test_strcpy_warn (const char *s)
     257  {
     258    {
     259      const char a[] = "123";
     260      /* Verify that using signed int for the strlen result works (i.e.,
     261         that the conversion from signed int to size_t doesn't prevent
     262         the detection.  */
     263      int n = strlen (a);
     264      char *t = (char*)calloc (n, 1);     // { dg-message "destination object of size 3 allocated by 'calloc'" "note" }
     265      strcpy (t, a);                      // { dg-warning "writing 4 bytes into a region of size (between 0 and )?3 " }
     266  
     267      sink (t);
     268    }
     269  
     270    {
     271      const char a[] = "1234";
     272      size_t n = strlen (a);
     273      char *t = (char*)malloc (n);        // { dg-message "destination object of size 4 allocated by 'malloc'" "note" }
     274      strcpy (t, a);                      // { dg-warning "writing 5 bytes into a region of size (between 0 and )?4 " }
     275      sink (t);
     276    }
     277  
     278    // Exercise PR middle-end/85484.
     279    {
     280      size_t len = strlen (s);
     281      char vla[len];                      // { dg-message "destination object 'vla'" "vla note" }
     282      strcpy (vla, s);                    // { dg-warning "writing one too many bytes into a region of a size that depends on 'strlen'" }
     283      sink (vla);
     284    }
     285  
     286    {
     287      size_t n = strlen (s);
     288      char *t = (char*)malloc (n);        // { dg-message "allocated by 'malloc'" "malloc note" }
     289      strcpy (t, s);                      // { dg-warning "writing one too many bytes into a region of a size that depends on 'strlen'" }
     290      sink (t);
     291    }
     292  }