(root)/
glibc-2.38/
string/
test-strcpy.c
       1  /* Test and measure strcpy functions.
       2     Copyright (C) 1999-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  #ifdef WIDE
      20  # include <wchar.h>
      21  # define CHAR wchar_t
      22  # define UCHAR wchar_t
      23  # define sfmt "ls"
      24  # define BIG_CHAR WCHAR_MAX
      25  # define SMALL_CHAR 1273
      26  # define STRCMP wcscmp
      27  # define MEMCMP wmemcmp
      28  # define MEMSET wmemset
      29  #else
      30  # define CHAR char
      31  # define UCHAR unsigned char
      32  # define sfmt "s"
      33  # define BIG_CHAR CHAR_MAX
      34  # define SMALL_CHAR 127
      35  # define STRCMP strcmp
      36  # define MEMCMP memcmp
      37  # define MEMSET memset
      38  #endif
      39  
      40  #ifndef STRCPY_RESULT
      41  # define STRCPY_RESULT(dst, len) dst
      42  # define TEST_MAIN
      43  # ifndef WIDE
      44  #  define TEST_NAME "strcpy"
      45  # else
      46  #  define TEST_NAME "wcscpy"
      47  # endif
      48  # include "test-string.h"
      49  # ifndef WIDE
      50  #  define STRCPY strcpy
      51  # else
      52  #  define STRCPY wcscpy
      53  # endif
      54  
      55  IMPL (STRCPY, 1)
      56  
      57  /* Also check the generic implementation.  */
      58  #undef STRCPY
      59  #undef libc_hidden_builtin_def
      60  #define libc_hidden_builtin_def(a)
      61  #undef libc_hidden_def
      62  #define libc_hidden_def(a)
      63  #undef weak_alias
      64  #define weak_alias(a,b)
      65  #undef attribute_hidden
      66  #define attribute_hidden
      67  # ifndef WIDE
      68  #  define STPCPY __stpcpy_default
      69  #  include "string/stpcpy.c"
      70  #  define STRCPY __strcpy_default
      71  #  define __stpcpy __stpcpy_default
      72  #  include "string/strcpy.c"
      73  IMPL (__strcpy_default, 1)
      74  # else
      75  #  define __wcslen wcslen
      76  #  define __wmemcpy wmemcpy
      77  #  define WCSCPY __wcscpy_default
      78  #  include "wcsmbs/wcscpy.c"
      79  IMPL (__wcscpy_default, 1)
      80  # endif
      81  #endif
      82  
      83  typedef CHAR *(*proto_t) (CHAR *, const CHAR *);
      84  
      85  static void
      86  do_one_test (impl_t *impl, CHAR *dst, const CHAR *src,
      87  	     size_t len __attribute__((unused)))
      88  {
      89    if (CALL (impl, dst, src) != STRCPY_RESULT (dst, len))
      90      {
      91        error (0, 0, "Wrong result in function %s %p %p", impl->name,
      92  	     CALL (impl, dst, src), STRCPY_RESULT (dst, len));
      93        ret = 1;
      94        return;
      95      }
      96  
      97    if (STRCMP (dst, src) != 0)
      98      {
      99        error (0, 0,
     100  	     "Wrong result in function %s dst \"%" sfmt "\" src \"%" sfmt "\"",
     101  	     impl->name, dst, src);
     102        ret = 1;
     103        return;
     104      }
     105  }
     106  
     107  static void
     108  do_test (size_t align1, size_t align2, size_t len, int max_char)
     109  {
     110    size_t i;
     111    CHAR *s1, *s2;
     112  /* For wcscpy: align1 and align2 here mean alignment not in bytes,
     113     but in wchar_ts, in bytes it will equal to align * (sizeof (wchar_t))
     114     len for wcschr here isn't in bytes but it's number of wchar_t symbols.  */
     115    align1 &= 7;
     116    if ((align1 + len) * sizeof (CHAR) >= page_size)
     117      return;
     118  
     119    align2 &= 7;
     120    if ((align2 + len) * sizeof (CHAR) >= page_size)
     121      return;
     122  
     123    s1 = (CHAR *) (buf1) + align1;
     124    s2 = (CHAR *) (buf2) + align2;
     125  
     126    for (i = 0; i < len; i++)
     127      s1[i] = 32 + 23 * i % (max_char - 32);
     128    s1[len] = 0;
     129  
     130    FOR_EACH_IMPL (impl, 0)
     131      do_one_test (impl, s2, s1, len);
     132  }
     133  
     134  static void
     135  do_random_tests (void)
     136  {
     137    size_t i, j, n, align1, align2, len;
     138    UCHAR *p1 = (UCHAR *) (buf1 + page_size) - 512;
     139    UCHAR *p2 = (UCHAR *) (buf2 + page_size) - 512;
     140    UCHAR *res;
     141  
     142    for (n = 0; n < ITERATIONS; n++)
     143      {
     144        /* For wcsrchr: align1 and align2 here mean align not in bytes,
     145  	 but in wchar_ts, in bytes it will equal to align * (sizeof
     146  	 (wchar_t)).  For strrchr we need to check all alignments from
     147  	 0 to 63 since some assembly implementations have separate
     148  	 prolog for alignments more 48. */
     149  
     150        align1 = random () & (63 / sizeof (CHAR));
     151        if (random () & 1)
     152  	align2 = random () & (63 / sizeof (CHAR));
     153        else
     154  	align2 = align1 + (random () & 24);
     155        len = random () & 511;
     156        j = align1;
     157        if (align2 > j)
     158  	j = align2;
     159        if (len + j >= 511)
     160  	len = 510 - j - (random () & 7);
     161        j = len + align1 + 64;
     162        if (j > 512)
     163  	j = 512;
     164        for (i = 0; i < j; i++)
     165  	{
     166  	  if (i == len + align1)
     167  	    p1[i] = 0;
     168  	  else
     169  	    {
     170  	      p1[i] = random () & BIG_CHAR;
     171  	      if (i >= align1 && i < len + align1 && !p1[i])
     172  		p1[i] = (random () & SMALL_CHAR) + 3;
     173  	    }
     174  	}
     175  
     176        FOR_EACH_IMPL (impl, 1)
     177  	{
     178  	  MEMSET (p2 - 64, '\1', 512 + 64);
     179  	  res = (UCHAR *) CALL (impl, (CHAR *) (p2 + align2), (CHAR *) (p1 + align1));
     180  	  if (res != STRCPY_RESULT (p2 + align2, len))
     181  	    {
     182  	      error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %zd, %zd) %p != %p",
     183  		     n, impl->name, align1, align2, len, res,
     184  		     STRCPY_RESULT (p2 + align2, len));
     185  	      ret = 1;
     186  	    }
     187  	  for (j = 0; j < align2 + 64; ++j)
     188  	    {
     189  	      if (p2[j - 64] != '\1')
     190  		{
     191  		  error (0, 0, "Iteration %zd - garbage before, %s (%zd, %zd, %zd)",
     192  			 n, impl->name, align1, align2, len);
     193  		  ret = 1;
     194  		  break;
     195  		}
     196  	    }
     197  	  for (j = align2 + len + 1; j < 512; ++j)
     198  	    {
     199  	      if (p2[j] != '\1')
     200  		{
     201  		  error (0, 0, "Iteration %zd - garbage after, %s (%zd, %zd, %zd)",
     202  			 n, impl->name, align1, align2, len);
     203  		  ret = 1;
     204  		  break;
     205  		}
     206  	    }
     207  	  if (MEMCMP (p1 + align1, p2 + align2, len + 1))
     208  	    {
     209  	      error (0, 0, "Iteration %zd - different strings, %s (%zd, %zd, %zd)",
     210  		     n, impl->name, align1, align2, len);
     211  	      ret = 1;
     212  	    }
     213  	}
     214      }
     215  }
     216  
     217  int
     218  test_main (void)
     219  {
     220    size_t i;
     221  
     222    test_init ();
     223  
     224    printf ("%23s", "");
     225    FOR_EACH_IMPL (impl, 0)
     226      printf ("\t%s", impl->name);
     227    putchar ('\n');
     228  
     229    for (i = 0; i < 16; ++i)
     230      {
     231        do_test (0, 0, i, SMALL_CHAR);
     232        do_test (0, 0, i, BIG_CHAR);
     233        do_test (0, i, i, SMALL_CHAR);
     234        do_test (i, 0, i, BIG_CHAR);
     235      }
     236  
     237    for (i = 1; i < 8; ++i)
     238      {
     239        do_test (0, 0, 8 << i, SMALL_CHAR);
     240        do_test (8 - i, 2 * i, 8 << i, SMALL_CHAR);
     241      }
     242  
     243    for (i = 1; i < 8; ++i)
     244      {
     245        do_test (i, 2 * i, 8 << i, SMALL_CHAR);
     246        do_test (2 * i, i, 8 << i, BIG_CHAR);
     247        do_test (i, i, 8 << i, SMALL_CHAR);
     248        do_test (i, i, 8 << i, BIG_CHAR);
     249      }
     250  
     251    do_random_tests ();
     252    return ret;
     253  }
     254  
     255  #include <support/test-driver.c>