(root)/
gcc-13.2.0/
gcc/
testsuite/
c-c++-common/
attr-nonstring-3.c
       1  /* Test to exercise warnings when an array declared with attribute "nonstring"
       2     is passed to a function that expects a nul-terminated string as an argument.
       3     { dg-do compile }
       4     { dg-options "-O2 -Wattributes -Wstringop-overflow -ftrack-macro-expansion=0" }  */
       5  
       6  typedef __SIZE_TYPE__       size_t;
       7  typedef __builtin_va_list   va_list;
       8  
       9  #if __cplusplus
      10  extern "C" {
      11  #endif
      12  
      13  void* memchr (const void*, int, size_t);
      14  int memcmp (const void*, const void*, size_t);
      15  void* memcpy (void*, const void*, size_t);
      16  void* memmove (void*, const void*, size_t);
      17  
      18  int printf (const char*, ...);
      19  int puts (const char*);
      20  int puts_unlocked (const char*);
      21  int sprintf (char*, const char*, ...);
      22  int snprintf (char*, size_t, const char*, ...);
      23  int vsprintf (char*, const char*, va_list);
      24  int vsnprintf (char*, size_t, const char*, va_list);
      25  
      26  int strcmp (const char*, const char*);
      27  int strncmp (const char*, const char*, size_t);
      28  
      29  char* stpcpy (char*, const char*);
      30  char* stpncpy (char*, const char*, size_t);
      31  
      32  char* strcat (char*, const char*);
      33  char* strncat (char*, const char*, size_t);
      34  
      35  char* strcpy (char*, const char*);
      36  char* strncpy (char*, const char*, size_t);
      37  
      38  char* strchr (const char*, int);
      39  char* strdup (const char*);
      40  size_t strlen (const char*);
      41  size_t strnlen (const char*, size_t);
      42  char* strndup (const char*, size_t);
      43  
      44  #if __cplusplus
      45  }   /* extern "C" */
      46  #endif
      47  
      48  #define NONSTRING __attribute__ ((nonstring))
      49  
      50  /* STR needs to be bigger than ARR to trigger warnings, otherwise
      51     since STR must be a string, using both in a string function
      52     can be assumed to be safe even if ARR isn't nul-terminated.  */
      53  char str[5];
      54  char arr[4] NONSTRING;
      55  
      56  char *ptr;
      57  char *parr NONSTRING;
      58  
      59  struct MemArrays
      60  {
      61    char str[5];
      62    char arr[4] NONSTRING;
      63    char *parr NONSTRING;
      64  };
      65  
      66  void sink (int, ...);
      67  
      68  
      69  #define T(call)  sink (0, call)
      70  
      71  void test_printf (struct MemArrays *p)
      72  {
      73    T (printf (str));
      74    T (printf (arr));             /* { dg-warning "argument 1 declared attribute .nonstring." } */
      75  
      76    T (printf (ptr));
      77    T (printf (parr));            /* { dg-warning "argument 1 declared attribute .nonstring." } */
      78  
      79    T (printf (p->str));
      80    T (printf (p->arr));          /* { dg-warning "argument 1 declared attribute .nonstring." } */
      81  }
      82  
      83  
      84  void test_puts (struct MemArrays *p)
      85  {
      86    T (puts (str));
      87    T (puts (arr));               /* { dg-warning "argument 1 declared attribute .nonstring." } */
      88  
      89    T (puts (ptr));
      90    T (puts (parr));              /* { dg-warning "argument 1 declared attribute .nonstring." } */
      91  
      92    T (puts (p->str));
      93    T (puts (p->arr));            /* { dg-warning "argument 1 declared attribute .nonstring." } */
      94  }
      95  
      96  
      97  void test_snprintf (char *d, size_t n, struct MemArrays *p)
      98  {
      99    T (snprintf (d, n, str));
     100    T (snprintf (d, n, arr));       /* { dg-warning "argument 3 declared attribute .nonstring." } */
     101  
     102    T (snprintf (d, n, ptr));
     103    T (snprintf (d, n, parr));      /* { dg-warning "argument 3 declared attribute .nonstring." } */
     104  
     105    T (snprintf (d, n, p->str));
     106    T (snprintf (d, n, p->arr));    /* { dg-warning "argument 3 declared attribute .nonstring." } */
     107  }
     108  
     109  
     110  void test_sprintf (char *d, struct MemArrays *p)
     111  {
     112    T (sprintf (d, str));
     113    T (sprintf (d, arr));           /* { dg-warning "argument 2 declared attribute .nonstring." } */
     114  
     115    T (sprintf (d, ptr));
     116    T (sprintf (d, parr));          /* { dg-warning "argument 2 declared attribute .nonstring." } */
     117  
     118    T (sprintf (d, p->str));
     119    T (sprintf (d, p->arr));        /* { dg-warning "argument 2 declared attribute .nonstring." } */
     120  }
     121  
     122  
     123  void test_vsnprintf (char *d, size_t n, struct MemArrays *p, va_list va)
     124  {
     125    T (vsnprintf (d, n, str, va));
     126    T (vsnprintf (d, n, arr, va));  /* { dg-warning "argument 3 declared attribute .nonstring." } */
     127  
     128    T (vsnprintf (d, n, ptr, va));
     129    T (vsnprintf (d, n, parr, va)); /* { dg-warning "argument 3 declared attribute .nonstring." } */
     130  
     131    T (vsnprintf (d, n, p->str, va));
     132    T (vsnprintf (d, n, p->arr, va)); /* { dg-warning "argument 3 declared attribute .nonstring." } */
     133  }
     134  
     135  
     136  void test_vsprintf (char *d, struct MemArrays *p, va_list va)
     137  {
     138    T (vsprintf (d, str, va));
     139    T (vsprintf (d, arr, va));      /* { dg-warning "argument 2 declared attribute .nonstring." } */
     140  
     141    T (vsprintf (d, ptr, va));
     142    T (vsprintf (d, parr, va));     /* { dg-warning "argument 2 declared attribute .nonstring." } */
     143  
     144    T (vsprintf (d, p->str, va));
     145    T (vsprintf (d, p->arr, va));   /* { dg-warning "argument 2 declared attribute .nonstring." } */
     146  }
     147  
     148  
     149  void test_strcmp (struct MemArrays *p)
     150  {
     151    T (strcmp (str, str));
     152    T (strcmp (str, arr));          /* { dg-warning "argument 2 declared attribute .nonstring." } */
     153    T (strcmp (arr, str));          /* { dg-warning "argument 1 declared attribute .nonstring." } */
     154  
     155    T (strcmp (str, ptr));
     156    T (strcmp (str, parr));         /* { dg-warning "argument 2 declared attribute .nonstring." } */
     157    T (strcmp (parr, str));         /* { dg-warning "argument 1 declared attribute .nonstring." } */
     158  
     159    T (strcmp (p->str, p->arr));    /* { dg-warning "argument 2 declared attribute .nonstring." } */
     160    T (strcmp (p->arr, p->str));    /* { dg-warning "argument 1 declared attribute .nonstring." } */
     161    T (strcmp (p->parr, p->str));   /* { dg-warning "argument 1 declared attribute .nonstring." } */
     162  }
     163  
     164  
     165  void test_strncmp_warn (struct MemArrays *p)
     166  {
     167    enum { N = sizeof arr };
     168    T (strncmp (str, arr, N));
     169    T (strncmp (arr, str, N));
     170  
     171    T (strncmp (str, arr, N + 1));   /* { dg-warning "argument 2 declared attribute .nonstring. is smaller than the specified bound 5" } */
     172    T (strncmp (arr, str, N + 1));   /* { dg-warning "argument 1 declared attribute .nonstring. is smaller than the specified bound 5" } */
     173  
     174    T (strncmp (str, parr, N + 1));
     175    T (strncmp (parr, str, N + 1));
     176  
     177    T (strncmp (p->str, p->arr, N));
     178    T (strncmp (p->arr, p->str, N));
     179    T (strncmp (p->parr, p->str, N));
     180  
     181    T (strncmp (p->str, p->arr, N));
     182    T (strncmp (p->arr, p->str, N));
     183    T (strncmp (p->parr, p->str, N));
     184  }
     185  
     186  
     187  void test_strncmp_nowarn (struct MemArrays *p, size_t n)
     188  {
     189    T (strncmp (str, str, n));
     190    T (strncmp (str, arr, n));
     191    T (strncmp (arr, str, n));
     192  
     193    T (strncmp (str, ptr, n));
     194    T (strncmp (str, parr, n));
     195    T (strncmp (parr, str, n));
     196  
     197    T (strncmp (p->str, p->arr, n));
     198    T (strncmp (p->arr, p->str, n));
     199    T (strncmp (p->parr, p->str, n));
     200  }
     201  
     202  
     203  void test_stpcpy (struct MemArrays *p)
     204  {
     205    T (stpcpy (str, str));
     206    T (stpcpy (str, arr));          /* { dg-warning "argument 2 declared attribute .nonstring." } */
     207    T (stpcpy (arr, str));
     208  
     209    T (stpcpy (str, ptr));
     210    T (stpcpy (str, parr));         /* { dg-warning "argument 2 declared attribute .nonstring." } */
     211    T (stpcpy (parr, str));
     212  
     213    T (stpcpy (p->str, p->arr));    /* { dg-warning "argument 2 declared attribute .nonstring." } */
     214    T (stpcpy (p->arr, p->str));
     215    T (stpcpy (p->parr, p->str));
     216  }
     217  
     218  
     219  void test_stpncpy_nowarn (struct MemArrays *p, unsigned n)
     220  {
     221    T (stpncpy (str, str, n));
     222    T (stpncpy (str, arr, n));
     223    T (stpncpy (arr, str, n));
     224  
     225    T (stpncpy (str, ptr, n));
     226    T (stpncpy (str, parr, n));
     227    T (stpncpy (parr, str, n));
     228  
     229    T (stpncpy (p->str, p->arr, n));
     230    T (stpncpy (p->arr, p->str, n));
     231    T (stpncpy (p->parr, p->str, n));
     232  }
     233  
     234  
     235  void test_stpncpy_warn (struct MemArrays *p, unsigned n)
     236  {
     237    enum { N = sizeof arr };
     238  
     239    T (stpncpy (str, str, N));
     240    T (stpncpy (str, arr, N));
     241    T (stpncpy (arr, str, N));
     242  
     243    T (stpncpy (str, ptr, N));
     244    T (stpncpy (str, parr, N));
     245    T (stpncpy (parr, str, N));
     246  
     247    T (stpncpy (p->str, p->arr, N));
     248    T (stpncpy (p->arr, p->str, N));
     249    T (stpncpy (p->parr, p->str, N));
     250  
     251    T (stpncpy (ptr, str, N + 1));
     252    T (stpncpy (ptr, arr, N + 1));          /* { dg-warning "argument 2 declared attribute .nonstring. is smaller than the specified bound 5" } */
     253    T (stpncpy (arr, str, N + 1));          /* { dg-warning "writing 5 bytes into a region of size 4 overflows " } */
     254  
     255    T (stpncpy (ptr, ptr, N + 1));
     256    T (stpncpy (ptr, parr, N + 1));
     257    T (stpncpy (parr, str, N + 1));
     258  
     259    T (stpncpy (ptr, p->arr, N + 1));       /* { dg-warning "argument 2 declared attribute .nonstring. is smaller" } */
     260    T (stpncpy (p->arr, p->str, N + 1));    /* { dg-warning "writing 5 bytes into a region of size 4 overflows " } */
     261    T (stpncpy (p->parr, p->str, N + 1));
     262  }
     263  
     264  
     265  void test_strcat (struct MemArrays *p)
     266  {
     267    T (strcat (str, str));
     268    T (strcat (str, arr));          /* { dg-warning "argument 2 declared attribute .nonstring." } */
     269    T (strcat (arr, str));
     270  
     271    T (strcat (str, ptr));
     272    T (strcat (str, parr));         /* { dg-warning "argument 2 declared attribute .nonstring." } */
     273    T (strcat (parr, str));
     274  
     275    T (strcat (p->str, p->arr));    /* { dg-warning "argument 2 declared attribute .nonstring." } */
     276    T (strcat (p->arr, p->str));
     277    T (strcat (p->parr, p->str));
     278  }
     279  
     280  
     281  void test_strncat (struct MemArrays *p, unsigned n)
     282  {
     283    T (strncat (str, str, n));
     284    T (strncat (str, arr, n));      /* { dg-warning "argument 2 declared attribute .nonstring." } */
     285    T (strncat (arr, str, n));
     286  
     287    T (strncat (str, ptr, n));
     288    T (strncat (str, parr, n));     /* { dg-warning "argument 2 declared attribute .nonstring." } */
     289    T (strncat (parr, str, n));
     290  
     291    T (strncat (p->str, p->arr, n));   /* { dg-warning "argument 2 declared attribute .nonstring." } */
     292    T (strncat (p->arr, p->str, n));
     293    T (strncat (p->parr, p->str, n));
     294  }
     295  
     296  
     297  void test_strcpy (struct MemArrays *p)
     298  {
     299    T (strcpy (str, str));
     300    T (strcpy (str, arr));          /* { dg-warning "argument 2 declared attribute .nonstring." } */
     301    T (strcpy (arr, str));
     302  
     303    T (strcpy (str, ptr));
     304    T (strcpy (str, parr));         /* { dg-warning "argument 2 declared attribute .nonstring." } */
     305    T (strcpy (parr, str));
     306  
     307    T (strcpy (p->str, p->arr));    /* { dg-warning "argument 2 declared attribute .nonstring." } */
     308    T (strcpy (p->arr, p->str));
     309    T (strcpy (p->parr, p->str));
     310  }
     311  
     312  
     313  void test_strncpy (struct MemArrays *p, unsigned n)
     314  {
     315    T (strncpy (str, str, n));
     316    T (strncpy (str, arr, n));
     317    T (strncpy (arr, str, n));
     318  
     319    T (strncpy (str, ptr, n));
     320    T (strncpy (str, parr, n));
     321    T (strncpy (parr, str, n));
     322  
     323    T (strncpy (p->str, p->arr, n));
     324    T (strncpy (p->arr, p->str, n));
     325    T (strncpy (p->parr, p->str, n));
     326  }
     327  
     328  
     329  void test_strchr (struct MemArrays *p, int c)
     330  {
     331    T (strchr (str, c));
     332    T (strchr (arr, c));          /* { dg-warning "argument 1 declared attribute .nonstring." } */
     333  
     334    T (strchr (ptr, c));
     335    T (strchr (parr, c));         /* { dg-warning "argument 1 declared attribute .nonstring." } */
     336  
     337    T (strchr (p->str, c));
     338    T (strchr (p->arr, c));       /* { dg-warning "argument 1 declared attribute .nonstring." } */
     339  }
     340  
     341  
     342  void test_strdup (struct MemArrays *p)
     343  {
     344    T (strdup (str));
     345    T (strdup (arr));             /* { dg-warning "argument 1 declared attribute .nonstring." } */
     346  
     347    T (strdup (ptr));
     348    T (strdup (parr));            /* { dg-warning "argument 1 declared attribute .nonstring." } */
     349  
     350    T (strdup (p->str));
     351    T (strdup (p->arr));          /* { dg-warning "argument 1 declared attribute .nonstring." } */
     352  }
     353  
     354  
     355  void test_stnrdup_nowarn (struct MemArrays *p, size_t n)
     356  {
     357    T (strndup (str, n));
     358    T (strndup (arr, n));
     359  
     360    T (strndup (ptr, n));
     361    T (strndup (parr, n));
     362  
     363    T (strndup (p->str, n));
     364    T (strndup (p->arr, n));
     365  }
     366  
     367  
     368  void test_stnrdup_warn (struct MemArrays *p)
     369  {
     370    enum { N = sizeof arr };
     371  
     372    T (strndup (str, N));
     373    T (strndup (arr, N));
     374  
     375    T (strndup (ptr, N));
     376    T (strndup (parr, N));
     377  
     378    T (strndup (p->str, N));
     379    T (strndup (p->arr, N));
     380  
     381  
     382    T (strndup (arr, N + 1));     /* { dg-warning "argument 1 declared attribute 'nonstring' is smaller than the specified bound 5|specified bound 5 exceeds source size 4" } */
     383    T (strndup (parr, N + 1));
     384    T (strndup (p->arr, N + 1));  /* { dg-warning "argument 1 declared attribute 'nonstring' is smaller than the specified bound 5|specified bound 5 exceeds source size 4" } */
     385    T (strndup (p->parr, N + 1));
     386  }
     387  
     388  
     389  void test_strlen (struct MemArrays *p, char *s NONSTRING, size_t n)
     390  {
     391    T (strlen (str));
     392    T (strlen (arr));             /* { dg-warning "argument 1 declared attribute .nonstring." } */
     393  
     394    T (strlen (ptr));
     395    T (strlen (parr));            /* { dg-warning "argument 1 declared attribute .nonstring." } */
     396  
     397    T (strlen (p->str));
     398    T (strlen (p->arr));          /* { dg-warning "argument 1 declared attribute .nonstring." } */
     399  
     400    T (strlen (s));               /* { dg-warning "argument 1 declared attribute .nonstring." } */
     401    {
     402      strcpy (s, "123");
     403      T (strlen (s));
     404    }
     405  
     406    {
     407      char a[] __attribute__ ((nonstring)) = { 1, 2, 3 };
     408  
     409      T (strlen (a));             /* { dg-warning "argument 1 declared attribute .nonstring." } */
     410    }
     411  
     412    {
     413      char a[] __attribute__ ((nonstring)) = { 1, 2, 3, 4 };
     414  
     415      strcpy (a, "12");
     416      T (strlen (a));
     417    }
     418  
     419    {
     420      char *p __attribute__ ((nonstring));
     421      p = (char *)__builtin_malloc (n);
     422      __builtin_memset (p, '*', n);
     423  
     424      T (strlen (p));             /* { dg-warning "argument 1 declared attribute .nonstring." } */
     425  
     426      strcpy (p, "12345");
     427      T (strlen (p));
     428    }
     429  }
     430  
     431  
     432  void test_strnlen (struct MemArrays *p, size_t n)
     433  {
     434    T (strnlen (str, n));
     435    T (strnlen (arr, n));
     436  
     437    T (strnlen (ptr, n));
     438    T (strnlen (parr, n));
     439  
     440    T (strnlen (p->str, n));
     441    T (strnlen (p->arr, n));
     442  }
     443  
     444  
     445  /* Verify no warnings are issued for raw mempory functions.  */
     446  
     447  void test_mem_functions (struct MemArrays *p, int c, size_t n)
     448  {
     449    T (memchr (arr, c, n));
     450    T (memchr (parr, c, n));
     451    T (memchr (p->arr, c, n));
     452    T (memchr (p->parr, c, n));
     453  
     454    T (memcmp (str, arr, n));
     455    T (memcmp (arr, str, n));
     456    T (memcmp (str, parr, n));
     457    T (memcmp (parr, str, n));
     458    T (memcmp (p->str, p->arr, n));
     459    T (memcmp (p->arr, p->str, n));
     460    T (memcmp (p->parr, p->str, n));
     461  
     462    T (memcpy (str, arr, n));
     463    T (memcpy (arr, str, n));
     464    T (memcpy (str, parr, n));
     465    T (memcpy (parr, str, n));
     466    T (memcpy (p->str, p->arr, n));
     467    T (memcpy (p->arr, p->str, n));
     468    T (memcpy (p->parr, p->str, n));
     469  
     470    T (memmove (str, arr, n));
     471    T (memmove (arr, str, n));
     472    T (memmove (str, parr, n));
     473    T (memmove (parr, str, n));
     474    T (memmove (p->str, p->arr, n));
     475    T (memmove (p->arr, p->str, n));
     476    T (memmove (p->parr, p->str, n));
     477  }