1 /* Test memset functions.
2    Copyright (C) 1999-2021 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 CHAR *SIMPLE_MEMSET (CHAR *, int, size_t);
54 
55 #ifdef TEST_BZERO
56 typedef void (*proto_t) (char *, size_t);
57 void simple_bzero (char *, size_t);
58 void builtin_bzero (char *, size_t);
59 
60 IMPL (simple_bzero, 0)
61 IMPL (builtin_bzero, 0)
62 #ifdef TEST_EXPLICIT_BZERO
63 IMPL (explicit_bzero, 1)
64 #else
65 IMPL (bzero, 1)
66 #endif
67 
68 void
simple_bzero(char * s,size_t n)69 simple_bzero (char *s, size_t n)
70 {
71   SIMPLE_MEMSET (s, 0, n);
72 }
73 
74 void
builtin_bzero(char * s,size_t n)75 builtin_bzero (char *s, size_t n)
76 {
77   __builtin_bzero (s, n);
78 }
79 #else
80 typedef CHAR *(*proto_t) (CHAR *, int, size_t);
81 
82 IMPL (SIMPLE_MEMSET, 0)
83 # ifndef WIDE
84 char *builtin_memset (char *, int, size_t);
85 IMPL (builtin_memset, 0)
86 # endif /* !WIDE */
87 IMPL (MEMSET, 1)
88 
89 # ifndef WIDE
90 char *
builtin_memset(char * s,int c,size_t n)91 builtin_memset (char *s, int c, size_t n)
92 {
93   return __builtin_memset (s, c, n);
94 }
95 # endif /* !WIDE */
96 #endif /* !TEST_BZERO */
97 
98 CHAR *
99 inhibit_loop_to_libcall
SIMPLE_MEMSET(CHAR * s,int c,size_t n)100 SIMPLE_MEMSET (CHAR *s, int c, size_t n)
101 {
102   CHAR *r = s, *end = s + n;
103   while (r < end)
104     *r++ = c;
105   return s;
106 }
107 
108 static void
do_one_test(impl_t * impl,CHAR * s,int c __attribute ((unused)),size_t n)109 do_one_test (impl_t *impl, CHAR *s, int c __attribute ((unused)), size_t n)
110 {
111   CHAR buf[n + 2];
112   CHAR *tstbuf = buf + 1;
113   CHAR sentinel = c - 1;
114   buf[0] = sentinel;
115   buf[n + 1] = sentinel;
116 #ifdef TEST_BZERO
117   simple_bzero (tstbuf, n);
118   CALL (impl, s, n);
119   if (memcmp (s, tstbuf, n) != 0
120       || buf[0] != sentinel
121       || buf[n + 1] != sentinel)
122 #else
123   CHAR *res = CALL (impl, s, c, n);
124   if (res != s
125       || SIMPLE_MEMSET (tstbuf, c, n) != tstbuf
126       || MEMCMP (s, tstbuf, n) != 0
127       || buf[0] != sentinel
128       || buf[n + 1] != sentinel)
129 #endif /* !TEST_BZERO */
130     {
131       error (0, 0, "Wrong result in function %s", impl->name);
132       ret = 1;
133       return;
134     }
135 }
136 
137 static void
do_test(size_t align,int c,size_t len)138 do_test (size_t align, int c, size_t len)
139 {
140   align &= 4095;
141   if ((align + len) * sizeof (CHAR) > page_size)
142     return;
143 
144   FOR_EACH_IMPL (impl, 0)
145     do_one_test (impl, (CHAR *) (buf1) + align, c, len);
146 }
147 
148 #ifndef TEST_BZERO
149 static void
do_random_tests(void)150 do_random_tests (void)
151 {
152   size_t i, j, k, n, align, len, size;
153   int c, o;
154   UCHAR *p, *res;
155   UCHAR *p2 = (UCHAR *) buf2;
156 
157   for (i = 0; i < 65536 / sizeof (CHAR); ++i)
158     p2[i] = random () & BIG_CHAR;
159 
160   for (n = 0; n < ITERATIONS; n++)
161     {
162       if ((random () & 31) == 0)
163 	size = 65536 / sizeof (CHAR);
164       else
165 	size = 512;
166       p = (UCHAR *) (buf1 + page_size) - size;
167       len = random () & (size - 1);
168       align = size - len - (random () & 31);
169       if (align > size)
170 	align = size - len;
171       if ((random () & 7) == 0)
172 	align &= ~63;
173       if ((random () & 7) == 0)
174 	c = 0;
175       else
176 	c = random () & BIG_CHAR;
177       o = random () & BIG_CHAR;
178       if (o == c)
179 	o = (c + 1) & BIG_CHAR;
180       j = len + align + 128;
181       if (j > size)
182 	j = size;
183       if (align >= 128)
184 	k = align - 128;
185       else
186 	k = 0;
187       for (i = k; i < align; ++i)
188 	p[i] = o;
189       for (i = align + len; i < j; ++i)
190 	p[i] = o;
191 
192       FOR_EACH_IMPL (impl, 1)
193 	{
194 	  for (i = 0; i < len; ++i)
195 	    {
196 	      p[i + align] = p2[i];
197 	      if (p[i + align] == c)
198 		p[i + align] = o;
199 	    }
200 	  res = (UCHAR *) CALL (impl, (CHAR *) p + align, c, len);
201 	  if (res != p + align)
202 	    {
203 	      error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %d, %zd) %p != %p",
204 		     n, impl->name, align, c, len, res, p + align);
205 	      ret = 1;
206 	    }
207 	  for (i = k; i < align; ++i)
208 	    if (p[i] != o)
209 	      {
210 		error (0, 0, "Iteration %zd - garbage before %s (%zd, %d, %zd)",
211 		       n, impl->name, align, c, len);
212 		ret = 1;
213 		break;
214 	      }
215 	  for (; i < align + len; ++i)
216 	    if (p[i] != c)
217 	      {
218 		error (0, 0, "Iteration %zd - not cleared correctly %s (%zd, %d, %zd)",
219 		       n, impl->name, align, c, len);
220 		ret = 1;
221 		break;
222 	      }
223 	  for (; i < j; ++i)
224 	    if (p[i] != o)
225 	      {
226 		error (0, 0, "Iteration %zd - garbage after %s (%zd, %d, %zd)",
227 		       n, impl->name, align, c, len);
228 		ret = 1;
229 		break;
230 	      }
231 	}
232     }
233 }
234 #endif /* !TEST_BZERO */
235 
236 int
test_main(void)237 test_main (void)
238 {
239   size_t i;
240   int c = 0;
241 
242   test_init ();
243 
244   printf ("%24s", "");
245   FOR_EACH_IMPL (impl, 0)
246     printf ("\t%s", impl->name);
247   putchar ('\n');
248 
249 #ifndef TEST_BZERO
250   for (c = -65; c <= 130; c += 65)
251 #endif
252     {
253       for (i = 0; i < 18; ++i)
254 	do_test (0, c, 1 << i);
255       for (i = 1; i < 64; ++i)
256 	{
257 	  do_test (i, c, i);
258 	  do_test (4096 - i, c, i);
259 	  do_test (4095, c, i);
260 	  if (i & (i - 1))
261 	    do_test (0, c, i);
262 	}
263       do_test (1, c, 14);
264       do_test (3, c, 1024);
265       do_test (4, c, 64);
266       do_test (2, c, 25);
267     }
268 
269 #ifndef TEST_BZERO
270   do_random_tests ();
271 #endif
272 
273   return ret;
274 }
275 
276 #include <support/test-driver.c>
277