1 /* Test strlen functions.
2 Copyright (C) 1999-2022 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
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.
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.
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/>. */
21 # define TEST_NAME "strnlen"
23 # define TEST_NAME "wcsnlen"
25 #include "test-string.h"
28 # define STRNLEN strnlen
29 # define MEMSET memset
31 # define BIG_CHAR CHAR_MAX
32 # define MIDDLE_CHAR 127
33 # define SIMPLE_STRNLEN simple_strnlen
36 # define STRNLEN wcsnlen
37 # define MEMSET wmemset
39 # define BIG_CHAR WCHAR_MAX
40 # define MIDDLE_CHAR 1121
41 # define SIMPLE_STRNLEN simple_wcsnlen
44 typedef size_t (*proto_t
) (const CHAR
*, size_t);
45 size_t SIMPLE_STRNLEN (const CHAR
*, size_t);
47 IMPL (SIMPLE_STRNLEN
, 0)
51 SIMPLE_STRNLEN (const CHAR
*s
, size_t maxlen
)
55 for (i
= 0; i
< maxlen
&& s
[i
]; ++i
);
60 do_one_test (impl_t
*impl
, const CHAR
*s
, size_t maxlen
, size_t exp_len
)
62 size_t len
= CALL (impl
, s
, maxlen
);
65 error (0, 0, "Wrong result in function %s %zd %zd", impl
->name
,
73 do_test (size_t align
, size_t len
, size_t maxlen
, int max_char
)
78 if ((align
+ len
) * sizeof (CHAR
) >= page_size
)
81 CHAR
*buf
= (CHAR
*) (buf1
);
83 for (i
= 0; i
< len
; ++i
)
84 buf
[align
+ i
] = 1 + 11111 * i
% max_char
;
87 FOR_EACH_IMPL (impl
, 0)
88 do_one_test (impl
, (CHAR
*) (buf
+ align
), maxlen
, MIN (len
, maxlen
));
92 do_overflow_tests (void)
96 uintptr_t buf_addr
= (uintptr_t) buf1
;
98 for (i
= 0; i
< 750; ++i
)
100 do_test (0, i
, SIZE_MAX
- i
, BIG_CHAR
);
101 do_test (0, i
, i
- buf_addr
, BIG_CHAR
);
102 do_test (0, i
, -buf_addr
- i
, BIG_CHAR
);
103 do_test (0, i
, SIZE_MAX
- buf_addr
- i
, BIG_CHAR
);
104 do_test (0, i
, SIZE_MAX
- buf_addr
+ i
, BIG_CHAR
);
107 for (j
= 8 * sizeof(size_t) - 1; j
; --j
)
110 do_test (0, i
, len
- i
, BIG_CHAR
);
111 do_test (0, i
, len
+ i
, BIG_CHAR
);
112 do_test (0, i
, len
- buf_addr
- i
, BIG_CHAR
);
113 do_test (0, i
, len
- buf_addr
+ i
, BIG_CHAR
);
115 do_test (0, i
, ~len
- i
, BIG_CHAR
);
116 do_test (0, i
, ~len
+ i
, BIG_CHAR
);
117 do_test (0, i
, ~len
- buf_addr
- i
, BIG_CHAR
);
118 do_test (0, i
, ~len
- buf_addr
+ i
, BIG_CHAR
);
120 do_test (0, i
, -buf_addr
, BIG_CHAR
);
121 do_test (0, i
, j
- buf_addr
, BIG_CHAR
);
122 do_test (0, i
, -buf_addr
- j
, BIG_CHAR
);
128 do_random_tests (void)
130 size_t i
, j
, n
, align
, len
;
131 CHAR
*p
= (CHAR
*) (buf1
+ page_size
- 512 * sizeof (CHAR
));
133 for (n
= 0; n
< ITERATIONS
; n
++)
135 align
= random () & 15;
136 len
= random () & 511;
137 if (len
+ align
> 510)
138 len
= 511 - align
- (random () & 7);
139 j
= len
+ align
+ 64;
143 for (i
= 0; i
< j
; i
++)
145 if (i
== len
+ align
)
149 p
[i
] = random () & 255;
150 if (i
>= align
&& i
< len
+ align
&& !p
[i
])
151 p
[i
] = (random () & 127) + 1;
155 FOR_EACH_IMPL (impl
, 1)
158 && CALL (impl
, (CHAR
*) (p
+ align
), len
- 1) != len
- 1)
160 error (0, 0, "Iteration %zd (limited) - wrong result in function %s (%zd) %zd != %zd, p %p",
161 n
, impl
->name
, align
,
162 CALL (impl
, (CHAR
*) (p
+ align
), len
- 1), len
- 1, p
);
165 if (CALL (impl
, (CHAR
*) (p
+ align
), len
) != len
)
167 error (0, 0, "Iteration %zd (exact) - wrong result in function %s (%zd) %zd != %zd, p %p",
168 n
, impl
->name
, align
,
169 CALL (impl
, (CHAR
*) (p
+ align
), len
), len
, p
);
172 if (CALL (impl
, (CHAR
*) (p
+ align
), len
+ 1) != len
)
174 error (0, 0, "Iteration %zd (long) - wrong result in function %s (%zd) %zd != %zd, p %p",
175 n
, impl
->name
, align
,
176 CALL (impl
, (CHAR
*) (p
+ align
), len
+ 1), len
, p
);
183 /* Tests meant to unveil fail on implementation that does not access bytes
184 around the page boundary accordingly. */
188 size_t i
, exp_len
, start_offset
, offset
;
189 /* Calculate the null character offset. */
190 size_t last_offset
= (page_size
/ sizeof (CHAR
)) - 1;
192 CHAR
*s
= (CHAR
*) buf2
;
193 MEMSET (s
, 65, (last_offset
- 1));
196 /* Place short strings ending at page boundary. */
197 offset
= last_offset
;
198 for (i
= 0; i
< 128; i
++)
200 /* Decrease offset to stress several sizes and alignments. */
202 exp_len
= last_offset
- offset
;
203 FOR_EACH_IMPL (impl
, 0)
205 /* Varies maxlen value to cover the cases where it is:
206 - larger than length;
207 - slightly greater than length;
209 - slightly less than length. */
210 do_one_test (impl
, (CHAR
*) (s
+ offset
), page_size
, exp_len
);
211 do_one_test (impl
, (CHAR
*) (s
+ offset
), exp_len
+ 1, exp_len
);
212 do_one_test (impl
, (CHAR
*) (s
+ offset
), exp_len
, exp_len
);
214 do_one_test (impl
, (CHAR
*) (s
+ offset
), exp_len
- 1, exp_len
- 1);
218 /* Place long strings ending at page boundary. */
219 start_offset
= (last_offset
+ 1) / 2;
220 for (i
= 0; i
< 64; ++i
)
222 /* Increase offset to stress several alignments. */
223 offset
= start_offset
+ i
;
224 if (offset
>= (last_offset
+ 1))
226 exp_len
= last_offset
- offset
;
227 FOR_EACH_IMPL (impl
, 0)
229 /* Checks only for maxlen much larger than length because smaller
230 values are already covered in do_random_tests function. */
231 do_one_test (impl
, (CHAR
*) (s
+ offset
), page_size
, exp_len
);
236 /* Tests meant to unveil fail on implementations that access bytes
237 beyond the maxium length. */
240 do_page_2_tests (void)
242 size_t i
, exp_len
, offset
;
243 size_t last_offset
= page_size
/ sizeof (CHAR
);
245 CHAR
*s
= (CHAR
*) buf2
;
246 MEMSET (s
, 65, last_offset
);
248 /* Place short strings ending at page boundary without the null
250 offset
= last_offset
;
251 for (i
= 0; i
< 128; i
++)
253 /* Decrease offset to stress several sizes and alignments. */
255 exp_len
= last_offset
- offset
;
256 FOR_EACH_IMPL (impl
, 0)
258 /* If an implementation goes beyond EXP_LEN, it will trigger
260 do_one_test (impl
, (CHAR
*) (s
+ offset
), exp_len
, exp_len
);
268 size_t i
, length
, char_per_page
;
273 FOR_EACH_IMPL (impl
, 0)
274 printf ("\t%s", impl
->name
);
277 for (i
= 1; i
< 8; ++i
)
279 do_test (0, i
, i
- 1, MIDDLE_CHAR
);
280 do_test (0, i
, i
, MIDDLE_CHAR
);
281 do_test (0, i
, i
+ 1, MIDDLE_CHAR
);
284 for (i
= 1; i
< 8; ++i
)
286 do_test (i
, i
, i
- 1, MIDDLE_CHAR
);
287 do_test (i
, i
, i
, MIDDLE_CHAR
);
288 do_test (i
, i
, i
+ 1, MIDDLE_CHAR
);
291 for (i
= 2; i
<= 10; ++i
)
293 do_test (0, 1 << i
, 5000, MIDDLE_CHAR
);
294 do_test (1, 1 << i
, 5000, MIDDLE_CHAR
);
297 for (i
= 1; i
< 8; ++i
)
298 do_test (0, i
, 5000, BIG_CHAR
);
300 for (i
= 1; i
< 8; ++i
)
301 do_test (i
, i
, 5000, BIG_CHAR
);
303 for (i
= 2; i
<= 10; ++i
)
305 do_test (0, 1 << i
, 5000, BIG_CHAR
);
306 do_test (1, 1 << i
, 5000, BIG_CHAR
);
309 char_per_page
= getpagesize () / sizeof (CHAR
);
311 for (i
= 0; i
<= 127; i
++)
312 for (length
= i
; length
<= 512; length
++)
314 do_test (i
, length
, 512, BIG_CHAR
);
315 do_test (char_per_page
- i
, length
, 512, BIG_CHAR
);
321 do_overflow_tests ();
325 #include <support/test-driver.c>