(root)/
glibc-2.38/
string/
test-memset.c
       1  /* Test memset 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  #define TEST_MAIN
      20  #ifdef TEST_BZERO
      21  # ifdef TEST_EXPLICIT_BZERO
      22  #  define TEST_NAME "explicit_bzero"
      23  # else
      24  #  define TEST_NAME "bzero"
      25  # endif
      26  #else
      27  # ifndef WIDE
      28  #  define TEST_NAME "memset"
      29  # else
      30  #  define TEST_NAME "wmemset"
      31  # endif /* WIDE */
      32  #endif /* !TEST_BZERO */
      33  #define MIN_PAGE_SIZE 131072
      34  #include "test-string.h"
      35  
      36  #ifndef WIDE
      37  # define MEMSET memset
      38  # define CHAR char
      39  # define UCHAR unsigned char
      40  # define SIMPLE_MEMSET simple_memset
      41  # define MEMCMP memcmp
      42  # define BIG_CHAR CHAR_MAX
      43  #else
      44  # include <wchar.h>
      45  # define MEMSET wmemset
      46  # define CHAR wchar_t
      47  # define UCHAR wchar_t
      48  # define SIMPLE_MEMSET simple_wmemset
      49  # define MEMCMP wmemcmp
      50  # define BIG_CHAR WCHAR_MAX
      51  #endif /* WIDE */
      52  
      53  #ifdef TEST_BZERO
      54  typedef void (*proto_t) (char *, size_t);
      55  # ifdef TEST_EXPLICIT_BZERO
      56  IMPL (explicit_bzero, 1)
      57  # else
      58  IMPL (bzero, 1)
      59  # endif
      60  #else
      61  typedef CHAR *(*proto_t) (CHAR *, int, size_t);
      62  IMPL (MEMSET, 1)
      63  #endif /* !TEST_BZERO */
      64  
      65  /* Naive implementation to verify results.  */
      66  CHAR *
      67  inhibit_loop_to_libcall
      68  SIMPLE_MEMSET (CHAR *s, int c, size_t n)
      69  {
      70    CHAR *r = s, *end = s + n;
      71    while (r < end)
      72      *r++ = c;
      73    return s;
      74  }
      75  
      76  static void
      77  do_one_test (impl_t *impl, CHAR *s, int c __attribute ((unused)), size_t n, int space_below, int space_above)
      78  {
      79    CHAR buf[n];
      80    CHAR sentinel = ~c;
      81    if (space_below)
      82        s[-1] = sentinel;
      83    if (space_above)
      84        s[n] = sentinel;
      85    SIMPLE_MEMSET(s, ~c, n);
      86  #ifdef TEST_BZERO
      87    SIMPLE_MEMSET (buf, 0, n);
      88    CALL (impl, s, n);
      89    if (memcmp (s, buf, n) != 0
      90        || (space_below && s[-1] != sentinel)
      91        || (space_above && s[n] != sentinel))
      92  #else
      93    CHAR *res = CALL (impl, s, c, n);
      94    if (res != s
      95        || SIMPLE_MEMSET (buf, c, n) != buf
      96        || MEMCMP (s, buf, n) != 0
      97        || (space_below && s[-1] != sentinel)
      98        || (space_above && s[n] != sentinel))
      99  #endif /* !TEST_BZERO */
     100      {
     101        error (0, 0, "Wrong result in function %s", impl->name);
     102        ret = 1;
     103        return;
     104      }
     105  }
     106  
     107  static void
     108  do_test (size_t align, int c, size_t len)
     109  {
     110    int space_below, space_above;
     111    align &= 4095;
     112    if ((align + len) * sizeof (CHAR) > page_size)
     113      return;
     114  
     115    space_below = !!align;
     116    space_above = !((align + len + 1) * sizeof (CHAR) > page_size);
     117  
     118    FOR_EACH_IMPL (impl, 0)
     119      do_one_test (impl, (CHAR *) (buf1) + align, c, len, space_below, space_above);
     120  }
     121  
     122  #ifndef TEST_BZERO
     123  static void
     124  do_random_tests (void)
     125  {
     126    size_t i, j, k, n, align, len, size;
     127    int c, o;
     128    UCHAR *p, *res;
     129    UCHAR *p2 = (UCHAR *) buf2;
     130  
     131    for (i = 0; i < 65536 / sizeof (CHAR); ++i)
     132      p2[i] = random () & BIG_CHAR;
     133  
     134    for (n = 0; n < ITERATIONS; n++)
     135      {
     136        if ((random () & 31) == 0)
     137  	size = 65536 / sizeof (CHAR);
     138        else
     139  	size = 512;
     140        p = (UCHAR *) (buf1 + page_size) - size;
     141        len = random () & (size - 1);
     142        align = size - len - (random () & 31);
     143        if (align > size)
     144  	align = size - len;
     145        if ((random () & 7) == 0)
     146  	align &= ~63;
     147        if ((random () & 7) == 0)
     148  	c = 0;
     149        else
     150  	c = random () & BIG_CHAR;
     151        o = random () & BIG_CHAR;
     152        if (o == c)
     153  	o = (c + 1) & BIG_CHAR;
     154        j = len + align + 128;
     155        if (j > size)
     156  	j = size;
     157        if (align >= 128)
     158  	k = align - 128;
     159        else
     160  	k = 0;
     161        for (i = k; i < align; ++i)
     162  	p[i] = o;
     163        for (i = align + len; i < j; ++i)
     164  	p[i] = o;
     165  
     166        FOR_EACH_IMPL (impl, 1)
     167  	{
     168  	  for (i = 0; i < len; ++i)
     169  	    {
     170  	      p[i + align] = p2[i];
     171  	      if (p[i + align] == c)
     172  		p[i + align] = o;
     173  	    }
     174  	  res = (UCHAR *) CALL (impl, (CHAR *) p + align, c, len);
     175  	  if (res != p + align)
     176  	    {
     177  	      error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %d, %zd) %p != %p",
     178  		     n, impl->name, align, c, len, res, p + align);
     179  	      ret = 1;
     180  	    }
     181  	  for (i = k; i < align; ++i)
     182  	    if (p[i] != o)
     183  	      {
     184  		error (0, 0, "Iteration %zd - garbage before %s (%zd, %d, %zd)",
     185  		       n, impl->name, align, c, len);
     186  		ret = 1;
     187  		break;
     188  	      }
     189  	  for (; i < align + len; ++i)
     190  	    if (p[i] != c)
     191  	      {
     192  		error (0, 0, "Iteration %zd - not cleared correctly %s (%zd, %d, %zd)",
     193  		       n, impl->name, align, c, len);
     194  		ret = 1;
     195  		break;
     196  	      }
     197  	  for (; i < j; ++i)
     198  	    if (p[i] != o)
     199  	      {
     200  		error (0, 0, "Iteration %zd - garbage after %s (%zd, %d, %zd)",
     201  		       n, impl->name, align, c, len);
     202  		ret = 1;
     203  		break;
     204  	      }
     205  	}
     206      }
     207  }
     208  #endif /* !TEST_BZERO */
     209  
     210  int
     211  test_main (void)
     212  {
     213    size_t i;
     214    int c = 0;
     215  
     216    test_init ();
     217  
     218    printf ("%24s", "");
     219    FOR_EACH_IMPL (impl, 0)
     220      printf ("\t%s", impl->name);
     221    putchar ('\n');
     222  
     223  #ifndef TEST_BZERO
     224    for (c = -65; c <= 130; c += 65)
     225  #endif
     226      {
     227        for (i = 0; i < 18; ++i)
     228  	do_test (0, c, 1 << i);
     229        for (i = 1; i < 64; ++i)
     230  	{
     231  	  do_test (i, c, i);
     232  	  do_test (4096 - i, c, i);
     233  	  do_test (4095, c, i);
     234  	  if (i & (i - 1))
     235  	    do_test (0, c, i);
     236  	}
     237        do_test (1, c, 14);
     238        do_test (3, c, 1024);
     239        do_test (4, c, 64);
     240        do_test (2, c, 25);
     241      }
     242  
     243  #ifndef TEST_BZERO
     244    do_random_tests ();
     245  #endif
     246  
     247    return ret;
     248  }
     249  
     250  #include <support/test-driver.c>