1 /* Test strncpy functions.
2 Copyright (C) 1999-2021 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/>. */
22 # define UCHAR wchar_t
23 # define BIG_CHAR WCHAR_MAX
24 # define SMALL_CHAR 1273
25 # define MEMCMP wmemcmp
26 # define MEMSET wmemset
27 # define STRNLEN wcsnlen
30 # define UCHAR unsigned char
31 # define BIG_CHAR CHAR_MAX
32 # define SMALL_CHAR 127
33 # define MEMCMP memcmp
34 # define MEMSET memset
35 # define STRNLEN strnlen
39 #ifndef STRNCPY_RESULT
40 # define STRNCPY_RESULT(dst, len, n) dst
43 # define TEST_NAME "strncpy"
45 # define TEST_NAME "wcsncpy"
47 # include "test-string.h"
49 # define SIMPLE_STRNCPY simple_strncpy
50 # define STUPID_STRNCPY stupid_strncpy
51 # define STRNCPY strncpy
53 # define SIMPLE_STRNCPY simple_wcsncpy
54 # define STUPID_STRNCPY stupid_wcsncpy
55 # define STRNCPY wcsncpy
58 CHAR
*SIMPLE_STRNCPY (CHAR
*, const CHAR
*, size_t);
59 CHAR
*STUPID_STRNCPY (CHAR
*, const CHAR
*, size_t);
61 IMPL (STUPID_STRNCPY
, 0)
62 IMPL (SIMPLE_STRNCPY
, 0)
66 SIMPLE_STRNCPY (CHAR
*dst
, const CHAR
*src
, size_t n
)
70 if ((*dst
++ = *src
++) == '\0')
80 STUPID_STRNCPY (CHAR
*dst
, const CHAR
*src
, size_t n
)
82 size_t nc
= STRNLEN (src
, n
);
85 for (i
= 0; i
< nc
; ++i
)
91 #endif /* !STRNCPY_RESULT */
93 typedef CHAR
*(*proto_t
) (CHAR
*, const CHAR
*, size_t);
96 do_one_test (impl_t
*impl
, CHAR
*dst
, const CHAR
*src
, size_t len
, size_t n
)
98 if (CALL (impl
, dst
, src
, n
) != STRNCPY_RESULT (dst
, len
, n
))
100 error (0, 0, "Wrong result in function %s %p %p", impl
->name
,
101 CALL (impl
, dst
, src
, n
), dst
);
106 if (memcmp (dst
, src
, (len
> n
? n
: len
) * sizeof (CHAR
)) != 0)
108 error (0, 0, "Wrong result in function %s", impl
->name
);
117 for (i
= len
; i
< n
; ++i
)
120 error (0, 0, "Wrong result in function %s", impl
->name
);
128 do_test (size_t align1
, size_t align2
, size_t len
, size_t n
, int max_char
)
133 /* For wcsncpy: align1 and align2 here mean alignment not in bytes,
134 but in wchar_ts, in bytes it will equal to align * (sizeof (wchar_t)). */
136 if ((align1
+ len
) * sizeof (CHAR
) >= page_size
)
140 if ((align2
+ len
) * sizeof (CHAR
) >= page_size
)
143 s1
= (CHAR
*) (buf1
) + align1
;
144 s2
= (CHAR
*) (buf2
) + align2
;
146 for (i
= 0; i
< len
; ++i
)
147 s1
[i
] = 32 + 23 * i
% (max_char
- 32);
149 for (i
= len
+ 1; (i
+ align1
) * sizeof (CHAR
) < page_size
&& i
< len
+ 64;
151 s1
[i
] = 32 + 32 * i
% (max_char
- 32);
153 FOR_EACH_IMPL (impl
, 0)
154 do_one_test (impl
, s2
, s1
, len
, n
);
161 const size_t maxoffset
= 64;
163 /* Put s1 at the maxoffset from the edge of buf1's last page. */
164 s1
= (CHAR
*) buf1
+ BUF1PAGES
* page_size
/ sizeof(CHAR
) - maxoffset
;
165 /* s2 needs room to put a string with size of maxoffset + 1 at s2 +
167 s2
= (CHAR
*) buf2
+ page_size
/ sizeof(CHAR
) - maxoffset
* 2;
169 MEMSET (s1
, 'a', maxoffset
- 1);
170 s1
[maxoffset
- 1] = '\0';
172 /* Both strings are bounded to a page with read/write access and the next
173 page is protected with PROT_NONE (meaning that any access outside of the
174 page regions will trigger an invalid memory access).
176 The loop copies the string s1 for all possible offsets up to maxoffset
177 for both inputs with a size larger than s1 (so memory access outside the
178 expected memory regions might trigger invalid access). */
180 for (size_t off1
= 0; off1
< maxoffset
; off1
++)
182 for (size_t off2
= 0; off2
< maxoffset
; off2
++)
184 FOR_EACH_IMPL (impl
, 0)
185 do_one_test (impl
, s2
+ off2
, s1
+ off1
, maxoffset
- off1
- 1,
186 maxoffset
+ (maxoffset
- off2
));
192 do_random_tests (void)
194 size_t i
, j
, n
, align1
, align2
, len
, size
, mode
;
195 UCHAR
*p1
= (UCHAR
*) (buf1
+ page_size
) - 512;
196 UCHAR
*p2
= (UCHAR
*) (buf2
+ page_size
) - 512;
199 for (n
= 0; n
< ITERATIONS
; n
++)
201 /* For wcsncpy: align1 and align2 here mean align not in bytes,
202 but in wchar_ts, in bytes it will equal to align * (sizeof
208 size
= random () & 255;
209 align1
= 512 - size
- (random () & 15);
211 align2
= align1
- (random () & 24);
213 align2
= align1
- (random () & 31);
221 len
= size
- (random () & 31);
225 len
= random () & 511;
229 align1
= random () & 31;
231 align2
= random () & 31;
233 align2
= align1
+ (random () & 24);
234 len
= random () & 511;
240 size
= random () & 511;
242 size
= 512 - j
- (random () & 31);
246 if ((mode
& 8) && len
+ j
>= 512)
247 len
= 512 - j
- (random () & 7);
249 j
= len
+ align1
+ 64;
252 for (i
= 0; i
< j
; i
++)
254 if (i
== len
+ align1
)
258 p1
[i
] = random () & BIG_CHAR
;
259 if (i
>= align1
&& i
< len
+ align1
&& !p1
[i
])
260 p1
[i
] = (random () & SMALL_CHAR
) + 3;
264 FOR_EACH_IMPL (impl
, 1)
266 MEMSET (p2
- 64, '\1', 512 + 64);
267 res
= (UCHAR
*) CALL (impl
, (CHAR
*) (p2
+ align2
),
268 (CHAR
*) (p1
+ align1
), size
);
269 if (res
!= STRNCPY_RESULT (p2
+ align2
, len
, size
))
271 error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %zd, %zd) %p != %p",
272 n
, impl
->name
, align1
, align2
, len
, res
,
273 STRNCPY_RESULT (p2
+ align2
, len
, size
));
276 for (j
= 0; j
< align2
+ 64; ++j
)
278 if (p2
[j
- 64] != '\1')
280 error (0, 0, "Iteration %zd - garbage before, %s (%zd, %zd, %zd)",
281 n
, impl
->name
, align1
, align2
, len
);
286 j
= align2
+ len
+ 1;
287 if (size
+ align2
> j
)
293 error (0, 0, "Iteration %zd - garbage after, %s (%zd, %zd, %zd)",
294 n
, impl
->name
, align1
, align2
, len
);
299 for (j
= align2
+ len
+ 1; j
< align2
+ size
; ++j
)
302 error (0, 0, "Iteration %zd - garbage after size, %s (%zd, %zd, %zd)",
303 n
, impl
->name
, align1
, align2
, len
);
310 if (MEMCMP (p1
+ align1
, p2
+ align2
, j
))
312 error (0, 0, "Iteration %zd - different strings, %s (%zd, %zd, %zd)",
313 n
, impl
->name
, align1
, align2
, len
);
328 FOR_EACH_IMPL (impl
, 0)
329 printf ("\t%s", impl
->name
);
332 for (i
= 1; i
< 8; ++i
)
334 do_test (i
, i
, 16, 16, SMALL_CHAR
);
335 do_test (i
, i
, 16, 16, BIG_CHAR
);
336 do_test (i
, 2 * i
, 16, 16, SMALL_CHAR
);
337 do_test (2 * i
, i
, 16, 16, BIG_CHAR
);
338 do_test (8 - i
, 2 * i
, 1 << i
, 2 << i
, SMALL_CHAR
);
339 do_test (2 * i
, 8 - i
, 2 << i
, 1 << i
, SMALL_CHAR
);
340 do_test (8 - i
, 2 * i
, 1 << i
, 2 << i
, BIG_CHAR
);
341 do_test (2 * i
, 8 - i
, 2 << i
, 1 << i
, BIG_CHAR
);
344 for (i
= 1; i
< 8; ++i
)
346 do_test (0, 0, 4 << i
, 8 << i
, SMALL_CHAR
);
347 do_test (0, 0, 16 << i
, 8 << i
, SMALL_CHAR
);
348 do_test (8 - i
, 2 * i
, 4 << i
, 8 << i
, SMALL_CHAR
);
349 do_test (8 - i
, 2 * i
, 16 << i
, 8 << i
, SMALL_CHAR
);
357 #include <support/test-driver.c>