1/* Test memset functions.
2 Copyright (C) 1999-2022 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
53CHAR *SIMPLE_MEMSET (CHAR *, int, size_t);
54
55#ifdef TEST_BZERO
56typedef void (*proto_t) (char *, size_t);
57void simple_bzero (char *, size_t);
58void builtin_bzero (char *, size_t);
59
60IMPL (simple_bzero, 0)
61IMPL (builtin_bzero, 0)
62#ifdef TEST_EXPLICIT_BZERO
63IMPL (explicit_bzero, 1)
64#else
65IMPL (bzero, 1)
66#endif
67
68void
69simple_bzero (char *s, size_t n)
70{
71 SIMPLE_MEMSET (s, 0, n);
72}
73
74void
75builtin_bzero (char *s, size_t n)
76{
77 __builtin_bzero (s, n);
78}
79#else
80typedef CHAR *(*proto_t) (CHAR *, int, size_t);
81
82IMPL (SIMPLE_MEMSET, 0)
83# ifndef WIDE
84char *builtin_memset (char *, int, size_t);
85IMPL (builtin_memset, 0)
86# endif /* !WIDE */
87IMPL (MEMSET, 1)
88
89# ifndef WIDE
90char *
91builtin_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
98CHAR *
99inhibit_loop_to_libcall
100SIMPLE_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
108static void
109do_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 (s: 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 (status: 0, errnum: 0, format: "Wrong result in function %s", impl->name);
132 ret = 1;
133 return;
134 }
135}
136
137static void
138do_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, s: (CHAR *) (buf1) + align, c, n: len);
146}
147
148#ifndef TEST_BZERO
149static void
150do_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
236int
237test_main (void)
238{
239 size_t i;
240 int c = 0;
241
242 test_init ();
243
244 printf (format: "%24s", "");
245 FOR_EACH_IMPL (impl, 0)
246 printf (format: "\t%s", impl->name);
247 putchar (c: '\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 (align: 0, c, len: 1 << i);
255 for (i = 1; i < 64; ++i)
256 {
257 do_test (align: i, c, len: i);
258 do_test (align: 4096 - i, c, len: i);
259 do_test (align: 4095, c, len: i);
260 if (i & (i - 1))
261 do_test (align: 0, c, len: i);
262 }
263 do_test (align: 1, c, len: 14);
264 do_test (align: 3, c, len: 1024);
265 do_test (align: 4, c, len: 64);
266 do_test (align: 2, c, len: 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

source code of glibc/string/test-memset.c