1 /* Test strlcat functions.
2 Copyright (C) 2023-2024 Free Software Foundation, Inc.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, see
16 <https://www.gnu.org/licenses/>. */
20 # define TEST_NAME "strlcat"
22 # define TEST_NAME "wcslcat"
24 #include "test-string.h"
28 # define BIG_CHAR WCHAR_MAX
30 # define MEMCMP wmemcmp
31 # define MEMCPY wmemcpy
32 # define MEMSET wmemset
33 # define SIMPLE_STRLCAT simple_wcslcat
34 # define SMALL_CHAR 1273
35 # define STRLCAT wcslcat
36 # define STRLEN wcslen
37 # define STRNLEN wcsnlen
38 # define UCHAR wchar_t
40 # define BIG_CHAR CHAR_MAX
42 # define MEMCMP memcmp
43 # define MEMCPY memcpy
44 # define MEMSET memset
45 # define SMALL_CHAR 127
46 # define SIMPLE_STRLCAT simple_strlcat
47 # define STRLCAT strlcat
48 # define STRLEN strlen
49 # define STRNLEN strnlen
50 # define UCHAR unsigned char
53 /* Naive implementation to verify results. */
55 SIMPLE_STRLCAT (CHAR
*dst
, const CHAR
*src
, size_t n
)
57 size_t src_length
= STRLEN (src
);
62 size_t dst_length
= STRNLEN (dst
, n
);
66 size_t to_copy
= n
- dst_length
- 1;
68 if (to_copy
> src_length
)
71 CHAR
*target
= dst
+ dst_length
;
72 MEMCPY (target
, src
, to_copy
);
73 target
[to_copy
] = '\0';
75 return dst_length
+ src_length
;
78 IMPL (SIMPLE_STRLCAT
, 0)
81 typedef size_t (*proto_t
) (CHAR
*, const CHAR
*, size_t);
84 __attribute__((noinline
))
85 do_one_test (impl_t
*impl
, CHAR
*dst
, const CHAR
*src
,
88 size_t exp_ret
, func_ret
;
89 size_t src_length
= STRLEN (src
);
90 size_t dst_length
= STRNLEN (dst
, n
);
95 exp_ret
= src_length
+ dst_length
;
97 func_ret
= CALL (impl
, dst
, src
, n
);
98 if (exp_ret
!= func_ret
)
100 error (0, 0, "Wrong result in function %s %zd != %zd", impl
->name
,
108 size_t to_copy
= n
- dst_length
- 1;
109 if (to_copy
> src_length
)
110 to_copy
= src_length
;
111 if (MEMCMP (dst
+ dst_length
, src
, to_copy
) != 0)
113 error (0, 0, "Incorrect concatenation in function %s",
118 if (dst
[dst_length
+ to_copy
] != '\0')
120 error (0, 0, "There is no zero in the end of output string in %s",
130 do_test (size_t align1
, size_t align2
, size_t len1
, size_t len2
,
131 size_t n
, int max_char
)
137 if ((align1
+ len1
) * sizeof (CHAR
) >= page_size
)
139 if ((align1
+ n
) * sizeof (CHAR
) > page_size
)
142 if ((align2
+ len1
+ len2
) * sizeof (CHAR
) >= page_size
)
144 if ((align2
+ len1
+ n
) * sizeof (CHAR
) > page_size
)
146 s1
= (CHAR
*) (buf1
) + align1
;
147 s2
= (CHAR
*) (buf2
) + align2
;
149 for (i
= 0; i
< len1
; ++i
)
150 s1
[i
] = 32 + 23 * i
% (max_char
- 32);
153 FOR_EACH_IMPL (impl
, 0)
156 for (i
= 0; i
< len2
; i
++)
157 s2
[i
] = 32 + 23 * i
% (max_char
- 32);
160 do_one_test (impl
, s2
, s1
, n
);
165 do_overflow_tests (void)
168 const size_t one
= 1;
173 s1_addr
= (uintptr_t)s1
;
174 for (j
= 0; j
< 200; ++j
)
175 s2
[j
] = 32 + 23 * j
% (BIG_CHAR
- 32);
177 for (i
= 0; i
< 750; ++i
) {
178 for (j
= 0; j
< i
; ++j
)
179 s1
[j
] = 32 + 23 * j
% (BIG_CHAR
- 32);
182 FOR_EACH_IMPL (impl
, 0)
185 do_one_test (impl
, s2
, s1
, SIZE_MAX
- i
);
187 do_one_test (impl
, s2
, s1
, i
- s1_addr
);
189 do_one_test (impl
, s2
, s1
, -s1_addr
- i
);
191 do_one_test (impl
, s2
, s1
, SIZE_MAX
- s1_addr
- i
);
193 do_one_test (impl
, s2
, s1
, SIZE_MAX
- s1_addr
+ i
);
197 for (j
= 8 * sizeof(size_t) - 1; j
; --j
)
200 FOR_EACH_IMPL (impl
, 0)
203 do_one_test (impl
, s2
, s1
, len
- i
);
205 do_one_test (impl
, s2
, s1
, len
+ i
);
207 do_one_test (impl
, s2
, s1
, len
- s1_addr
- i
);
209 do_one_test (impl
, s2
, s1
, len
- s1_addr
+ i
);
212 do_one_test (impl
, s2
, s1
, ~len
- i
);
214 do_one_test (impl
, s2
, s1
, ~len
+ i
);
216 do_one_test (impl
, s2
, s1
, ~len
- s1_addr
- i
);
218 do_one_test (impl
, s2
, s1
, ~len
- s1_addr
+ i
);
225 do_random_tests (void)
227 size_t i
, j
, n
, align1
, align2
, len1
, len2
, N
;
228 UCHAR
*p1
= (UCHAR
*) (buf1
+ page_size
) - 1024;
229 UCHAR
*p2
= (UCHAR
*) (buf2
+ page_size
) - 1024;
230 UCHAR
*p3
= (UCHAR
*) buf1
;
232 fprintf (stdout
, "Number of iterations in random test = %zd\n",
234 for (n
= 0; n
< ITERATIONS
; n
++)
236 N
= random () & 1023;
237 align1
= random () & 255;
238 align2
= random () & 255;
239 len1
= random () & 255;
240 len2
= random () & 255;
242 for (i
= 0; i
< len1
; i
++)
244 p1
[align1
+ i
] = random () & BIG_CHAR
;
246 p1
[align1
+ i
] = (random () & SMALL_CHAR
) + 3;
248 p1
[align1
+ len1
] = 0;
250 for (i
= 0; i
< len2
; i
++)
252 p3
[i
] = random () & BIG_CHAR
;
254 p3
[i
] = (random () & SMALL_CHAR
) + 3;
259 size_t src_length
= STRLEN ((CHAR
*) (p1
+ align1
));
260 size_t dst_length
= STRNLEN ((CHAR
*) (p3
), N
);
263 exp_ret
= src_length
;
265 exp_ret
= src_length
+ dst_length
;
267 FOR_EACH_IMPL (impl
, 1)
269 MEMSET (p2
- 64, '\1', align2
+ 64);
270 MEMSET (p2
+ align2
+ len2
+ 1, '\1', 1024 - align2
- len2
- 1);
271 MEMCPY (p2
+ align2
, p3
, len2
+ 1);
272 res
= CALL (impl
, (CHAR
*) (p2
+ align2
),
273 (CHAR
*) (p1
+ align1
), N
);
276 error (0, 0, "Iteration %zd - wrong result in function %s "
277 "(%zd, %zd, %zd, %zd, %zd) %zd != %zd",
278 n
, impl
->name
, align1
, align2
, len1
, len2
, N
,
283 for (j
= 0; j
< align2
+ 64; ++j
)
285 if (p2
[j
- 64] != '\1')
287 error (0, 0, "Iteration %zd - garbage before dst, %s "
288 "%zd, %zd, %zd, %zd, %zd)",
289 n
, impl
->name
, align1
, align2
, len1
, len2
, N
);
294 if (MEMCMP (p2
+ align2
, p3
, len2
))
296 error (0, 0, "Iteration %zd - garbage in string before, %s "
297 "(%zd, %zd, %zd, %zd, %zd)",
298 n
, impl
->name
, align1
, align2
, len1
, len2
, N
);
303 j
= (N
- len2
- 1 >= len1
) ? len1
: N
- len2
- 1;
304 if (MEMCMP (p2
+ align2
+ len2
, p1
+ align1
, j
))
306 error (0, 0, "Iteration %zd - different strings, %s "
307 "(%zd, %zd, %zd, %zd)", n
, impl
->name
, align1
,
312 if (p2
[align2
+ len2
+ j
] != '\0')
314 error (0, 0, "Iteration %zd - there is no zero at the "
315 "end of output string, %s (%zd, %zd, %zd, %zd, %zd)",
316 n
, impl
->name
, align1
, align2
, len1
, len2
, N
);
320 for (j
= j
+ align2
+ len2
+ 1; j
< 1024; ++j
)
324 error (0, 0, "Iteration %zd - garbage after, %s "
325 "(%zd, %zd, %zd, %zd, %zd)",
326 n
, impl
->name
, align1
, align2
, len1
, len2
, N
);
334 if (p2
[align2
+ len2
] != '\0')
336 error (0, 0, "Iteration %zd - destination modified, %s "
337 "(%zd, %zd, %zd, %zd, %zd)",
338 n
, impl
->name
, align1
, align2
, len1
, len2
, N
);
354 FOR_EACH_IMPL (impl
, 0)
355 printf ("\t%s", impl
->name
);
358 for (n
= 2; n
<= 2048; n
*=4)
360 do_test (0, 2, 2, 2, n
, SMALL_CHAR
);
361 do_test (0, 0, 4, 4, n
, SMALL_CHAR
);
362 do_test (4, 0, 4, 4, n
, BIG_CHAR
);
363 do_test (0, 0, 8, 8, n
, SMALL_CHAR
);
364 do_test (0, 8, 8, 8, n
, SMALL_CHAR
);
366 do_test (0, 2, 2, 2, SIZE_MAX
, SMALL_CHAR
);
367 do_test (0, 0, 4, 4, SIZE_MAX
, SMALL_CHAR
);
368 do_test (4, 0, 4, 4, SIZE_MAX
, BIG_CHAR
);
369 do_test (0, 0, 8, 8, SIZE_MAX
, SMALL_CHAR
);
370 do_test (0, 8, 8, 8, SIZE_MAX
, SMALL_CHAR
);
372 for (i
= 1; i
< 8; ++i
)
374 do_test (0, 0, 8 << i
, 8 << i
, n
, SMALL_CHAR
);
375 do_test (8 - i
, 2 * i
, 8 << i
, 8 << i
, n
, SMALL_CHAR
);
376 do_test (0, 0, 8 << i
, 2 << i
, n
, SMALL_CHAR
);
377 do_test (8 - i
, 2 * i
, 8 << i
, 2 << i
, n
, SMALL_CHAR
);
379 do_test (0, 0, 8 << i
, 8 << i
, SIZE_MAX
, SMALL_CHAR
);
380 do_test (8 - i
, 2 * i
, 8 << i
, 8 << i
, SIZE_MAX
, SMALL_CHAR
);
381 do_test (0, 0, 8 << i
, 2 << i
, SIZE_MAX
, SMALL_CHAR
);
382 do_test (8 - i
, 2 * i
, 8 << i
, 2 << i
, SIZE_MAX
, SMALL_CHAR
);
385 for (i
= 1; i
< 8; ++i
)
387 do_test (i
, 2 * i
, 8 << i
, 1, n
, SMALL_CHAR
);
388 do_test (2 * i
, i
, 8 << i
, 1, n
, BIG_CHAR
);
389 do_test (i
, i
, 8 << i
, 10, n
, SMALL_CHAR
);
391 do_test (i
, 2 * i
, 8 << i
, 1, SIZE_MAX
, SMALL_CHAR
);
392 do_test (2 * i
, i
, 8 << i
, 1, SIZE_MAX
, BIG_CHAR
);
393 do_test (i
, i
, 8 << i
, 10, SIZE_MAX
, SMALL_CHAR
);
398 do_overflow_tests ();
402 #include <support/test-driver.c>