1 /* Test strlcat functions.
2 Copyright (C) 2023 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 do_one_test (impl_t
*impl
, CHAR
*dst
, const CHAR
*src
,
87 size_t exp_ret
, func_ret
;
88 size_t src_length
= STRLEN (src
);
89 size_t dst_length
= STRNLEN (dst
, n
);
94 exp_ret
= src_length
+ dst_length
;
96 func_ret
= CALL (impl
, dst
, src
, n
);
97 if (exp_ret
!= func_ret
)
99 error (0, 0, "Wrong result in function %s %zd != %zd", impl
->name
,
107 size_t to_copy
= n
- dst_length
- 1;
108 if (to_copy
> src_length
)
109 to_copy
= src_length
;
110 if (MEMCMP (dst
+ dst_length
, src
, to_copy
) != 0)
112 error (0, 0, "Incorrect concatenation in function %s",
117 if (dst
[dst_length
+ to_copy
] != '\0')
119 error (0, 0, "There is no zero in the end of output string in %s",
129 do_test (size_t align1
, size_t align2
, size_t len1
, size_t len2
,
130 size_t n
, int max_char
)
136 if ((align1
+ len1
) * sizeof (CHAR
) >= page_size
)
138 if ((align1
+ n
) * sizeof (CHAR
) > page_size
)
141 if ((align2
+ len1
+ len2
) * sizeof (CHAR
) >= page_size
)
143 if ((align2
+ len1
+ n
) * sizeof (CHAR
) > page_size
)
145 s1
= (CHAR
*) (buf1
) + align1
;
146 s2
= (CHAR
*) (buf2
) + align2
;
148 for (i
= 0; i
< len1
; ++i
)
149 s1
[i
] = 32 + 23 * i
% (max_char
- 32);
152 FOR_EACH_IMPL (impl
, 0)
155 for (i
= 0; i
< len2
; i
++)
156 s2
[i
] = 32 + 23 * i
% (max_char
- 32);
159 do_one_test (impl
, s2
, s1
, n
);
164 do_overflow_tests (void)
167 const size_t one
= 1;
172 s1_addr
= (uintptr_t)s1
;
173 for (j
= 0; j
< 200; ++j
)
174 s2
[j
] = 32 + 23 * j
% (BIG_CHAR
- 32);
176 for (i
= 0; i
< 750; ++i
) {
177 for (j
= 0; j
< i
; ++j
)
178 s1
[j
] = 32 + 23 * j
% (BIG_CHAR
- 32);
181 FOR_EACH_IMPL (impl
, 0)
184 do_one_test (impl
, s2
, s1
, SIZE_MAX
- i
);
186 do_one_test (impl
, s2
, s1
, i
- s1_addr
);
188 do_one_test (impl
, s2
, s1
, -s1_addr
- i
);
190 do_one_test (impl
, s2
, s1
, SIZE_MAX
- s1_addr
- i
);
192 do_one_test (impl
, s2
, s1
, SIZE_MAX
- s1_addr
+ i
);
196 for (j
= 8 * sizeof(size_t) - 1; j
; --j
)
199 FOR_EACH_IMPL (impl
, 0)
202 do_one_test (impl
, s2
, s1
, len
- i
);
204 do_one_test (impl
, s2
, s1
, len
+ i
);
206 do_one_test (impl
, s2
, s1
, len
- s1_addr
- i
);
208 do_one_test (impl
, s2
, s1
, len
- s1_addr
+ i
);
211 do_one_test (impl
, s2
, s1
, ~len
- i
);
213 do_one_test (impl
, s2
, s1
, ~len
+ i
);
215 do_one_test (impl
, s2
, s1
, ~len
- s1_addr
- i
);
217 do_one_test (impl
, s2
, s1
, ~len
- s1_addr
+ i
);
224 do_random_tests (void)
226 size_t i
, j
, n
, align1
, align2
, len1
, len2
, N
;
227 UCHAR
*p1
= (UCHAR
*) (buf1
+ page_size
) - 1024;
228 UCHAR
*p2
= (UCHAR
*) (buf2
+ page_size
) - 1024;
229 UCHAR
*p3
= (UCHAR
*) buf1
;
231 fprintf (stdout
, "Number of iterations in random test = %zd\n",
233 for (n
= 0; n
< ITERATIONS
; n
++)
235 N
= random () & 1023;
236 align1
= random () & 255;
237 align2
= random () & 255;
238 len1
= random () & 255;
239 len2
= random () & 255;
241 for (i
= 0; i
< len1
; i
++)
243 p1
[align1
+ i
] = random () & BIG_CHAR
;
245 p1
[align1
+ i
] = (random () & SMALL_CHAR
) + 3;
247 p1
[align1
+ len1
] = 0;
249 for (i
= 0; i
< len2
; i
++)
251 p3
[i
] = random () & BIG_CHAR
;
253 p3
[i
] = (random () & SMALL_CHAR
) + 3;
258 size_t src_length
= STRLEN ((CHAR
*) (p1
+ align1
));
259 size_t dst_length
= STRNLEN ((CHAR
*) (p3
), N
);
262 exp_ret
= src_length
;
264 exp_ret
= src_length
+ dst_length
;
266 FOR_EACH_IMPL (impl
, 1)
268 MEMSET (p2
- 64, '\1', align2
+ 64);
269 MEMSET (p2
+ align2
+ len2
+ 1, '\1', 1024 - align2
- len2
- 1);
270 MEMCPY (p2
+ align2
, p3
, len2
+ 1);
271 res
= CALL (impl
, (CHAR
*) (p2
+ align2
),
272 (CHAR
*) (p1
+ align1
), N
);
275 error (0, 0, "Iteration %zd - wrong result in function %s "
276 "(%zd, %zd, %zd, %zd, %zd) %zd != %zd",
277 n
, impl
->name
, align1
, align2
, len1
, len2
, N
,
282 for (j
= 0; j
< align2
+ 64; ++j
)
284 if (p2
[j
- 64] != '\1')
286 error (0, 0, "Iteration %zd - garbage before dst, %s "
287 "%zd, %zd, %zd, %zd, %zd)",
288 n
, impl
->name
, align1
, align2
, len1
, len2
, N
);
293 if (MEMCMP (p2
+ align2
, p3
, len2
))
295 error (0, 0, "Iteration %zd - garbage in string before, %s "
296 "(%zd, %zd, %zd, %zd, %zd)",
297 n
, impl
->name
, align1
, align2
, len1
, len2
, N
);
302 j
= (N
- len2
- 1 >= len1
) ? len1
: N
- len2
- 1;
303 if (MEMCMP (p2
+ align2
+ len2
, p1
+ align1
, j
))
305 error (0, 0, "Iteration %zd - different strings, %s "
306 "(%zd, %zd, %zd, %zd)", n
, impl
->name
, align1
,
311 if (p2
[align2
+ len2
+ j
] != '\0')
313 error (0, 0, "Iteration %zd - there is no zero at the "
314 "end of output string, %s (%zd, %zd, %zd, %zd, %zd)",
315 n
, impl
->name
, align1
, align2
, len1
, len2
, N
);
319 for (j
= j
+ align2
+ len2
+ 1; j
< 1024; ++j
)
323 error (0, 0, "Iteration %zd - garbage after, %s "
324 "(%zd, %zd, %zd, %zd, %zd)",
325 n
, impl
->name
, align1
, align2
, len1
, len2
, N
);
333 if (p2
[align2
+ len2
] != '\0')
335 error (0, 0, "Iteration %zd - destination modified, %s "
336 "(%zd, %zd, %zd, %zd, %zd)",
337 n
, impl
->name
, align1
, align2
, len1
, len2
, N
);
353 FOR_EACH_IMPL (impl
, 0)
354 printf ("\t%s", impl
->name
);
357 for (n
= 2; n
<= 2048; n
*=4)
359 do_test (0, 2, 2, 2, n
, SMALL_CHAR
);
360 do_test (0, 0, 4, 4, n
, SMALL_CHAR
);
361 do_test (4, 0, 4, 4, n
, BIG_CHAR
);
362 do_test (0, 0, 8, 8, n
, SMALL_CHAR
);
363 do_test (0, 8, 8, 8, n
, SMALL_CHAR
);
365 do_test (0, 2, 2, 2, SIZE_MAX
, SMALL_CHAR
);
366 do_test (0, 0, 4, 4, SIZE_MAX
, SMALL_CHAR
);
367 do_test (4, 0, 4, 4, SIZE_MAX
, BIG_CHAR
);
368 do_test (0, 0, 8, 8, SIZE_MAX
, SMALL_CHAR
);
369 do_test (0, 8, 8, 8, SIZE_MAX
, SMALL_CHAR
);
371 for (i
= 1; i
< 8; ++i
)
373 do_test (0, 0, 8 << i
, 8 << i
, n
, SMALL_CHAR
);
374 do_test (8 - i
, 2 * i
, 8 << i
, 8 << i
, n
, SMALL_CHAR
);
375 do_test (0, 0, 8 << i
, 2 << i
, n
, SMALL_CHAR
);
376 do_test (8 - i
, 2 * i
, 8 << i
, 2 << i
, n
, SMALL_CHAR
);
378 do_test (0, 0, 8 << i
, 8 << i
, SIZE_MAX
, SMALL_CHAR
);
379 do_test (8 - i
, 2 * i
, 8 << i
, 8 << i
, SIZE_MAX
, SMALL_CHAR
);
380 do_test (0, 0, 8 << i
, 2 << i
, SIZE_MAX
, SMALL_CHAR
);
381 do_test (8 - i
, 2 * i
, 8 << i
, 2 << i
, SIZE_MAX
, SMALL_CHAR
);
384 for (i
= 1; i
< 8; ++i
)
386 do_test (i
, 2 * i
, 8 << i
, 1, n
, SMALL_CHAR
);
387 do_test (2 * i
, i
, 8 << i
, 1, n
, BIG_CHAR
);
388 do_test (i
, i
, 8 << i
, 10, n
, SMALL_CHAR
);
390 do_test (i
, 2 * i
, 8 << i
, 1, SIZE_MAX
, SMALL_CHAR
);
391 do_test (2 * i
, i
, 8 << i
, 1, SIZE_MAX
, BIG_CHAR
);
392 do_test (i
, i
, 8 << i
, 10, SIZE_MAX
, SMALL_CHAR
);
397 do_overflow_tests ();
401 #include <support/test-driver.c>