(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.dg/
Wstringop-overflow-25.c
       1  /* PR middle-end/91582 - missing heap overflow detection for strcpy
       2     { dg-do compile }
       3     { dg-options "-O2 -Wall -Wno-array-bounds -ftrack-macro-expansion=0" }
       4     { dg-require-effective-target alloca } */
       5  
       6  #include "range.h"
       7  
       8  #define INT_MAX     __INT_MAX__
       9  #define INT_MIN     (-INT_MAX - 1)
      10  
      11  #define ATTR(...)   __attribute__ ((__VA_ARGS__))
      12  #define NOIPA       ATTR (noipa)
      13  
      14  extern void* alloca (size_t);
      15  extern void* calloc (size_t, size_t);
      16  extern void* malloc (size_t);
      17  
      18  extern ATTR (alloc_size (1), malloc) void*
      19    alloc1 (size_t, int);
      20  extern ATTR (alloc_size (2), malloc) void*
      21    alloc2 (int, size_t);
      22  extern ATTR (alloc_size (2, 4), malloc) void*
      23    alloc2_4 (int, size_t, int, size_t);
      24  
      25  extern char* strcpy (char*, const char*);
      26  
      27  void sink (void*);
      28  
      29  #define S36 "0123456789abcdefghijklmnopqrstuvwxyz"
      30  #define S(N) (S36 + sizeof S36 - N - 1)
      31  
      32  #define T(src, alloc) do {			\
      33      char *s = src;				\
      34      char *d = alloc;				\
      35      strcpy (d, s);				\
      36      sink (d);					\
      37    } while (0)
      38  
      39  
      40  NOIPA void test_strcpy_alloca (size_t n)
      41  {
      42    size_t r_0_1 = UR (0, 1);
      43    size_t r_1_2 = UR (1, 2);
      44    size_t r_2_3 = UR (2, 3);
      45  
      46    T (S (0), alloca (r_0_1));
      47    T (S (1), alloca (r_0_1));      // { dg-warning "\\\[-Wstringop-overflow" }
      48  
      49    T (S (0), alloca (r_1_2));
      50    T (S (1), alloca (r_1_2));
      51    T (S (2), alloca (r_1_2));      // { dg-warning "\\\[-Wstringop-overflow" }
      52  
      53    T (S (0), alloca (r_2_3));
      54    T (S (2), alloca (r_2_3));
      55    T (S (3), alloca (r_2_3));      // { dg-warning "\\\[-Wstringop-overflow" }
      56    T (S (9), alloca (r_2_3));      // { dg-warning "\\\[-Wstringop-overflow" }
      57  
      58    size_t r_2_smax = UR (2, SIZE_MAX);
      59    T (S (0), alloca (r_2_smax));
      60    T (S (1), alloca (r_2_smax));
      61    T (S (2), alloca (r_2_smax));
      62    T (S (3), alloca (r_2_smax * 2));
      63    T (S (4), alloca (r_2_smax * 2 + 1));
      64  
      65    T (S (1), alloca (n));
      66    T (S (2), alloca (n + 1));
      67    T (S (9), alloca (n * 2 + 1));
      68  
      69    int r_imin_imax = SR (INT_MIN, INT_MAX);
      70    T (S (1), alloca (r_imin_imax));
      71    T (S (2), alloca (r_imin_imax + 1));
      72    T (S (9), alloca (r_imin_imax * 2 + 1));
      73  
      74    int r_0_imax = SR (0, INT_MAX);
      75    T (S (1), alloca (r_0_imax));
      76    T (S (2), alloca (r_0_imax + 1));
      77    T (S (9), alloca (r_0_imax * 2 + 1));
      78  
      79    int r_1_imax = SR (1, INT_MAX);
      80    T (S (1), alloca (r_1_imax));
      81    T (S (2), alloca (r_1_imax + 1));
      82    T (S (9), alloca (r_1_imax * 2 + 1));
      83  
      84    ptrdiff_t r_dmin_dmax = SR (DIFF_MIN, DIFF_MAX);
      85    T (S (1), alloca (r_dmin_dmax));
      86    T (S (2), alloca (r_dmin_dmax + 1));
      87    T (S (9), alloca (r_dmin_dmax * 2 + 1));
      88  }
      89  
      90  NOIPA void test_strcpy_calloc (void)
      91  {
      92    size_t r_1_2 = UR (1, 2);
      93    size_t r_2_3 = UR (2, 3);
      94  
      95    T (S (0), calloc (r_1_2, 1));
      96    T (S (1), calloc (r_1_2, 1));
      97    T (S (2), calloc (r_1_2, 1));   // { dg-warning "\\\[-Wstringop-overflow" }
      98  
      99    T (S (2), calloc (r_2_3, 1));
     100    T (S (3), calloc (r_2_3, 1));   // { dg-warning "\\\[-Wstringop-overflow" }
     101  
     102    T (S (0), calloc (1, r_1_2));
     103    T (S (1), calloc (1, r_1_2));
     104    T (S (2), calloc (1, r_1_2));   // { dg-warning "\\\[-Wstringop-overflow" }
     105  
     106    T (S (2), calloc (1, r_2_3));
     107    T (S (3), calloc (1, r_2_3));   // { dg-warning "\\\[-Wstringop-overflow" }
     108  
     109    T (S (0), calloc (r_1_2, 2));
     110    T (S (1), calloc (r_1_2, 2));
     111    T (S (2), calloc (r_1_2, 2));
     112    T (S (3), calloc (r_1_2, 2));
     113    T (S (4), calloc (r_1_2, 2));   // { dg-warning "\\\[-Wstringop-overflow" }
     114  
     115    T (S (0), calloc (r_2_3, 2));
     116    T (S (1), calloc (r_2_3, 2));
     117    T (S (2), calloc (r_2_3, 2));
     118    T (S (5), calloc (r_2_3, 2));
     119    T (S (6), calloc (r_2_3, 2));   // { dg-warning "\\\[-Wstringop-overflow" }
     120  
     121    T (S (0), calloc (r_1_2, 2));
     122    T (S (1), calloc (r_1_2, 2));
     123    T (S (2), calloc (r_1_2, 2));
     124    T (S (3), calloc (r_1_2, 2));
     125    T (S (4), calloc (r_1_2, 2));   // { dg-warning "\\\[-Wstringop-overflow" }
     126  
     127    T (S (0), calloc (r_2_3, 2));
     128    T (S (1), calloc (r_2_3, 2));
     129    T (S (2), calloc (r_2_3, 2));
     130    T (S (5), calloc (r_2_3, 2));
     131    T (S (6), calloc (r_2_3, 2));   // { dg-warning "\\\[-Wstringop-overflow" }
     132  
     133    T (S (0), calloc (r_1_2, r_2_3));
     134    T (S (1), calloc (r_1_2, r_2_3));
     135    T (S (2), calloc (r_1_2, r_2_3));
     136    T (S (3), calloc (r_1_2, r_2_3));
     137    T (S (4), calloc (r_1_2, r_2_3));
     138    T (S (5), calloc (r_1_2, r_2_3));
     139    T (S (6), calloc (r_1_2, r_2_3));   // { dg-warning "\\\[-Wstringop-overflow" }
     140    T (S (9), calloc (r_1_2, r_2_3));   // { dg-warning "\\\[-Wstringop-overflow" }
     141  
     142    size_t r_2_dmax = UR (2, DIFF_MAX);
     143    T (S (0), calloc (0, r_2_dmax));   // { dg-warning "\\\[-Wstringop-overflow" }
     144    T (S (0), calloc (1, r_2_dmax));
     145    T (S (9), calloc (2, r_2_dmax));
     146  
     147    T (S (0), calloc (r_2_dmax, r_2_dmax));
     148    T (S (9), calloc (r_2_dmax, r_2_dmax));
     149  
     150    size_t r_2_smax = UR (2, SIZE_MAX);
     151    T (S (0), calloc (r_2_smax, 1));
     152    T (S (9), calloc (r_2_smax, 2));
     153  
     154    T (S (0), calloc (r_2_smax, r_2_smax));
     155    T (S (9), calloc (r_2_smax, r_2_smax));
     156  }
     157  
     158  
     159  NOIPA void test_strcpy_malloc (void)
     160  {
     161    size_t r_0_1 = UR (0, 1);
     162    size_t r_1_2 = UR (1, 2);
     163    size_t r_2_3 = UR (2, 3);
     164  
     165    T (S (0), malloc (r_0_1));
     166    T (S (1), malloc (r_0_1));      // { dg-warning "\\\[-Wstringop-overflow" }
     167  
     168    T (S (0), malloc (r_1_2));
     169    T (S (1), malloc (r_1_2));
     170    T (S (2), malloc (r_1_2));      // { dg-warning "\\\[-Wstringop-overflow" }
     171  
     172    T (S (0), malloc (r_2_3));
     173    T (S (2), malloc (r_2_3));
     174    T (S (3), malloc (r_2_3));      // { dg-warning "\\\[-Wstringop-overflow" }
     175    T (S (9), malloc (r_2_3));      // { dg-warning "\\\[-Wstringop-overflow" }
     176  }
     177  
     178  
     179  NOIPA void test_strcpy_alloc1 (void)
     180  {
     181    size_t r_0_1 = UR (0, 1);
     182    size_t r_1_2 = UR (1, 2);
     183    size_t r_2_3 = UR (2, 3);
     184  
     185  #define alloc1(n) alloc1 (n, 1)
     186  
     187    T (S (0), alloc1 (r_0_1));
     188    T (S (1), alloc1 (r_0_1));      // { dg-warning "\\\[-Wstringop-overflow" }
     189  
     190    T (S (0), alloc1 (r_1_2));
     191    T (S (1), alloc1 (r_1_2));
     192    T (S (2), alloc1 (r_1_2));      // { dg-warning "\\\[-Wstringop-overflow" }
     193  
     194    T (S (0), alloc1 (r_2_3));
     195    T (S (2), alloc1 (r_2_3));
     196    T (S (3), alloc1 (r_2_3));      // { dg-warning "\\\[-Wstringop-overflow" }
     197    T (S (9), alloc1 (r_2_3));      // { dg-warning "\\\[-Wstringop-overflow" }
     198  }
     199  
     200  NOIPA void test_strcpy_alloc2 (void)
     201  {
     202    size_t r_0_1 = UR (0, 1);
     203    size_t r_1_2 = UR (1, 2);
     204    size_t r_2_3 = UR (2, 3);
     205  
     206  #define alloc2(n) alloc2 (1, n)
     207  
     208    T (S (0), alloc1 (r_0_1));
     209    T (S (1), alloc1 (r_0_1));      // { dg-warning "\\\[-Wstringop-overflow" }
     210  
     211    T (S (0), alloc1 (r_1_2));
     212    T (S (1), alloc1 (r_1_2));
     213    T (S (2), alloc1 (r_1_2));      // { dg-warning "\\\[-Wstringop-overflow" }
     214  
     215    T (S (0), alloc1 (r_2_3));
     216    T (S (2), alloc1 (r_2_3));
     217    T (S (3), alloc1 (r_2_3));      // { dg-warning "\\\[-Wstringop-overflow" }
     218    T (S (9), alloc1 (r_2_3));      // { dg-warning "\\\[-Wstringop-overflow" }
     219  }
     220  
     221  
     222  NOIPA void test_strcpy_alloc2_4 (void)
     223  {
     224    size_t r_1_2 = UR (1, 2);
     225    size_t r_2_3 = UR (2, 3);
     226  
     227  #define alloc2_4(n1, n2) alloc2_4 (1, n1, 2, n2)
     228  
     229    T (S (0), alloc2_4 (r_1_2, 1));
     230    T (S (1), alloc2_4 (r_1_2, 1));
     231    T (S (2), alloc2_4 (r_1_2, 1));   // { dg-warning "\\\[-Wstringop-overflow" }
     232  
     233    T (S (2), alloc2_4 (r_2_3, 1));
     234    T (S (3), alloc2_4 (r_2_3, 1));   // { dg-warning "\\\[-Wstringop-overflow" }
     235  
     236    T (S (0), alloc2_4 (1, r_1_2));
     237    T (S (1), alloc2_4 (1, r_1_2));
     238    T (S (2), alloc2_4 (1, r_1_2));   // { dg-warning "\\\[-Wstringop-overflow" }
     239  
     240    T (S (2), alloc2_4 (1, r_2_3));
     241    T (S (3), alloc2_4 (1, r_2_3));   // { dg-warning "\\\[-Wstringop-overflow" }
     242  
     243    T (S (0), alloc2_4 (r_1_2, 2));
     244    T (S (1), alloc2_4 (r_1_2, 2));
     245    T (S (2), alloc2_4 (r_1_2, 2));
     246    T (S (3), alloc2_4 (r_1_2, 2));
     247    T (S (4), alloc2_4 (r_1_2, 2));   // { dg-warning "\\\[-Wstringop-overflow" }
     248  
     249    T (S (0), alloc2_4 (r_2_3, 2));
     250    T (S (1), alloc2_4 (r_2_3, 2));
     251    T (S (2), alloc2_4 (r_2_3, 2));
     252    T (S (5), alloc2_4 (r_2_3, 2));
     253    T (S (6), alloc2_4 (r_2_3, 2));   // { dg-warning "\\\[-Wstringop-overflow" }
     254  
     255    T (S (0), alloc2_4 (r_1_2, 2));
     256    T (S (1), alloc2_4 (r_1_2, 2));
     257    T (S (2), alloc2_4 (r_1_2, 2));
     258    T (S (3), alloc2_4 (r_1_2, 2));
     259    T (S (4), alloc2_4 (r_1_2, 2));   // { dg-warning "\\\[-Wstringop-overflow" }
     260  
     261    T (S (0), alloc2_4 (r_2_3, 2));
     262    T (S (1), alloc2_4 (r_2_3, 2));
     263    T (S (2), alloc2_4 (r_2_3, 2));
     264    T (S (5), alloc2_4 (r_2_3, 2));
     265    T (S (6), alloc2_4 (r_2_3, 2));   // { dg-warning "\\\[-Wstringop-overflow" }
     266  
     267    T (S (0), alloc2_4 (r_1_2, r_2_3));
     268    T (S (1), alloc2_4 (r_1_2, r_2_3));
     269    T (S (2), alloc2_4 (r_1_2, r_2_3));
     270    T (S (3), alloc2_4 (r_1_2, r_2_3));
     271    T (S (4), alloc2_4 (r_1_2, r_2_3));
     272    T (S (5), alloc2_4 (r_1_2, r_2_3));
     273    T (S (6), alloc2_4 (r_1_2, r_2_3));   // { dg-warning "\\\[-Wstringop-overflow" }
     274    T (S (9), alloc2_4 (r_1_2, r_2_3));   // { dg-warning "\\\[-Wstringop-overflow" }
     275  
     276    size_t r_2_dmax = UR (2, DIFF_MAX);
     277    T (S (0), alloc2_4 (r_2_dmax, r_2_dmax));
     278    T (S (9), alloc2_4 (r_2_dmax, r_2_dmax));
     279  
     280    size_t r_2_smax = UR (2, SIZE_MAX);
     281    T (S (0), alloc2_4 (r_2_smax, r_2_smax));
     282    T (S (9), alloc2_4 (r_2_smax, r_2_smax));
     283  }
     284  
     285  #undef T
     286  #define T(T, src, n) do {			\
     287      char *s = src;				\
     288      T vla[n];					\
     289      char *d = (char*)vla;			\
     290      strcpy (d, s);				\
     291      sink (vla);					\
     292    } while (0)
     293  
     294  // Hack around PR 92829.
     295  #define XUR(min, max) \
     296    (++idx, (vals[idx] < min || max < vals[idx] ? min : vals[idx]))
     297  
     298  NOIPA void test_strcpy_vla (const size_t vals[])
     299  {
     300    size_t idx = 0;
     301  
     302    size_t r_0_1 = XUR (0, 1);
     303    size_t r_1_2 = XUR (1, 2);
     304    size_t r_2_3 = XUR (2, 3);
     305  
     306    T (char, S (0), r_0_1);
     307    T (char, S (1), r_0_1);       // { dg-warning "\\\[-Wstringop-overflow" }
     308  
     309    T (char, S (0), r_1_2);
     310    T (char, S (1), r_1_2);
     311    T (char, S (2), r_1_2);       // { dg-warning "\\\[-Wstringop-overflow" }
     312  
     313    T (char, S (0), r_2_3);
     314    T (char, S (2), r_2_3);
     315    T (char, S (3), r_2_3);       // { dg-warning "\\\[-Wstringop-overflow" }
     316    T (char, S (9), r_2_3);       // { dg-warning "\\\[-Wstringop-overflow" }
     317  
     318  #ifdef __INT16_TYPE__
     319    typedef __INT16_TYPE__ int16_t;
     320  
     321    T (int16_t, S (0), r_1_2);
     322    T (int16_t, S (2), r_1_2);
     323    T (int16_t, S (3), r_1_2);
     324    T (int16_t, S (4), r_1_2);    // { dg-warning "\\\[-Wstringop-overflow" }
     325    T (int16_t, S (5), r_1_2);    // { dg-warning "\\\[-Wstringop-overflow" }
     326    T (int16_t, S (9), r_1_2);    // { dg-warning "\\\[-Wstringop-overflow" }
     327  
     328    T (int16_t, S (0), r_2_3);
     329    T (int16_t, S (2), r_2_3);
     330    T (int16_t, S (3), r_2_3);
     331    T (int16_t, S (4), r_2_3);
     332    T (int16_t, S (5), r_2_3);
     333    T (int16_t, S (6), r_2_3);    // { dg-warning "\\\[-Wstringop-overflow" }
     334  #endif
     335  
     336  #ifdef __INT32_TYPE__
     337    typedef __INT32_TYPE__ int32_t;
     338  
     339    T (int32_t, S ( 0), r_2_3);
     340    T (int32_t, S ( 2), r_2_3);
     341    T (int32_t, S ( 3), r_2_3);
     342    T (int32_t, S ( 4), r_2_3);
     343    T (int32_t, S ( 5), r_2_3);
     344    T (int32_t, S ( 6), r_2_3);
     345    T (int32_t, S (11), r_2_3);
     346    T (int32_t, S (12), r_2_3);    // { dg-warning "\\\[-Wstringop-overflow" }
     347    T (int32_t, S (36), r_2_3);    // { dg-warning "\\\[-Wstringop-overflow" }
     348  #endif
     349  }
     350  
     351  
     352  struct Flex
     353  {
     354    char n, ax[];
     355  };
     356  
     357  #undef T
     358  #define T(T, src, n) do {			\
     359      char *s = src;				\
     360      typedef struct { T n, ax[]; } Flex;		\
     361      Flex *p = (Flex*)malloc (sizeof *p + n);	\
     362      char *d = (char*)p->ax;			\
     363      strcpy (d, s);				\
     364      sink (p);					\
     365    } while (0)
     366  
     367  NOIPA void test_strcpy_malloc_flexarray (void)
     368  {
     369    size_t r_0_1 = UR (0, 1);
     370    size_t r_1_2 = UR (1, 2);
     371    size_t r_2_3 = UR (2, 3);
     372  
     373    T (char, S (0), r_0_1);
     374    T (char, S (1), r_0_1);       // { dg-warning "\\\[-Wstringop-overflow" "pr92814" }
     375  
     376    T (char, S (0), r_1_2);
     377    T (char, S (1), r_1_2);
     378    T (char, S (2), r_1_2);       // { dg-warning "\\\[-Wstringop-overflow" "pr92814" }
     379  
     380    T (char, S (0), r_2_3);
     381    T (char, S (2), r_2_3);
     382    T (char, S (3), r_2_3);       // { dg-warning "\\\[-Wstringop-overflow" "pr92814" }
     383    T (char, S (9), r_2_3);       // { dg-warning "\\\[-Wstringop-overflow" "pr92814" }
     384  }