(root)/
glibc-2.38/
string/
stratcliff.c
       1  /* Test for string function add boundaries of usable memory.
       2     Copyright (C) 1996-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #define _GNU_SOURCE 1
      20  
      21  /* Make sure we don't test the optimized inline functions if we want to
      22     test the real implementation.  */
      23  #undef __USE_STRING_INLINES
      24  
      25  #include <errno.h>
      26  #include <stdio.h>
      27  #include <string.h>
      28  #include <unistd.h>
      29  #include <sys/mman.h>
      30  #include <sys/param.h>
      31  
      32  #ifndef CHAR
      33  # define L(c) c
      34  # define CHAR char
      35  # define MEMSET memset
      36  # define STRLEN strlen
      37  # define STRNLEN strnlen
      38  # define STRCHR strchr
      39  # define STRRCHR strrchr
      40  # define STRCPY strcpy
      41  # define STRNCPY strncpy
      42  # define MEMCMP memcmp
      43  # define STPCPY stpcpy
      44  # define STPNCPY stpncpy
      45  # define MEMCPY memcpy
      46  # define MEMPCPY mempcpy
      47  # define MEMCHR memchr
      48  # define STRCMP strcmp
      49  # define STRNCMP strncmp
      50  #endif
      51  
      52  
      53  #define STRINGIFY(s) STRINGIFY2 (s)
      54  #define STRINGIFY2(s) #s
      55  
      56  
      57  int
      58  do_test (void)
      59  {
      60    size_t size = sysconf (_SC_PAGESIZE);
      61    size_t nchars = size / sizeof (CHAR);
      62    CHAR *adr;
      63    CHAR *dest;
      64    int result = 0;
      65  
      66    adr = (CHAR *) mmap (NULL, 3 * size, PROT_READ | PROT_WRITE,
      67  		       MAP_PRIVATE | MAP_ANON, -1, 0);
      68    dest = (CHAR *) mmap (NULL, 3 * size, PROT_READ | PROT_WRITE,
      69  			MAP_PRIVATE | MAP_ANON, -1, 0);
      70    if (adr == MAP_FAILED || dest == MAP_FAILED)
      71      {
      72        if (errno == ENOSYS)
      73  	puts ("No test, mmap not available.");
      74        else
      75  	{
      76  	  printf ("mmap failed: %m");
      77  	  result = 1;
      78  	}
      79      }
      80    else
      81      {
      82        size_t inner, middle, outer, nchars64, max128;
      83  
      84        if (nchars > 64)
      85  	nchars64 = nchars - 64;
      86        else
      87  	nchars64 = 0;
      88  
      89        if (nchars > 128)
      90  	max128 = nchars - 128;
      91        else
      92  	max128 = 0;
      93  
      94        mprotect (adr, size, PROT_NONE);
      95        mprotect (adr + 2 * nchars, size, PROT_NONE);
      96        adr += nchars;
      97  
      98        mprotect (dest, size, PROT_NONE);
      99        mprotect (dest + 2 * nchars, size, PROT_NONE);
     100        dest += nchars;
     101  
     102        MEMSET (adr, L('T'), nchars);
     103  
     104        /* strlen/wcslen test */
     105        for (outer = nchars - 1; outer >= max128; --outer)
     106  	{
     107  	  for (inner = MAX (outer, nchars64); inner < nchars; ++inner)
     108  	    {
     109  	      adr[inner] = L('\0');
     110  
     111  	      if (STRLEN (&adr[outer]) != (size_t) (inner - outer))
     112  		{
     113  		  printf ("%s flunked for outer = %zu, inner = %zu\n",
     114  			  STRINGIFY (STRLEN), outer, inner);
     115  		  result = 1;
     116  		}
     117  
     118  	      adr[inner] = L('T');
     119  	    }
     120  	  if (outer == 0)
     121  	    break;
     122  	}
     123  
     124        /* strnlen/wcsnlen test */
     125        for (outer = nchars; outer >= max128; --outer)
     126  	{
     127  	  for (inner = MAX (outer, nchars64); inner < nchars; ++inner)
     128  	    {
     129  	      adr[inner] = L('\0');
     130  
     131  	      if (STRNLEN (&adr[outer], inner - outer + 1)
     132  		  != (size_t) (inner - outer))
     133  		{
     134  		  printf ("%s flunked for outer = %zu, inner = %zu\n",
     135  			  STRINGIFY (STRNLEN), outer, inner);
     136  		  result = 1;
     137  		}
     138  
     139  	      adr[inner] = L('T');
     140  	    }
     141  	  if (outer == 0)
     142  	    break;
     143  	}
     144        for (outer = nchars; outer >= max128; --outer)
     145  	{
     146  	  for (inner = MAX (outer, nchars64); inner <= nchars; ++inner)
     147  	    {
     148  	      if (STRNLEN (&adr[outer], inner - outer)
     149  		  != (size_t) (inner - outer))
     150  		{
     151  		  printf ("%s flunked bounded for outer = %zu, inner = %zu\n",
     152  			  STRINGIFY (STRNLEN), outer, inner);
     153  		  result = 1;
     154  		}
     155  	    }
     156  	  if (outer == 0)
     157  	    break;
     158  	}
     159  
     160        /* strchr/wcschr test */
     161        for (outer = nchars - 1; outer >= max128; --outer)
     162  	{
     163  	  for (middle = MAX (outer, nchars64); middle < nchars; ++middle)
     164  	    {
     165  	      for (inner = middle; inner < nchars; ++inner)
     166  		{
     167  		  adr[middle] = L('V');
     168  		  adr[inner] = L('\0');
     169  
     170  		  CHAR *cp = STRCHR (&adr[outer], L('V'));
     171  
     172  		  if ((inner == middle && cp != NULL)
     173  		      || (inner != middle
     174  			  && (cp - &adr[outer]) != middle - outer))
     175  		    {
     176  		      printf ("%s flunked for outer = %zu, middle = %zu, "
     177  			      "inner = %zu\n",
     178  			      STRINGIFY (STRCHR), outer, middle, inner);
     179  		      result = 1;
     180  		    }
     181  
     182  		  adr[inner] = L('T');
     183  		  adr[middle] = L('T');
     184  		}
     185  	    }
     186  	  if (outer == 0)
     187  	    break;
     188  	}
     189  
     190        /* Special test.  */
     191        adr[nchars - 1] = L('\0');
     192        if (STRCHR (&adr[nchars - 1], L('\n')) != NULL)
     193  	{
     194  	  printf ("%s flunked test of empty string at end of page\n",
     195  		  STRINGIFY (STRCHR));
     196  	  result = 1;
     197  	}
     198  
     199        /* strrchr/wcsrchr test */
     200        for (outer = nchars - 1; outer >= max128; --outer)
     201  	{
     202  	  for (middle = MAX (outer, nchars64); middle < nchars; ++middle)
     203  	    {
     204  	      for (inner = middle; inner < nchars; ++inner)
     205  		{
     206  		  adr[middle] = L('V');
     207  		  adr[inner] = L('\0');
     208  
     209  		  CHAR *cp = STRRCHR (&adr[outer], L('V'));
     210  
     211  		  if ((inner == middle && cp != NULL)
     212  		      || (inner != middle
     213  			  && (cp - &adr[outer]) != middle - outer))
     214  		    {
     215  		      printf ("%s flunked for outer = %zu, middle = %zu, "
     216  			      "inner = %zu\n",
     217  			      STRINGIFY (STRRCHR), outer, middle, inner);
     218  		      result = 1;
     219  		    }
     220  
     221  		  adr[inner] = L('T');
     222  		  adr[middle] = L('T');
     223  		}
     224  	    }
     225  	  if (outer == 0)
     226  	    break;
     227  	}
     228  
     229        /* memchr test */
     230        for (outer = nchars - 1; outer >= max128; --outer)
     231  	{
     232  	  for (middle = MAX (outer, nchars64); middle < nchars; ++middle)
     233  	    {
     234  	      adr[middle] = L('V');
     235  
     236  	      CHAR *cp = MEMCHR (&adr[outer], L('V'), 3 * size);
     237  
     238  	      if (cp - &adr[outer] != middle - outer)
     239  		{
     240  		  printf ("%s flunked for outer = %zu, middle = %zu\n",
     241  			  STRINGIFY (MEMCHR), outer, middle);
     242  		  result = 1;
     243  		}
     244  
     245  	      adr[middle] = L('T');
     246  	    }
     247  	  if (outer == 0)
     248  	    break;
     249  	}
     250        for (outer = nchars; outer >= max128; --outer)
     251  	{
     252  	  CHAR *cp = MEMCHR (&adr[outer], L('V'), nchars - outer);
     253  
     254  	  if (cp != NULL)
     255  	    {
     256  	      printf ("%s flunked for outer = %zu\n",
     257  		      STRINGIFY (MEMCHR), outer);
     258  	      result = 1;
     259  	    }
     260  	  if (outer == 0)
     261  	    break;
     262  	}
     263  
     264        /* These functions only exist for single-byte characters.  */
     265  #ifndef WCSTEST
     266        /* rawmemchr test */
     267        for (outer = nchars - 1; outer >= max128; --outer)
     268  	{
     269  	  for (middle = MAX (outer, nchars64); middle < nchars; ++middle)
     270  	    {
     271  	      adr[middle] = L('V');
     272  
     273  	      CHAR *cp = rawmemchr (&adr[outer], L('V'));
     274  
     275  	      if (cp - &adr[outer] != middle - outer)
     276  		{
     277  		  printf ("%s flunked for outer = %zu, middle = %zu\n",
     278  			  STRINGIFY (rawmemchr), outer, middle);
     279  		  result = 1;
     280  		}
     281  
     282  	      adr[middle] = L('T');
     283  	    }
     284  	  if (outer == 0)
     285  	    break;
     286  	}
     287  
     288        /* memrchr test */
     289        for (outer = nchars - 1; outer >= max128; --outer)
     290  	{
     291  	  for (middle = MAX (outer, nchars64); middle < nchars; ++middle)
     292  	    {
     293  	      adr[middle] = L('V');
     294  
     295  	      CHAR *cp = memrchr (&adr[outer], L('V'), nchars - outer);
     296  
     297  	      if (cp - &adr[outer] != middle - outer)
     298  		{
     299  		  printf ("%s flunked for outer = %zu, middle = %zu\n",
     300  			  STRINGIFY (memrchr), outer, middle);
     301  		  result = 1;
     302  		}
     303  
     304  	      adr[middle] = L('T');
     305  	    }
     306  	  if (outer == 0)
     307  	    break;
     308  	}
     309        for (outer = nchars; outer >= max128; --outer)
     310  	{
     311  	  CHAR *cp = memrchr (&adr[outer], L('V'), nchars - outer);
     312  
     313  	  if (cp != NULL)
     314  	    {
     315  	      printf ("%s flunked for outer = %zu\n",
     316  		      STRINGIFY (memrchr), outer);
     317  	      result = 1;
     318  	    }
     319  	  if (outer == 0)
     320  	    break;
     321  	}
     322  #endif
     323  
     324        /* strcpy/wcscpy test */
     325        for (outer = nchars - 1; outer >= max128; --outer)
     326  	{
     327  	  for (inner = MAX (outer, nchars64); inner < nchars; ++inner)
     328  	    {
     329  	      adr[inner] = L('\0');
     330  
     331  	      if (STRCPY (dest, &adr[outer]) != dest
     332  		  || STRLEN (dest) != (size_t) (inner - outer))
     333  		{
     334  		  printf ("%s flunked for outer = %zu, inner = %zu\n",
     335  			  STRINGIFY (STRCPY), outer, inner);
     336  		  result = 1;
     337  		}
     338  
     339  	      adr[inner] = L('T');
     340  	    }
     341  	  if (outer == 0)
     342  	    break;
     343  	}
     344  
     345        /* strcmp/wcscmp tests */
     346        for (outer = 1; outer < 32; ++outer)
     347  	for (middle = 0; middle < 16; ++middle)
     348  	  {
     349  	    MEMSET (adr + middle, L('T'), 256);
     350  	    adr[256] = L('\0');
     351  	    MEMSET (dest + nchars - outer, L('T'), outer - 1);
     352  	    dest[nchars - 1] = L('\0');
     353  
     354  	    if (STRCMP (adr + middle, dest + nchars - outer) <= 0)
     355  	      {
     356  		printf ("%s 1 flunked for outer = %zu, middle = %zu\n",
     357  			STRINGIFY (STRCMP), outer, middle);
     358  		result = 1;
     359  	      }
     360  
     361  	    if (STRCMP (dest + nchars - outer, adr + middle) >= 0)
     362  	      {
     363  		printf ("%s 2 flunked for outer = %zu, middle = %zu\n",
     364  			STRINGIFY (STRCMP), outer, middle);
     365  		result = 1;
     366  	      }
     367  	  }
     368  
     369        /* strncmp/wcsncmp tests */
     370        for (outer = 1; outer < 32; ++outer)
     371  	for (middle = 0; middle < 16; ++middle)
     372  	  {
     373  	    MEMSET (adr + middle, L('T'), 256);
     374  	    adr[256] = L('\0');
     375  	    MEMSET (dest + nchars - outer, L('T'), outer - 1);
     376  	    dest[nchars - 1] = L('U');
     377  
     378  	    for (inner = 0; inner < outer; ++inner)
     379  	      {
     380  		if (STRNCMP (adr + middle, dest + nchars - outer, inner) != 0)
     381  		  {
     382  		    printf ("%s 1 flunked for outer = %zu, middle = %zu, "
     383  			    "inner = %zu\n",
     384  			    STRINGIFY (STRNCMP), outer, middle, inner);
     385  		    result = 1;
     386  		  }
     387  
     388  		if (STRNCMP (dest + nchars - outer, adr + middle, inner) != 0)
     389  		  {
     390  		    printf ("%s 2 flunked for outer = %zu, middle = %zu, "
     391  			    "inner = %zu\n",
     392  			    STRINGIFY (STRNCMP), outer, middle, inner);
     393  		    result = 1;
     394  		  }
     395  	      }
     396  
     397  	    if (STRNCMP (adr + middle, dest + nchars - outer, outer) >= 0)
     398  	      {
     399  		printf ("%s 1 flunked for outer = %zu, middle = %zu, full\n",
     400  			STRINGIFY (STRNCMP), outer, middle);
     401  		result = 1;
     402  	      }
     403  
     404  	    if (STRNCMP (dest + nchars - outer, adr + middle, outer) <= 0)
     405  	      {
     406  		printf ("%s 2 flunked for outer = %zu, middle = %zu, full\n",
     407  			STRINGIFY (STRNCMP), outer, middle);
     408  		result = 1;
     409  	      }
     410  	  }
     411  
     412        /* strncpy/wcsncpy tests */
     413        adr[nchars - 1] = L('T');
     414        for (outer = nchars; outer >= max128; --outer)
     415  	{
     416  	  size_t len;
     417  
     418  	  for (len = 0; len < nchars - outer; ++len)
     419  	    {
     420  	      if (STRNCPY (dest, &adr[outer], len) != dest
     421  		  || MEMCMP (dest, &adr[outer], len) != 0)
     422  		{
     423  		  printf ("outer %s flunked for outer = %zu, len = %zu\n",
     424  			  STRINGIFY (STRNCPY), outer, len);
     425  		  result = 1;
     426  		}
     427  	    }
     428  	  if (outer == 0)
     429  	    break;
     430  	}
     431        adr[nchars - 1] = L('\0');
     432  
     433        for (outer = nchars - 1; outer >= max128; --outer)
     434  	{
     435  	  for (inner = MAX (outer, nchars64); inner < nchars; ++inner)
     436  	    {
     437  	      size_t len;
     438  
     439  	      adr[inner] = L('\0');
     440  
     441  	      for (len = 0; len < nchars - outer + 64; ++len)
     442  		{
     443  		  if (STRNCPY (dest, &adr[outer], len) != dest
     444  		      || MEMCMP (dest, &adr[outer],
     445  				 MIN (inner - outer, len)) != 0
     446  		      || (inner - outer < len
     447  			  && STRLEN (dest) != (inner - outer)))
     448  		    {
     449  		      printf ("%s flunked for outer = %zu, inner = %zu, "
     450  			      "len = %zu\n",
     451  			      STRINGIFY (STRNCPY), outer, inner, len);
     452  		      result = 1;
     453  		    }
     454  		  if (STRNCPY (dest + 1, &adr[outer], len) != dest + 1
     455  		      || MEMCMP (dest + 1, &adr[outer],
     456  				 MIN (inner - outer, len)) != 0
     457  		      || (inner - outer < len
     458  			  && STRLEN (dest + 1) != (inner - outer)))
     459  		    {
     460  		      printf ("%s+1 flunked for outer = %zu, inner = %zu, "
     461  			      "len = %zu\n",
     462  			      STRINGIFY (STRNCPY), outer, inner, len);
     463  		      result = 1;
     464  		    }
     465  		}
     466  
     467  	      adr[inner] = L('T');
     468  	    }
     469  	  if (outer == 0)
     470  	    break;
     471  	}
     472  
     473        /* stpcpy/wcpcpy test */
     474        for (outer = nchars - 1; outer >= max128; --outer)
     475  	{
     476  	  for (inner = MAX (outer, nchars64); inner < nchars; ++inner)
     477  	    {
     478  	      adr[inner] = L('\0');
     479  
     480  	      if ((STPCPY (dest, &adr[outer]) - dest) != inner - outer)
     481  		{
     482  		  printf ("%s flunked for outer = %zu, inner = %zu\n",
     483  			  STRINGIFY (STPCPY), outer, inner);
     484  		  result = 1;
     485  		}
     486  
     487  	      adr[inner] = L('T');
     488  	    }
     489  	  if (outer == 0)
     490  	    break;
     491  	}
     492  
     493        /* stpncpy/wcpncpy test */
     494        adr[nchars - 1] = L('T');
     495        for (outer = nchars; outer >= max128; --outer)
     496  	{
     497  	  size_t len;
     498  
     499  	  for (len = 0; len < nchars - outer; ++len)
     500  	    {
     501  	      if (STPNCPY (dest, &adr[outer], len) != dest + len
     502  		  || MEMCMP (dest, &adr[outer], len) != 0)
     503  		{
     504  		  printf ("outer %s flunked for outer = %zu, len = %zu\n",
     505  			  STRINGIFY (STPNCPY), outer, len);
     506  		  result = 1;
     507  		}
     508  	    }
     509  	  if (outer == 0)
     510  	    break;
     511  	}
     512        adr[nchars - 1] = L('\0');
     513  
     514        for (outer = nchars - 1; outer >= max128; --outer)
     515  	{
     516  	  for (middle = MAX (outer, nchars64); middle < nchars; ++middle)
     517  	    {
     518  	      adr[middle] = L('\0');
     519  
     520  	      for (inner = 0; inner < nchars - outer; ++ inner)
     521  		{
     522  		  if ((STPNCPY (dest, &adr[outer], inner) - dest)
     523  		      != MIN (inner, middle - outer))
     524  		    {
     525  		      printf ("%s flunked for outer = %zu, middle = %zu, "
     526  			      "inner = %zu\n",
     527  			      STRINGIFY (STPNCPY), outer, middle, inner);
     528  		      result = 1;
     529  		    }
     530  		}
     531  
     532  	      adr[middle] = L('T');
     533  	    }
     534  	  if (outer == 0)
     535  	    break;
     536  	}
     537  
     538        /* memcpy/wmemcpy test */
     539        for (outer = nchars; outer >= max128; --outer)
     540  	{
     541  	  for (inner = 0; inner < nchars - outer; ++inner)
     542  	    if (MEMCPY (dest, &adr[outer], inner) !=  dest)
     543  	      {
     544  		printf ("%s flunked for outer = %zu, inner = %zu\n",
     545  			STRINGIFY (MEMCPY), outer, inner);
     546  		result = 1;
     547  	      }
     548  	  if (outer == 0)
     549  	    break;
     550  	}
     551  
     552        /* mempcpy/wmempcpy test */
     553        for (outer = nchars; outer >= max128; --outer)
     554  	{
     555  	  for (inner = 0; inner < nchars - outer; ++inner)
     556  	    if (MEMPCPY (dest, &adr[outer], inner) !=  dest + inner)
     557  	      {
     558  		printf ("%s flunked for outer = %zu, inner = %zu\n",
     559  			STRINGIFY (MEMPCPY), outer, inner);
     560  		result = 1;
     561  	      }
     562  	  if (outer == 0)
     563  	    break;
     564  	}
     565  
     566        /* This function only exists for single-byte characters.  */
     567  #ifndef WCSTEST
     568        /* memccpy test */
     569        memset (adr, '\0', nchars);
     570        for (outer = nchars; outer >= max128; --outer)
     571  	{
     572  	  for (inner = 0; inner < nchars - outer; ++inner)
     573  	    if (memccpy (dest, &adr[outer], L('\1'), inner) != NULL)
     574  	      {
     575  		printf ("memccpy flunked full copy for outer = %zu, inner = %zu\n",
     576  			outer, inner);
     577  		result = 1;
     578  	      }
     579  	  if (outer == 0)
     580  	    break;
     581  	}
     582        for (outer = nchars - 1; outer >= max128; --outer)
     583  	{
     584  	  for (middle = 0; middle < nchars - outer; ++middle)
     585  	    {
     586  	      memset (dest, L('\2'), middle + 1);
     587  	      for (inner = 0; inner < middle; ++inner)
     588  		{
     589  		  adr[outer + inner] = L('\1');
     590  
     591  		  if (memccpy (dest, &adr[outer], '\1', middle + 128)
     592  		      !=  dest + inner + 1)
     593  		    {
     594  		      printf ("\
     595  			      memccpy flunked partial copy for outer = %zu, middle = %zu, inner = %zu\n",
     596  			      outer, middle, inner);
     597  		      result = 1;
     598  		    }
     599  		  else if (dest[inner + 1] != L('\2'))
     600  		    {
     601  		      printf ("\
     602  			      memccpy copied too much for outer = %zu, middle = %zu, inner = %zu\n",
     603  			      outer, middle, inner);
     604  		      result = 1;
     605  		    }
     606  		  adr[outer + inner] = L('\0');
     607  		}
     608  	    }
     609  	  if (outer == 0)
     610  	    break;
     611  	}
     612  #endif
     613      }
     614  
     615    return result;
     616  }
     617  
     618  #include <support/test-driver.c>