1  /* Verify -Wstringop-overread is issued appropriately.
       2    { dg-do compile }
       3    { dg-options "-O2 -ftrack-macro-expansion=0" } */
       4  
       5  typedef __SIZE_TYPE__ size_t;
       6  
       7  // <libint.h> functions.
       8  
       9  char* gettext (const char *);
      10  
      11  // <stdio.h> functions.
      12  
      13  int puts (const char*);
      14  int puts_unlocked (const char*);
      15  
      16  // <string.h> functions.
      17  
      18  char* strchr (const char*, int);
      19  
      20  int strcmp (const char*, const char*);
      21  int strncmp (const char*, const char*, size_t);
      22  
      23  char* strcat (char*, const char*);
      24  char* strcpy (char*, const char*);
      25  char* strncpy (char*, const char*, size_t);
      26  char* strdup (const char*);
      27  char* strndup (const char*, size_t);
      28  
      29  char* strpbrk (char*, const char*);
      30  size_t strcspn (const char*, const char*);
      31  size_t strspn (const char*, const char*);
      32  char* strstr (char*, const char*);
      33  
      34  size_t strlen (const char*);
      35  size_t strnlen (const char*, size_t);
      36  
      37  
      38  void sink (int, ...);
      39  #define sink(...) sink (0, __VA_ARGS__)
      40  
      41  extern char *d;
      42  extern char a0[0];              // { dg-message "source object 'a0'" }
      43  extern char a1[1];              // { dg-message "source object 'a1'" }
      44  extern char a2[2];              // { dg-message "source object 'a2'" }
      45  
      46  extern char b1[1];
      47  extern char b2[2];
      48  extern char bx[];
      49  
      50  const char s0[0] = { };         // { dg-message "source object 's0'" }
      51  const char s1[1] = "";          // { dg-message "source object 's1'" }
      52  const char s2[2] = "1";         // { dg-message "source object 's2'" }
      53  
      54  #define T(x) sink (0, (x))
      55  
      56  
      57  void test_strcat_array (const char *s, int i, int i0)
      58  {
      59    if (i0 < 0)
      60      i0 = 0;
      61  
      62    T (strcat (d, a0));           // { dg-warning "'strcat' reading 1 or more bytes from a region of size 0" }
      63    T (strcat (d, a0 + i));       // { dg-warning "'strcat' reading 1 or more bytes from a region of size 0" }
      64    T (strcat (d, a0 + i + 1));   // { dg-warning "'strcat' reading 1 or more bytes from a region of size 0" }
      65  
      66    T (strcat (d, a0 + i0));      // { dg-warning "'strcat' reading 1 or more bytes from a region of size 0" }
      67  
      68    T (strcat (d, a1));
      69    T (strcat (d, a1 + 1));       // { dg-warning "'strcat' reading 1 or more bytes from a region of size 0" }
      70    T (strcat (d, a1 + i));
      71    T (strcat (d, a1 + i + 1));
      72  
      73    T (strcat (d, a1 + i0));
      74    T (strcat (d, a1 + i0 + 1));  // { dg-warning "'strcat' reading 1 or more bytes from a region of size 0" }
      75  
      76    T (strcat (d, a2));
      77    T (strcat (d, a2 + 1));
      78    T (strcat (d, a2 + 2));       // { dg-warning "'strcat' reading 1 or more bytes from a region of size 0" }
      79    T (strcat (d, a2 + i));
      80    T (strcat (d, a2 + i + 2));
      81  
      82    T (strcat (d, a2 + i0));
      83    T (strcat (d, a2 + i0 + 1));
      84    T (strcat (d, a2 + i0 + 2));  // { dg-warning "'strcat' reading 1 or more bytes from a region of size 0" }
      85  
      86    // Repeat the above with the arguments reversed.
      87  
      88    T (strcat (a0, s));           // { dg-warning "'strcat' writing 1 or more bytes into a region of size 0" }
      89    T (strcat (a0 + i, s));       // { dg-warning "'strcat' writing 1 or more bytes into a region of size 0" }
      90    T (strcat (a0 + i + 1, s));   // { dg-warning "'strcat' writing 1 or more bytes into a region of size 0" }
      91  
      92    T (strcat (a0 + i0, s));      // { dg-warning "'strcat' writing 1 or more bytes into a region of size 0" }
      93  
      94    T (strcat (a1, s));
      95    T (strcat (a1 + 1, s));       // { dg-warning "'strcat' writing 1 or more bytes into a region of size 0" }
      96    T (strcat (a1 + i, s));
      97    T (strcat (a1 + i + 1, s));
      98  
      99    T (strcat (a1 + i0, s));
     100    T (strcat (a1 + i0 + 1, s));  // { dg-warning "'strcat' writing 1 or more bytes into a region of size 0" }
     101  
     102    T (strcat (a2, s));
     103    T (strcat (a2 + 1, s));
     104    T (strcat (a2 + 2, s));       // { dg-warning "'strcat' writing 1 or more bytes into a region of size 0" }
     105    T (strcat (a2 + i, s));
     106    T (strcat (a2 + i + 2, s));
     107  
     108    T (strcat (a2 + i0, s));
     109    T (strcat (a2 + i0 + 1, s));
     110    T (strcat (a2 + i0 + 2, s));  // { dg-warning "'strcat' writing 1 or more bytes into a region of size 0" }
     111  }
     112  
     113  void test_strcat_literal (int i)
     114  {
     115    T (strcat (d, ""));
     116    T (strcat (d, "" + 0));
     117    T (strcat (d, "" + i));
     118  
     119    T (strcat (d, "1"));
     120    T (strcat (d, "1" + 1));
     121    T (strcat (d, "1" + 2));      // { dg-warning "'strcat' reading 1 or more bytes from a region of size 0" }
     122    T (strcat (d, "1" + i));
     123  
     124    T (strcat (d, "12"));
     125    T (strcat (d, "12" + 1));
     126    T (strcat (d, "12" + 2));
     127    T (strcat (d, "12" + 3));     // { dg-warning "'strcat' reading 1 or more bytes from a region of size 0" }
     128    T (strcat (d, "12" + i));
     129  }
     130  
     131  void test_strcat_string (int i)
     132  {
     133    T (strcat (d, s0));           // { dg-warning "'strcat' reading 1 or more bytes from a region of size 0" }
     134    T (strcat (d, s0 + 1));       // { dg-warning "'strcat' reading 1 or more bytes from a region of size 0" }
     135    T (strcat (d, s0 + i));       // { dg-warning "'strcat' (reading 1 or more bytes from a region of size 0|argument missing terminating nul)" }
     136  
     137    T (strcat (d, s1));
     138    T (strcat (d, s1 + 1));      // { dg-warning "'strcat' reading 1 or more bytes from a region of size 0" }
     139    T (strcat (d, s1 + 2));      // { dg-warning "'strcat' reading 1 or more bytes from a region of size 0" }
     140    T (strcat (d, s1 + i));
     141  
     142    T (strcat (d, s2));
     143    T (strcat (d, s2 + 1));
     144    T (strcat (d, s2 + 2));      // { dg-warning "'strcat' reading 1 or more bytes from a region of size 0" }
     145    T (strcat (d, s2 + 3));      // { dg-warning "'strcat' reading 1 or more bytes from a region of size 0" }
     146    T (strcat (d, s2 + i));
     147  }
     148  
     149  
     150  void test_strcpy_array (int i, int i0)
     151  {
     152    if (i0 < 0)
     153      i0 = 0;
     154  
     155    T (strcpy (d, a0));           // { dg-warning "'strcpy' reading 1 or more bytes from a region of size 0" }
     156    T (strcpy (d, a0 + i));       // { dg-warning "'strcpy' reading 1 or more bytes from a region of size 0" }
     157    T (strcpy (d, a0 + i + 1));   // { dg-warning "'strcpy' reading 1 or more bytes from a region of size 0" }
     158  
     159    T (strcpy (d, a0 + i0));      // { dg-warning "'strcpy' reading 1 or more bytes from a region of size 0" }
     160  
     161    T (strcpy (d, a1));
     162    T (strcpy (d, a1 + 1));       // { dg-warning "'strcpy' reading 1 or more bytes from a region of size 0" }
     163    T (strcpy (d, a1 + i));
     164    T (strcpy (d, a1 + i + 1));
     165  
     166    T (strcpy (d, a1 + i0));
     167    T (strcpy (d, a1 + i0 + 1));  // { dg-warning "'strcpy' reading 1 or more bytes from a region of size 0" }
     168  
     169    T (strcpy (d, a2));
     170    T (strcpy (d, a2 + 1));
     171    T (strcpy (d, a2 + 2));       // { dg-warning "'strcpy' reading 1 or more bytes from a region of size 0" }
     172    T (strcpy (d, a2 + i));
     173    T (strcpy (d, a2 + i + 2));
     174  
     175    T (strcpy (d, a2 + i0));
     176    T (strcpy (d, a2 + i0 + 1));
     177    T (strcpy (d, a2 + i0 + 2));  // { dg-warning "'strcpy' reading 1 or more bytes from a region of size 0" }
     178  }
     179  
     180  void test_strcpy_literal (int i)
     181  {
     182    T (strcpy (d, ""));
     183    T (strcpy (d, "" + 0));
     184    T (strcpy (d, "" + i));
     185  
     186    T (strcpy (d, "1"));
     187    T (strcpy (d, "1" + 1));
     188    T (strcpy (d, "1" + 2));      // { dg-warning "'strcpy' reading 1 or more bytes from a region of size 0" }
     189    T (strcpy (d, "1" + i));
     190  
     191    T (strcpy (d, "12"));
     192    T (strcpy (d, "12" + 1));
     193    T (strcpy (d, "12" + 2));
     194    T (strcpy (d, "12" + 3));     // { dg-warning "'strcpy' reading 1 or more bytes from a region of size 0" }
     195    T (strcpy (d, "12" + i));
     196  }
     197  
     198  void test_strcpy_string (int i)
     199  {
     200    T (strcpy (d, s0));           // { dg-warning "'strcpy' reading 1 or more bytes from a region of size 0" }
     201    T (strcpy (d, s0 + 1));       // { dg-warning "'strcpy' reading 1 or more bytes from a region of size 0" }
     202    T (strcpy (d, s0 + i));       // { dg-warning "'strcpy' (reading 1 or more bytes from a region of size 0|argument missing terminating nul)" }
     203  
     204    T (strcpy (d, s1));
     205    T (strcpy (d, s1 + 1));      // { dg-warning "'strcpy' reading 1 or more bytes from a region of size 0" }
     206    T (strcpy (d, s1 + 2));      // { dg-warning "'strcpy' reading 1 or more bytes from a region of size 0" }
     207    T (strcpy (d, s1 + i));
     208  
     209    T (strcpy (d, s2));
     210    T (strcpy (d, s2 + 1));
     211    T (strcpy (d, s2 + 2));      // { dg-warning "'strcpy' reading 1 or more bytes from a region of size 0" }
     212    T (strcpy (d, s2 + 3));      // { dg-warning "'strcpy' reading 1 or more bytes from a region of size 0" }
     213    T (strcpy (d, s2 + i));
     214  }
     215  
     216  
     217  void test_strncpy_array (int i)
     218  {
     219    T (strncpy (d, a0, 0));
     220    T (strncpy (d, a0, 1));       // { dg-warning "'strncpy' reading 1 byte from a region of size 0" }
     221    T (strncpy (d, a0 + i, 0));
     222    T (strncpy (d, a0 + i, 1));   // { dg-warning "'strncpy' reading 1 byte from a region of size 0" }
     223  
     224    T (strncpy (d, a1, 0));
     225    T (strncpy (d, a1, 1));
     226    T (strncpy (d, a1 + 1, 0));
     227    T (strncpy (d, a1 + 1, 1));   // { dg-warning "'strncpy' reading 1 byte from a region of size 0" }
     228    T (strncpy (d, a1 + i, 0));
     229    T (strncpy (d, a1 + i, 1));
     230    T (strncpy (d, a1 + i, 2));
     231  }
     232  
     233  
     234  void test_strncpy_literal (int i, int i0)
     235  {
     236    if (i0 < 0)
     237      i0 = 0;
     238  
     239    T (strncpy (d, "", 0));
     240    T (strncpy (d, "", 1));
     241    T (strncpy (d, "", 2));
     242  
     243    T (strncpy (d, "" + i, 0));
     244    T (strncpy (d, "" + i, 1));
     245    T (strncpy (d, "" + i0, 1));
     246    T (strncpy (d, "" + i0, 1));
     247  
     248    T (strncpy (d, "" + 1, 0));
     249    T (strncpy (d, "" + 1, 1));   // { dg-warning "'strncpy' reading 1 byte from a region of size 0" }
     250  
     251    T (strncpy (d, "1", 0));
     252    T (strncpy (d, "1" + 1, 0));
     253    T (strncpy (d, "1" + 1, 1));
     254    T (strncpy (d, "1" + 1, 2));
     255    T (strncpy (d, "1" + i, 2));
     256  
     257    T (strncpy (d, "1" + 2, 0));
     258    T (strncpy (d, "1" + 2, 1));  // { dg-warning "'strncpy' reading 1 byte from a region of size 0" }
     259  }
     260  
     261  
     262  void test_strlen_array (int i, int i0)
     263  {
     264    if (i0 < 0)
     265      i0 = 0;
     266  
     267    T (strlen (a0));              // { dg-warning "'strlen' reading 1 or more bytes from a region of size 0" }
     268    T (strlen (a0 + i));          // { dg-warning "'strlen' reading 1 or more bytes from a region of size 0" }
     269    T (strlen (a0 + i + 1));      // { dg-warning "'strlen' reading 1 or more bytes from a region of size 0" }
     270  
     271    T (strlen (a0 + i0));         // { dg-warning "'strlen' reading 1 or more bytes from a region of size 0" }
     272  
     273    T (strlen (a1));
     274    T (strlen (a1 + 1));          // { dg-warning "'strlen' reading 1 or more bytes from a region of size 0" }
     275    T (strlen (a1 + i));
     276    T (strlen (a1 + i + 1));
     277  
     278    T (strlen (a1 + i0));
     279    T (strlen (a1 + i0 + 1));     // { dg-warning "'strlen' reading 1 or more bytes from a region of size 0" }
     280  
     281    T (strlen (a2));
     282    T (strlen (a2 + 1));
     283    T (strlen (a2 + 2));          // { dg-warning "'strlen' reading 1 or more bytes from a region of size 0" }
     284    T (strlen (a2 + i));
     285    T (strlen (a2 + i + 2));
     286  
     287    T (strlen (a2 + i0));
     288    T (strlen (a2 + i0 + 1));
     289    T (strlen (a2 + i0 + 2));     // { dg-warning "'strlen' reading 1 or more bytes from a region of size 0" }
     290  }
     291  
     292  
     293  void test_strnlen_array (int i, int i0, unsigned n)
     294  {
     295    if (i0 < 0)
     296      i0 = 0;
     297  
     298    T (strnlen (a0, 0));
     299    T (strnlen (a0, 1));          // { dg-warning "'strnlen' (reading 1 byte from a region of size 0|specified bound 1 exceeds source size 0)" }
     300    T (strnlen (a0, i0));
     301    T (strnlen (a0, i0 + 1));     // { dg-warning "'strnlen' (reading between 1 and \[0-9\]+ bytes from a region of size 0|specified bound \\\[1, \[0-9\]+\\\] exceeds source size 0)" }
     302    T (strnlen (a0, n));
     303    T (strnlen (a0 + i, 0));
     304    T (strnlen (a0 + i, 1));      // { dg-warning "'strnlen' (reading 1 byte from a region of size 0|specified bound 1 exceeds source size 0)" }
     305    T (strnlen (a0 + i, i0));
     306    T (strnlen (a0 + i, n));
     307    T (strnlen (a0 + i + 1, 0));
     308    T (strnlen (a0 + i + 1, 1));  // { dg-warning "'strnlen' (reading 1 byte from a region of size 0|specified bound 1 exceeds source size 0)" }
     309  
     310    T (strnlen (a0 + i0, 0));
     311    T (strnlen (a0 + i0, 1));     // { dg-warning "'strnlen' (reading 1 byte from a region of size 0|specified bound 1 exceeds source size 0)" }
     312    T (strnlen (a0 + i0, n));
     313  
     314    T (strnlen (a1, 0));
     315    T (strnlen (a1, 1));
     316    T (strnlen (a1, 2));          // { dg-warning "'strnlen' specified bound 2 exceeds source size 1" "pr87492" { xfail *-*-* } }
     317    T (strnlen (a1, n));
     318  
     319    T (strnlen (a1 + 1, 0));
     320    T (strnlen (a1 + 1, 1));      // { dg-warning "'strnlen' specified bound 1 exceeds source size 0" }
     321    T (strnlen (a1 + 1, i0));
     322    T (strnlen (a1 + 1, i0 + 1)); // { dg-warning "'strnlen' specified bound \\\[1, \\d+] exceeds source size 0" }
     323    T (strnlen (a1 + 1, n));
     324    T (strnlen (a1 + i, 0));
     325    T (strnlen (a1 + i, 1));
     326    T (strnlen (a1 + i, 2));      // { dg-warning "'strnlen' specified bound 2 exceeds source size 1" }
     327    T (strnlen (a1 + i, n));
     328    T (strnlen (a1 + i + 1, 0));
     329    T (strnlen (a1 + i + 1, 1));
     330    T (strnlen (a1 + i + 1, 2));  // { dg-warning "'strnlen' specified bound 2 exceeds source size 1" }
     331    T (strnlen (a1 + i + 1, n));
     332  
     333    T (strnlen (a1 + i0, 0));
     334    T (strnlen (a1 + i0, 1));
     335    T (strnlen (a1 + i0, 2));     // { dg-warning "'strnlen' specified bound 2 exceeds source size 1" }
     336    T (strnlen (a1 + i0, n));
     337    T (strnlen (a1 + i0 + 1, 0));
     338    T (strnlen (a1 + i0 + 1, 1)); // { dg-warning "'strnlen' specified bound 1 exceeds source size 0" }
     339    T (strnlen (a1 + i0 + 1, n));
     340  
     341    T (strnlen (a2, 0));
     342    T (strnlen (a2, 1));
     343    T (strnlen (a2, 2));
     344    T (strnlen (a2, n));
     345    T (strnlen (a2 + 1, 0));
     346    T (strnlen (a2 + 1, 1));
     347    T (strnlen (a2 + 1, 2));      // { dg-warning "'strnlen' specified bound 2 exceeds source size 1"  "pr87492" }
     348    T (strnlen (a2 + 1, n));
     349    T (strnlen (a2 + 2, 0));
     350    T (strnlen (a2 + 2, 1));      // { dg-warning "'strnlen' specified bound 1 exceeds source size 0" }
     351    T (strnlen (a2 + 2, n));
     352    T (strnlen (a2 + i, 0));
     353    T (strnlen (a2 + i, 1));
     354    T (strnlen (a2 + i, 2));
     355    T (strnlen (a2 + i + 2, 0));
     356    T (strnlen (a2 + i + 2, 1));
     357    T (strnlen (a2 + i + 2, 2));
     358    T (strnlen (a2 + i + 2, n));
     359  
     360    T (strnlen (a2 + i0, 0));
     361    T (strnlen (a2 + i0, 1));
     362    T (strnlen (a2 + i0, 2));
     363    T (strnlen (a2 + i0, 3));     // { dg-warning "'strnlen' specified bound 3 exceeds source size 2" }
     364    T (strnlen (a2 + i0, n));
     365  
     366    T (strnlen (a2 + i0 + 1, 0));
     367    T (strnlen (a2 + i0 + 1, 1));
     368    T (strnlen (a2 + i0 + 1, 2)); // { dg-warning "'strnlen' specified bound 2 exceeds source size 1" }
     369    T (strnlen (a2 + i0 + 1, n));
     370  
     371    T (strnlen (a2 + i0 + 2, 0));
     372    T (strnlen (a2 + i0 + 2, 1)); // { dg-warning "'strnlen' specified bound 1 exceeds source size 0" }
     373    T (strnlen (a2 + i0 + 2, i0));
     374    T (strnlen (a2 + i0 + 2, i0 + 1)); // { dg-warning "'strnlen' specified bound \\\[1, \\d+] exceeds source size 0" }
     375    T (strnlen (a2 + i0 + 2, n));
     376  }
     377  
     378  
     379  void test_strcmp_array (const char *s, int i)
     380  {
     381    T (strcmp (a0, ""));        // { dg-warning "'strcmp' reading 1 or more bytes from a region of size 0" "pr?????" { xfail *-*-* } }
     382  
     383    T (strcmp (a0, s));         // { dg-warning "'strcmp' reading 1 or more bytes from a region of size 0" }
     384    T (strcmp (a0 + i, s));     // { dg-warning "'strcmp' reading 1 or more bytes from a region of size 0" }
     385  
     386    T (strcmp (a1, s));
     387    T (strcmp (a1 + 1, s));     // { dg-warning "'strcmp' reading 1 or more bytes from a region of size 0" }
     388    T (strcmp (a1 + i, s));
     389    T (strcmp (a1 + i + 1, s));
     390  
     391  
     392    // Repeat the above with the arguments reversed.
     393  
     394    T (strcmp ("", a0));         // { dg-warning "'strcmp' reading 1 or more bytes from a region of size 0" "pr?????" { xfail *-*-*} }
     395  
     396    T (strcmp (s, a0));         // { dg-warning "'strcmp' reading 1 or more bytes from a region of size 0" }
     397    T (strcmp (s, a0 + i));     // { dg-warning "'strcmp' reading 1 or more bytes from a region of size 0" }
     398  
     399    T (strcmp (s, a1));
     400    T (strcmp (s, a1 + 1));     // { dg-warning "'strcmp' reading 1 or more bytes from a region of size 0" }
     401    T (strcmp (s, a1 + i));
     402    T (strcmp (s, a1 + i + 1));
     403  }
     404  
     405  /* The number of characters read is considered to be bounded not just
     406     by the third argument to strncmp but also by the length of the shorter
     407     of the two strings.  When the string length is unknowm, verify that
     408     a warning is only issued for certain reading past the end but not
     409     otherwise.  */
     410  
     411  void test_strncmp_array (const char *s, int i)
     412  {
     413    T (strncmp (a0, a0, 0));
     414  
     415    T (strncmp (a0, s, 0));
     416    T (strncmp (a0, s, 1));       // { dg-warning "'strncmp' reading 1 or more bytes from a region of size 0" "pr?????" { xfail *-*-* } }
     417  
     418    T (strncmp (a0, s, 2));       // { dg-warning "'strncmp' (reading between 1 and 2 bytes from a region of size 0|specified bound 2 exceeds source size 0)" }
     419    T (strncmp (a1, s, 0));
     420    T (strncmp (a1, s, 1));
     421    T (strncmp (a1 + 1, s, 1));   // { dg-warning "'strncmp' reading 1 byte from a region of size 0" "pr?????" { xfail *-*-*} }
     422    T (strncmp (a1, s, 1));
     423    T (strncmp (a1 + 1, s, 2));   // { dg-warning "'strncmp' (reading between 1 and 2 bytes from a region of size 0|specified bound 2 exceeds source size 0)" }
     424  
     425    T (strncmp (a2, s, 1));
     426    T (strncmp (a2, s, 2));
     427    T (strncmp (a2, s, 3));
     428  
     429    T (strncmp (a2 + 1, s, 1));
     430    T (strncmp (a2 + 2, s, 2));   // { dg-warning "'strncmp' (reading between 1 and 2 bytes from a region of size 0|specified bound 2 exceeds source size 0)" }
     431  
     432    T (strncmp (a1, b1, 0));
     433    T (strncmp (a1, b1, 1));
     434    T (strncmp (a1, b1, 2));      // { dg-warning "'strncmp' specified bound 2 exceeds source size 1" }
     435  }
     436  
     437  
     438  void test_strncmp_literal (const char *s, int i)
     439  {
     440    T (strncmp (a0, "", 0));
     441    T (strncmp (a0, "1", 0));
     442    T (strncmp (a0, "12", 0));
     443  
     444    /* The calls with a bound in excess of the length of the literal are
     445       folded early (most into strcmp) so the warning doesn't trigger.  */
     446    T (strncmp (s, "", 0));
     447  
     448    T (strncmp (s, "1", 0));
     449    T (strncmp (s, "1", 1));
     450    T (strncmp (s, "1", 2));      // { dg-warning "\\\[-Wstringop-overread" "pr93665" { xfail *-*-* } }
     451  
     452    T (strncmp (s, "12", 0));
     453    T (strncmp (s, "12", 1));
     454    T (strncmp (s, "12", 2));
     455    T (strncmp (s, "12", 3));     // { dg-warning "\\\[-Wstringop-overread" "pr93665" { xfail *-*-* } }
     456  
     457    T (strncmp (s, "123", 0));
     458    T (strncmp (s, "123", 1));
     459    T (strncmp (s, "123", 2));
     460    T (strncmp (s, "123", 3));
     461    T (strncmp (s, "123", 4));    // { dg-warning "\\\[-Wstringop-overread" "pr93665" { xfail *-*-* } }
     462  }
     463  
     464  
     465  void test_strchr_array (int x, int i)
     466  {
     467    T (strchr (a0, x));         // { dg-warning "'strchr' reading 1 or more bytes from a region of size 0" }
     468    T (strchr (a0 + i, x));     // { dg-warning "'strchr' reading 1 or more bytes from a region of size 0" }
     469  
     470    T (strchr (a1, x));
     471    T (strchr (a1 + 1, x));     // { dg-warning "'strchr' reading 1 or more bytes from a region of size 0" }
     472    T (strchr (a1 + i, x));
     473    T (strchr (a1 + i + 1, x));
     474  }
     475  
     476  
     477  void test_strdup_array (int i)
     478  {
     479    T (strdup (a0));            // { dg-warning "'strdup' reading 1 or more bytes from a region of size 0" }
     480    T (strdup (a0 + i));        // { dg-warning "'strdup' reading 1 or more bytes from a region of size 0" }
     481  
     482    T (strdup (a1));
     483    T (strdup (a1 + 1));        // { dg-warning "'strdup' reading 1 or more bytes from a region of size 0" }
     484    T (strdup (a1 + i));
     485    T (strdup (a1 + i + 1));
     486  }
     487  
     488  
     489  void test_strndup_array (int i, int i0, unsigned n)
     490  {
     491    if (i0 < 0)
     492      i0 = 0;
     493  
     494    T (strndup (a0, 0));
     495    T (strndup (a0, 1));          // { dg-warning "'strndup' (reading 1 byte from a region of size 0|specified bound 1 exceeds source size 0)" }
     496    T (strndup (a0, i0));
     497    T (strndup (a0, i0 + 1));     // { dg-warning "'strndup' (reading between 1 and \[0-9\]+ bytes from a region of size 0|specified bound \\\[1, \[0-9\]+\\\] exceeds source size 0)" }
     498    T (strndup (a0, n));
     499    T (strndup (a0 + i, 0));
     500    T (strndup (a0 + i, 1));      // { dg-warning "'strndup' (reading 1 byte from a region of size 0|specified bound 1 exceeds source size 0)" }
     501    T (strndup (a0 + i, i0));
     502    T (strndup (a0 + i, n));
     503    T (strndup (a0 + i + 1, 0));
     504    T (strndup (a0 + i + 1, 1));  // { dg-warning "'strndup' (reading 1 byte from a region of size 0|specified bound 1 exceeds source size 0)" }
     505  
     506    T (strndup (a0 + i0, 0));
     507    T (strndup (a0 + i0, 1));     // { dg-warning "'strndup' (reading 1 byte from a region of size 0|specified bound 1 exceeds source size 0)" }
     508    T (strndup (a0 + i0, n));
     509  
     510    T (strndup (a1, 0));
     511    T (strndup (a1, 1));
     512    T (strndup (a1, 2));          // { dg-warning "'strndup' specified bound 2 exceeds source size 1" }
     513    T (strndup (a1, n));
     514    T (strndup (a1 + 1, 0));
     515    T (strndup (a1 + 1, 1));      // { dg-warning "'strndup' specified bound 1 exceeds source size 0" }
     516    T (strndup (a1 + 1, i0));
     517    T (strndup (a1 + 1, i0 + 1)); // { dg-warning "'strndup' specified bound \\\[1, \\d+] exceeds source size 0" }
     518    T (strndup (a1 + 1, n));
     519    T (strndup (a1 + i, 0));
     520    T (strndup (a1 + i, 1));
     521    T (strndup (a1 + i, 2));      // { dg-warning "'strndup' specified bound 2 exceeds source size 1" }
     522    T (strndup (a1 + i, n));
     523    T (strndup (a1 + i + 1, 0));
     524    T (strndup (a1 + i + 1, 1));
     525    T (strndup (a1 + i + 1, 2));  // { dg-warning "'strndup' specified bound 2 exceeds source size 1" }
     526    T (strndup (a1 + i + 1, n));
     527  
     528    T (strndup (a1 + i0, 0));
     529    T (strndup (a1 + i0, 1));
     530    T (strndup (a1 + i0, n));
     531    T (strndup (a1 + i0 + 1, 0));
     532    T (strndup (a1 + i0 + 1, 1)); // { dg-warning "'strndup' specified bound 1 exceeds source size 0" }
     533    T (strndup (a1 + i0 + 1, n));
     534  
     535    T (strndup (a2, 0));
     536    T (strndup (a2, 1));
     537    T (strndup (a2, 2));
     538    T (strndup (a2, n));
     539    T (strndup (a2 + 1, 0));
     540    T (strndup (a2 + 1, 1));
     541    T (strndup (a2 + 1, 2));      // { dg-warning "'strndup' specified bound 2 exceeds source size 1" }
     542    T (strndup (a2 + 1, n));
     543    T (strndup (a2 + 2, 0));
     544    T (strndup (a2 + 2, 1));      // { dg-warning "'strndup' specified bound 1 exceeds source size 0" }
     545    T (strndup (a2 + 2, n));
     546    T (strndup (a2 + i, 0));
     547    T (strndup (a2 + i, 1));
     548    T (strndup (a2 + i, 2));
     549    T (strndup (a2 + i + 2, 0));
     550    T (strndup (a2 + i + 2, 1));
     551    T (strndup (a2 + i + 2, 2));
     552    T (strndup (a2 + i + 2, n));
     553  
     554    T (strndup (a2 + i0, 0));
     555    T (strndup (a2 + i0, 1));
     556    T (strndup (a2 + i0, 2));
     557    T (strndup (a2 + i0, 3));     // { dg-warning "'strndup' specified bound 3 exceeds source size 2" }
     558    T (strndup (a2 + i0, n));
     559  
     560    T (strndup (a2 + i0 + 1, 0));
     561    T (strndup (a2 + i0 + 1, 1));
     562    T (strndup (a2 + i0 + 1, 2)); // { dg-warning "'strndup' specified bound 2 exceeds source size 1" }
     563    T (strndup (a2 + i0 + 1, n));
     564  
     565    T (strndup (a2 + i0 + 2, 0));
     566    T (strndup (a2 + i0 + 2, 1)); // { dg-warning "'strndup' specified bound 1 exceeds source size 0" }
     567    T (strndup (a2 + i0 + 2, i0));
     568    T (strndup (a2 + i0 + 2, i0 + 1)); // { dg-warning "'strndup' specified bound \\\[1, \\d+] exceeds source size 0" }
     569    T (strndup (a2 + i0 + 2, n));
     570  }
     571  
     572  
     573  void test_strpbrk_array (char *s, int i)
     574  {
     575    T (strpbrk (a0, ""));       // { dg-warning "'strpbrk' reading 1 or more bytes from a region of size 0" "pr?????" { xfail *-*-* } }
     576  
     577    T (strpbrk (a0, s));        // { dg-warning "'strpbrk' reading 1 or more bytes from a region of size 0" }
     578    T (strpbrk (a0 + i, s));    // { dg-warning "'strpbrk' reading 1 or more bytes from a region of size 0" }
     579  
     580    T (strpbrk (a1, s));
     581    T (strpbrk (a1 + 1, s));    // { dg-warning "'strpbrk' reading 1 or more bytes from a region of size 0" }
     582    T (strpbrk (a1 + i, s));
     583    T (strpbrk (a1 + i + 1, s));
     584  
     585  
     586    // Repeat the above with the arguments reversed.
     587  
     588    T (strpbrk ("", a0));       // { dg-warning "'strpbrk' reading 1 or more bytes from a region of size 0" }
     589  
     590    T (strpbrk (s, a0));        // { dg-warning "'strpbrk' reading 1 or more bytes from a region of size 0" }
     591    T (strpbrk (s, a0 + i));    // { dg-warning "'strpbrk' reading 1 or more bytes from a region of size 0" }
     592  
     593    T (strpbrk (s, a1));
     594    T (strpbrk (s, a1 + 1));    // { dg-warning "'strpbrk' reading 1 or more bytes from a region of size 0" }
     595    T (strpbrk (s, a1 + i));
     596    T (strpbrk (s, a1 + i + 1));
     597  }
     598  
     599  
     600  void test_strspn_array (const char *s, int i)
     601  {
     602    T (strspn (a0, ""));        // { dg-warning "'strspn' reading 1 or more bytes from a region of size 0" "pr?????" { xfail *-*-* } }
     603  
     604    T (strspn (a0, s));         // { dg-warning "'strspn' reading 1 or more bytes from a region of size 0" }
     605    T (strspn (a0 + i, s));     // { dg-warning "'strspn' reading 1 or more bytes from a region of size 0" }
     606  
     607    T (strspn (a1, s));
     608    T (strspn (a1 + 1, s));     // { dg-warning "'strspn' reading 1 or more bytes from a region of size 0" }
     609    T (strspn (a1 + i, s));
     610    T (strspn (a1 + i + 1, s));
     611  
     612  
     613    // Repeat the above with the arguments reversed.
     614  
     615    T (strspn ("", a0));         // { dg-warning "'strspn' reading 1 or more bytes from a region of size 0" "pr?????" { xfail *-*-*} }
     616  
     617    T (strspn (s, a0));         // { dg-warning "'strspn' reading 1 or more bytes from a region of size 0" }
     618    T (strspn (s, a0 + i));     // { dg-warning "'strspn' reading 1 or more bytes from a region of size 0" }
     619  
     620    T (strspn (s, a1));
     621    T (strspn (s, a1 + 1));     // { dg-warning "'strspn' reading 1 or more bytes from a region of size 0" }
     622    T (strspn (s, a1 + i));
     623    T (strspn (s, a1 + i + 1));
     624  }
     625  
     626  
     627  void test_strcspn_array (const char *s, int i)
     628  {
     629    /* The call below is tranformed to strlen() so the warning references
     630       the latter function instead of strcspn.  Avoid testing that aspect.  */
     631    T (strcspn (a0, ""));       // { dg-warning "reading 1 or more bytes from a region of size 0" }
     632  
     633    T (strcspn (a0, s));        // { dg-warning "'strcspn' reading 1 or more bytes from a region of size 0" }
     634    T (strcspn (a0 + i, s));    // { dg-warning "'strcspn' reading 1 or more bytes from a region of size 0" }
     635  
     636    T (strcspn (a1, s));
     637    T (strcspn (a1 + 1, s));    // { dg-warning "'strcspn' reading 1 or more bytes from a region of size 0" }
     638    T (strcspn (a1 + i, s));
     639    T (strcspn (a1 + i + 1, s));
     640  
     641  
     642    // Repeat the above with the arguments reversed.
     643  
     644    T (strcspn ("", a0));       // { dg-warning "'strcspn' reading 1 or more bytes from a region of size 0" "pr?????" { xfail *-*-*} }
     645  
     646    T (strcspn (s, a0));        // { dg-warning "'strcspn' reading 1 or more bytes from a region of size 0" }
     647    T (strcspn (s, a0 + i));    // { dg-warning "'strcspn' reading 1 or more bytes from a region of size 0" }
     648  
     649    T (strcspn (s, a1));
     650    T (strcspn (s, a1 + 1));    // { dg-warning "'strcspn' reading 1 or more bytes from a region of size 0" }
     651    T (strcspn (s, a1 + i));
     652    T (strcspn (s, a1 + i + 1));
     653  }
     654  
     655  
     656  void test_strstr_array (char *s, int i)
     657  {
     658    T (strstr (a0, ""));        // { dg-warning "'strstr' reading 1 or more bytes from a region of size 0" "pr?????" { xfail *-*-* } }
     659  
     660    T (strstr (a0, s));         // { dg-warning "'strstr' reading 1 or more bytes from a region of size 0" }
     661    T (strstr (a0 + i, s));     // { dg-warning "'strstr' reading 1 or more bytes from a region of size 0" }
     662  
     663    T (strstr (a1, s));
     664    T (strstr (a1 + 1, s));     // { dg-warning "'strstr' reading 1 or more bytes from a region of size 0" }
     665    T (strstr (a1 + i, s));
     666    T (strstr (a1 + i + 1, s));
     667  
     668  
     669    // Repeat the above with the arguments reversed.
     670  
     671    T (strstr ("", a0));        // { dg-warning "'strstr' reading 1 or more bytes from a region of size 0" }
     672  
     673    T (strstr (s, a0));         // { dg-warning "'strstr' reading 1 or more bytes from a region of size 0" }
     674    T (strstr (s, a0 + i));     // { dg-warning "'strstr' reading 1 or more bytes from a region of size 0" }
     675  
     676    T (strstr (s, a1));
     677    T (strstr (s, a1 + 1));     // { dg-warning "'strstr' reading 1 or more bytes from a region of size 0" }
     678    T (strstr (s, a1 + i));
     679    T (strstr (s, a1 + i + 1));
     680  }
     681  
     682  
     683  void test_puts_array (int i)
     684  {
     685    T (puts (a0));              // { dg-warning "'puts' reading 1 or more bytes from a region of size 0" }
     686    T (puts (a0 + i));          // { dg-warning "'puts' reading 1 or more bytes from a region of size 0" }
     687  
     688    T (puts (a1));
     689    T (puts (a1 + 1));          // { dg-warning "'puts' reading 1 or more bytes from a region of size 0" }
     690    T (puts (a1 + i));
     691    T (puts (a1 + i + 1));
     692  }
     693  
     694  
     695  void test_puts_unlocked_array (int i)
     696  {
     697    T (puts_unlocked (a0));     // { dg-warning "'puts_unlocked' reading 1 or more bytes from a region of size 0" }
     698    T (puts_unlocked (a0 + i)); // { dg-warning "'puts_unlocked' reading 1 or more bytes from a region of size 0" }
     699  
     700    T (puts_unlocked (a1));
     701    T (puts_unlocked (a1 + 1)); // { dg-warning "'puts_unlocked' reading 1 or more bytes from a region of size 0" }
     702    T (puts_unlocked (a1 + i));
     703    T (puts_unlocked (a1 + i + 1));
     704  }
     705  
     706  
     707  void test_gettext_array (int i)
     708  {
     709    T (gettext (a0));           // { dg-warning "'gettext' reading 1 or more bytes from a region of size 0" }
     710    T (gettext (a0 + i));       // { dg-warning "'gettext' reading 1 or more bytes from a region of size 0" }
     711  
     712    T (gettext (a1));
     713    T (gettext (a1 + 1));       // { dg-warning "'gettext' reading 1 or more bytes from a region of size 0" }
     714    T (gettext (a1 + i));
     715    T (gettext (a1 + i + 1));
     716  }