(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.dg/
Wstringop-overflow-22.c
       1  /* { dg-do compile }
       2     { dg-options "-O2 -Wall -Wno-stringop-truncation -ftrack-macro-expansion=0" } */
       3  
       4  #define NULL (void*)0
       5  
       6  const char a[] = { 'a', 'b', 'c', 'd' };
       7  const char b[] = { 'a', '\0', 'c', '\0', 'e' };
       8  
       9  #define CONCAT(a, b) a ## b
      10  #define CAT(a, b)    CONCAT (a, b)
      11  
      12  typedef struct FILE FILE;
      13  extern FILE *fp;
      14  
      15  extern char *d;
      16  extern const char *s;
      17  extern int n;
      18  
      19  #define T(func, ...)						\
      20    __attribute__ ((noipa)) void					\
      21    CAT (test_ ## func, __LINE__) (void)				\
      22    {								\
      23      sink (0, __builtin_ ## func (__VA_ARGS__), d, s, n);	\
      24    } typedef void dummy_type
      25  
      26  void sink (void*, ...);
      27  
      28  
      29  // Exercise string functions.
      30  T (index, a, 'x');          // { dg-warning "missing terminating nul" "index" }
      31  T (index, a, *s);           // { dg-warning "missing terminating nul" "index" }
      32  
      33  T (index, b, '0');
      34  T (index, b + 1, '1');
      35  T (index, b + 2, '2');
      36  T (index, b + 3, '3');
      37  T (index, b + 4, '4');      // { dg-warning "missing terminating nul" "index" }
      38  
      39  T (rindex, a, 'x');         // { dg-warning "missing terminating nul" "rindex" }
      40  T (rindex, a, *s);          // { dg-warning "missing terminating nul" "rindex" }
      41  
      42  T (rindex, b, '0');
      43  T (rindex, b + 1, '1');
      44  T (rindex, b + 2, '2');
      45  T (rindex, b + 3, '3');
      46  T (rindex, b + 4, '4');     // { dg-warning "missing terminating nul" "rindex" }
      47  
      48  T (stpcpy, d, a);           // { dg-warning "missing terminating nul" "stpcpy" }
      49  
      50  T (stpncpy, d, a, 4);
      51  T (stpncpy, d, a, 5);       // { dg-warning "specified bound 5 exceeds the size 4 of unterminated array" "stpncpy" }
      52  T (stpncpy, d, a, n);
      53  
      54  /* When the offset into an unterminated array isn't known and the bound
      55     is less than the size of the array it suggests the access may be
      56     constrained just right.  When the bound is exactly equal to the size
      57     of the array, then the offset would have to be zero for the access to
      58     be safe, so a warning is justified.  Otherwise, the bound is too small
      59     and the access is definitely unsafe.  */
      60  T (stpncpy, d, a + n, 3);
      61  T (stpncpy, d, a + n, 4);   // { dg-warning "specified bound 4 may exceed the size of at most 4 of unterminated array" "stpncpy" }
      62  T (stpncpy, d, a + n, 5);   // { dg-warning "specified bound 5 exceeds the size of at most 4 of unterminated array" "stpncpy" }
      63  
      64  T (stpncpy, d, b, 4);
      65  T (stpncpy, d, b, 5);
      66  T (stpncpy, d, b, n);
      67  
      68  T (stpncpy, d, b + 1, 4);
      69  T (stpncpy, d, b + 1, 5);
      70  T (stpncpy, d, b + 1, n);
      71  
      72  T (stpncpy, d, b + 3, 4);
      73  T (stpncpy, d, b + 3, 5);
      74  T (stpncpy, d, b + 3, n);
      75  
      76  T (stpncpy, d, b + 4, 1);
      77  T (stpncpy, d, b + 4, 2);   // { dg-warning "specified bound 2 exceeds the size 1 of unterminated array" "stpncpy" }
      78  T (stpncpy, d, b + 4, n);
      79  /* The following might be worth warning about since it's only safe with
      80     n < 4.  */
      81  T (stpncpy, d, b + n, 5);
      82  
      83  T (strcasecmp, a, "ab");    // { dg-warning "missing terminating nul" "strcasecmp" }
      84  T (strcasecmp, a, s);       // { dg-warning "missing terminating nul" "strcasecmp" }
      85  T (strcasecmp, a, b);       // { dg-warning "missing terminating nul" "strcasecmp" }
      86  T (strcasecmp, b, b + 1);
      87  T (strcasecmp, b, b + 2);
      88  T (strcasecmp, b, b + 3);
      89  T (strcasecmp, b, b + 4);   // { dg-warning "missing terminating nul" "strcasecmp" }
      90  
      91  T (strcat, d, a);           // { dg-warning "missing terminating nul" "strcat" }
      92  
      93  T (strncat, d, a, 4);
      94  T (strncat, d, a, 5);       // { dg-warning "specified bound 5 exceeds the size 4 of unterminated array" "strncat" }
      95  T (strncat, d, a, n);
      96  
      97  T (strncat, d, b, n);
      98  T (strncat, d, b + 1, n);
      99  T (strncat, d, b + 2, n);
     100  T (strncat, d, b + 3, n);
     101  T (strncat, d, b + 4, 0);
     102  T (strncat, d, b + 4, 1);
     103  T (strncat, d, b + 4, 2);   // { dg-warning "specified bound 2 exceeds the size 1 of unterminated array" "strncat" }
     104  /* The following should probably trigger a warning since it's only safe
     105     when n < 2, makes little sense with n == 0, and not much more with
     106     n == 1.  */
     107  T (strncat, d, b + 4, n);   // { dg-warning "missing terminating nul" "strncat" { xfail *-*-* } }
     108  
     109  T (strchr, a, 'x');         // { dg-warning "missing terminating nul" "strchr" }
     110  T (strchr, a, *s);          // { dg-warning "missing terminating nul" "strchr" }
     111  
     112  T (strcmp, a, "ab");        // { dg-warning "missing terminating nul" "strcmp" }
     113  T (strcmp, "bc", a);        // { dg-warning "missing terminating nul" "strcmp" }
     114  T (strcmp, a, s);           // { dg-warning "missing terminating nul" "strcmp" }
     115  T (strcmp, s, a);           // { dg-warning "missing terminating nul" "strcmp" }
     116  
     117  T (strcmp, a, b);           // { dg-warning "missing terminating nul" "strcmp" }
     118  /* Even though most likely safe in reality because b[1] is nul,
     119     the following is strictly undefined because a is not a string.
     120     The warning is not issued because GCC folds the call to (int)*a.  */
     121  T (strcmp, a, b + 1);       // { dg-warning "missing terminating nul" "bug" { xfail *-*-* } }
     122  
     123  T (strncmp, a, "ab", 4);
     124  T (strncmp, "bc", a, 4);
     125  T (strncmp, a, a, 4);
     126  T (strncmp, a, s, 4);
     127  T (strncmp, s, a, 4);
     128  
     129  /* The warning below is not issued because GCC folds strncmp calls with
     130     the same arguments to zero before it checks for the missing nul.  */
     131  T (strncmp, a, a, 5);       // { dg-warning "missing terminating nul" "pr92624" { xfail *-*-*} }
     132  T (strncmp, a, s, 5);       // { dg-warning "specified bound 5 exceeds the size 4 of unterminated array" "strcmp" }
     133  T (strncmp, s, a, 5);       // { dg-warning "specified bound 5 exceeds the size 4 of unterminated array" "strcmp" }
     134  
     135  T (strcpy, d, a);           // { dg-warning "missing terminating nul" "strcpy" }
     136  
     137  T (strcspn, a, s);          // { dg-warning "missing terminating nul" "strcspn" }
     138  T (strcspn, s, a);          // { dg-warning "missing terminating nul" "strcspn" }
     139  
     140  T (strspn, a, s);           // { dg-warning "missing terminating nul" "strcspn" }
     141  T (strspn, s, a);           // { dg-warning "missing terminating nul" "strcspn" }
     142  
     143  T (strdup, a);              // { dg-warning "missing terminating nul" "strdup" }
     144  
     145  T (strndup, a, 4);
     146  T (strndup, a, 5);          // { dg-warning "specified bound 5 exceeds the size 4 of unterminated array" "strndup" }
     147  T (strndup, b + 3, 2);
     148  T (strndup, b + 4, 1);
     149  T (strndup, b + 4, 2);      // { dg-warning "specified bound 2 exceeds the size 1 of unterminated array" "strndup" }
     150  
     151  T (strlen, a);              // { dg-warning "missing terminating nul" "strlen" }
     152  
     153  T (strnlen, a, 4);
     154  T (strnlen, a, 5);          // { dg-warning "specified bound 5 exceeds the size 4 of unterminated array" "strnlen" }
     155  T (strnlen, a, n);
     156  
     157  T (strpbrk, s, a);          // { dg-warning "missing terminating nul" "strpbrk" }
     158  
     159  T (strrchr, a, 'x');        // { dg-warning "missing terminating nul" "strrchr" }
     160  T (strrchr, a, *s);         // { dg-warning "missing terminating nul" "strrchr" }
     161  
     162  T (strstr, a, "cde");       // { dg-warning "missing terminating nul" "strstr" }
     163  T (strstr, a, s);           // { dg-warning "missing terminating nul" "strstr" }
     164  
     165  
     166  // Exercise a few string checking functions.
     167  T (__stpcpy_chk, d, a, -1);           // { dg-warning "missing terminating nul" "stpcpy" }
     168  
     169  
     170  T (__stpncpy_chk, d, a, 4, -1);
     171  T (__stpncpy_chk, d, a, 5, -1);       // { dg-warning "specified bound 5 exceeds the size 4 of unterminated array" "stpncpy_chk" }
     172  T (__stpncpy_chk, d, a, n, -1);
     173  
     174  T (__stpncpy_chk, d, a + n, 3, -1);
     175  T (__stpncpy_chk, d, a + n, 4, -1);   // { dg-warning "specified bound 4 may exceed the size of at most 4 of unterminated array" "stpncpy_chk" }
     176  T (__stpncpy_chk, d, a + n, 5, -1);   // { dg-warning "specified bound 5 exceeds the size of at most 4 of unterminated array" "stpncpy_chk" }
     177  
     178  T (__stpncpy_chk, d, b, 4, -1);
     179  T (__stpncpy_chk, d, b, 5, -1);
     180  T (__stpncpy_chk, d, b, n, -1);
     181  
     182  T (__stpncpy_chk, d, b + 1, 4, -1);
     183  T (__stpncpy_chk, d, b + 1, 5, -1);
     184  T (__stpncpy_chk, d, b + 1, n, -1);
     185  
     186  T (__stpncpy_chk, d, b + 3, 4, -1);
     187  T (__stpncpy_chk, d, b + 3, 5, -1);
     188  T (__stpncpy_chk, d, b + 3, n, -1);
     189  
     190  T (__stpncpy_chk, d, b + 4, 1, -1);
     191  T (__stpncpy_chk, d, b + 4, 2, -1);   // { dg-warning "specified bound 2 exceeds the size 1 of unterminated array" "stpncpy_chk" }
     192  T (__stpncpy_chk, d, b + 4, n, -1);
     193  
     194  
     195  T (__strncat_chk, d, a, 4, -1);
     196  T (__strncat_chk, d, a, 5, -1);       // { dg-warning "specified bound 5 exceeds the size 4 of unterminated array" "strncat_chk" }
     197  T (__strncat_chk, d, a, n, -1);
     198  
     199  T (__strncat_chk, d, a + n, 3, -1);
     200  T (__strncat_chk, d, a + n, 4, -1);   // { dg-warning "specified bound 4 may exceed the size of at most 4 of unterminated array" "strncat_chk" }
     201  T (__strncat_chk, d, a + n, 5, -1);   // { dg-warning "specified bound 5 exceeds the size of at most 4 of unterminated array" "strncat_chk" }
     202  
     203  T (__strncat_chk, d, b, 4, -1);
     204  T (__strncat_chk, d, b, 5, -1);
     205  T (__strncat_chk, d, b, n, -1);
     206  
     207  T (__strncat_chk, d, b + 1, 4, -1);
     208  T (__strncat_chk, d, b + 1, 5, -1);
     209  T (__strncat_chk, d, b + 1, n, -1);
     210  
     211  T (__strncat_chk, d, b + 3, 4, -1);
     212  T (__strncat_chk, d, b + 3, 5, -1);
     213  T (__strncat_chk, d, b + 3, n, -1);
     214  
     215  T (__strncat_chk, d, b + 4, 1, -1);
     216  T (__strncat_chk, d, b + 4, 2, -1);   // { dg-warning "specified bound 2 exceeds the size 1 of unterminated array" "strncat_chk" }
     217  T (__strncat_chk, d, b + 4, n, -1);
     218  
     219  
     220  T (__strncpy_chk, d, a, 4, -1);
     221  T (__strncpy_chk, d, a, 5, -1);       // { dg-warning "specified bound 5 exceeds the size 4 of unterminated array" "strncpy_chk" }
     222  T (__strncpy_chk, d, a, n, -1);
     223  
     224  T (__strncpy_chk, d, a + n, 3, -1);
     225  T (__strncpy_chk, d, a + n, 4, -1);   // { dg-warning "specified bound 4 may exceed the size of at most 4 of unterminated array" "strncpy_chk" }
     226  T (__strncpy_chk, d, a + n, 5, -1);   // { dg-warning "specified bound 5 exceeds the size of at most 4 of unterminated array" "strncpy_chk" }
     227  
     228  T (__strncpy_chk, d, b, 4, -1);
     229  T (__strncpy_chk, d, b, 5, -1);
     230  T (__strncpy_chk, d, b, n, -1);
     231  
     232  T (__strncpy_chk, d, b + 1, 4, -1);
     233  T (__strncpy_chk, d, b + 1, 5, -1);
     234  T (__strncpy_chk, d, b + 1, n, -1);
     235  
     236  T (__strncpy_chk, d, b + 3, 4, -1);
     237  T (__strncpy_chk, d, b + 3, 5, -1);
     238  T (__strncpy_chk, d, b + 3, n, -1);
     239  
     240  T (__strncpy_chk, d, b + 4, 1, -1);
     241  T (__strncpy_chk, d, b + 4, 2, -1);   // { dg-warning "specified bound 2 exceeds the size 1 of unterminated array" "strncpy" }
     242  T (__strncpy_chk, d, b + 4, n, -1);
     243  
     244  
     245  // Exercise some stdio functions.
     246  T (printf, a);              // { dg-warning "unterminated format string" "printf" }
     247  T (printf, "%s", a);        // { dg-warning "not a nul-terminated string" "printf" }
     248  T (sprintf, d, "%s", a);    // { dg-warning "not a nul-terminated string" "sprintf" }
     249  T (snprintf, d, n, "%s", a);    // { dg-warning "not a nul-terminated string" "sprintf" }
     250  
     251  T (__sprintf_chk, d, 0, -1, "%s", a);      // { dg-warning "not a nul-terminated string" "sprintf" }
     252  T (__snprintf_chk, d, n, 0, -1, "%s", a);  // { dg-warning "not a nul-terminated string" "sprintf" }
     253  
     254  T (fputs, a, fp);           // { dg-warning "missing terminating nul" "fputs" }
     255  T (fputs_unlocked, a, fp);  // { dg-warning "missing terminating nul" "fputs_unlocked" }
     256  T (puts, a);                // { dg-warning "missing terminating nul" "puts" }
     257  T (puts_unlocked, a);       // { dg-warning "missing terminating nul" "puts_unlocked" }
     258  
     259  
     260  
     261  // Exerise exec functions.
     262  T (execl, a, s, NULL);      // { dg-warning "missing terminating nul" "execl" }
     263  T (execle, a, s, NULL, NULL);   // { dg-warning "missing terminating nul" "execle" }
     264  T (execlp, a, s, NULL);     // { dg-warning "missing terminating nul" "execlp" }
     265  
     266  T (execv, a, &d);           // { dg-warning "missing terminating nul" "execv" }
     267  T (execve, a, &d, &d);      // { dg-warning "missing terminating nul" "execve" }
     268  T (execvp, a, &d);          // { dg-warning "missing terminating nul" "execvp" }
     269  
     270  T (gettext, a);             // { dg-warning "missing terminating nul" "gettext" }
     271  
     272  T (strfmon, d, n, a);       // { dg-warning "unterminated format string" "strfmon" }