1 /* Test strlcpy functions.
2 Copyright (C) 2023 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 "strlcpy"
23 # define TEST_NAME "wcslcpy"
25 #include "test-string.h"
29 # define BIG_CHAR WCHAR_MAX
31 # define MEMCMP wmemcmp
32 # define MEMSET wmemset
33 # define SIMPLE_STRLCPY simple_wcslcpy
34 # define SMALL_CHAR 1273
35 # define STRLCPY wcslcpy
36 # define STRLEN wcslen
38 # define BIG_CHAR CHAR_MAX
40 # define MEMCMP memcmp
41 # define MEMSET memset
42 # define SIMPLE_STRLCPY simple_strlcpy
43 # define SMALL_CHAR 127
44 # define STRLCPY strlcpy
45 # define STRLEN strlen
48 /* Naive implementation to verify results. */
50 SIMPLE_STRLCPY (CHAR
*dst
, const CHAR
*src
, size_t n
)
52 size_t ret
= STRLEN (src
);
58 if ((*dst
++ = *src
++) == '\0')
64 IMPL (SIMPLE_STRLCPY
, 0)
67 typedef size_t (*proto_t
) (CHAR
*, const CHAR
*, size_t);
70 do_one_test (impl_t
*impl
, CHAR
*dst
, const CHAR
*src
, size_t len
, size_t n
)
72 if (CALL (impl
, dst
, src
, n
) != len
)
74 error (0, 0, "Wrong result in function %s %zd %zd", impl
->name
,
75 CALL (impl
, dst
, src
, n
), len
);
83 len
= (len
>= n
? n
- 1 : len
);
84 if (MEMCMP (dst
, src
, len
) != 0)
86 error (0, 0, "Wrong result in function1 %s", impl
->name
);
91 if (dst
[len
] != '\0')
93 error (0, 0, "Wrong result in function2 %s", impl
->name
);
100 do_test (size_t align1
, size_t align2
, size_t len
, size_t n
, int max_char
)
105 /* For wcslcpy: align1 and align2 here mean alignment not in bytes,
106 but in wchar_ts, in bytes it will equal to align * (sizeof (wchar_t)). */
108 if ((align1
+ len
) * sizeof (CHAR
) >= page_size
)
112 if ((align2
+ len
) * sizeof (CHAR
) >= page_size
)
115 s1
= (CHAR
*) (buf1
) + align1
;
116 s2
= (CHAR
*) (buf2
) + align2
;
118 for (i
= 0; i
< len
; ++i
)
119 s1
[i
] = 32 + 23 * i
% (max_char
- 32);
122 FOR_EACH_IMPL (impl
, 0)
123 do_one_test (impl
, s2
, s1
, len
, n
);
130 const size_t maxoffset
= 64;
132 /* Put s1 at the maxoffset from the edge of buf1's last page. */
133 s1
= (CHAR
*) buf1
+ BUF1PAGES
* page_size
/ sizeof(CHAR
) - maxoffset
;
134 /* s2 needs room to put a string with size of maxoffset + 1 at s2 +
136 s2
= (CHAR
*) buf2
+ page_size
/ sizeof(CHAR
) - maxoffset
* 2;
138 MEMSET (s1
, 'a', maxoffset
- 1);
139 s1
[maxoffset
- 1] = '\0';
141 /* Both strings are bounded to a page with read/write access and the next
142 page is protected with PROT_NONE (meaning that any access outside of the
143 page regions will trigger an invalid memory access).
145 The loop copies the string s1 for all possible offsets up to maxoffset
146 for both inputs with a size larger than s1 (so memory access outside the
147 expected memory regions might trigger invalid access). */
149 for (size_t off1
= 0; off1
< maxoffset
; off1
++)
151 for (size_t off2
= 0; off2
< maxoffset
; off2
++)
153 FOR_EACH_IMPL (impl
, 0)
154 do_one_test (impl
, s2
+ off2
, s1
+ off1
, maxoffset
- off1
- 1,
155 maxoffset
+ (maxoffset
- off2
));
161 do_random_tests (void)
163 size_t i
, j
, n
, align1
, align2
, len
, size
, mode
;
164 CHAR
*p1
= (CHAR
*) (buf1
+ page_size
) - 1024;
165 CHAR
*p2
= (CHAR
*) (buf2
+ page_size
) - 1024;
168 for (n
= 0; n
< ITERATIONS
; n
++)
170 /* For wcslcpy: align1 and align2 here mean align not in bytes,
171 but in wchar_ts, in bytes it will equal to align * (sizeof
177 size
= random () & 255;
178 align1
= 512 - size
- (random () & 15);
180 align2
= align1
- (random () & 24);
182 align2
= align1
- (random () & 31);
190 len
= size
- (random () & 31);
194 len
= random () & 511;
198 align1
= random () & 31;
200 align2
= random () & 31;
202 align2
= align1
+ (random () & 24);
203 len
= random () & 511;
209 size
= random () & 511;
211 size
= 512 - j
- (random () & 31);
215 if ((mode
& 8) && len
+ j
>= 512)
216 len
= 512 - j
- (random () & 7);
219 for (i
= 0; i
< j
; i
++)
221 p1
[i
] = random () & BIG_CHAR
;
222 if (i
>= align1
&& i
< len
+ align1
&& !p1
[i
])
223 p1
[i
] = (random () & SMALL_CHAR
) + 3;
227 FOR_EACH_IMPL (impl
, 1)
229 MEMSET (p2
- 64, '\1', 512 + 64);
230 res
= CALL (impl
, (CHAR
*) (p2
+ align2
),
231 (CHAR
*) (p1
+ align1
), size
);
234 error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %zd) %zd != %zd",
235 n
, impl
->name
, align1
, align2
, len
, res
);
238 for (j
= 0; j
< align2
+ 64; ++j
)
240 if (p2
[j
- 64] != '\1')
242 error (0, 0, "Iteration %zd - garbage before, %s (%zd, %zd, %zd)",
243 n
, impl
->name
, align1
, align2
, len
);
248 j
= align2
+ len
+ 1;
249 if (size
+ align2
> j
)
255 error (0, 0, "Iteration %zd - garbage after, %s (%zd, %zd, %zd)",
256 n
, impl
->name
, align1
, align2
, len
);
262 /* Check for zero size. */
267 if (MEMCMP (p1
+ align1
, p2
+ align2
, j
))
269 error (0, 0, "Iteration %zd - different strings, %s (%zd, %zd, %zd)",
270 n
, impl
->name
, align1
, align2
, len
);
275 error (0, 0, "Iteration %zd - garbage after size, %s (%zd, %zd, %zd)",
276 n
, impl
->name
, align1
, align2
, len
);
293 FOR_EACH_IMPL (impl
, 0)
294 printf ("\t%s", impl
->name
);
297 for (i
= 1; i
< 8; ++i
)
299 do_test (i
, i
, 16, 16, SMALL_CHAR
);
300 do_test (i
, i
, 16, 16, BIG_CHAR
);
301 do_test (i
, 2 * i
, 16, 16, SMALL_CHAR
);
302 do_test (2 * i
, i
, 16, 16, BIG_CHAR
);
303 do_test (8 - i
, 2 * i
, 1 << i
, 2 << i
, SMALL_CHAR
);
304 do_test (2 * i
, 8 - i
, 2 << i
, 1 << i
, SMALL_CHAR
);
305 do_test (8 - i
, 2 * i
, 1 << i
, 2 << i
, BIG_CHAR
);
306 do_test (2 * i
, 8 - i
, 2 << i
, 1 << i
, BIG_CHAR
);
309 for (i
= 1; i
< 8; ++i
)
311 do_test (0, 0, 4 << i
, 8 << i
, SMALL_CHAR
);
312 do_test (0, 0, 16 << i
, 8 << i
, SMALL_CHAR
);
313 do_test (8 - i
, 2 * i
, 4 << i
, 8 << i
, SMALL_CHAR
);
314 do_test (8 - i
, 2 * i
, 16 << i
, 8 << i
, SMALL_CHAR
);
322 #include <support/test-driver.c>