test-strncpy.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. /* Test strncpy functions.
  2. Copyright (C) 1999-2026 Free Software Foundation, Inc.
  3. This file is part of the GNU C Library.
  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.
  8. The GNU C Library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with the GNU C Library; if not, see
  14. <https://www.gnu.org/licenses/>. */
  15. #ifdef WIDE
  16. # include <wchar.h>
  17. # define CHAR wchar_t
  18. # define UCHAR wchar_t
  19. # define BIG_CHAR WCHAR_MAX
  20. # define SMALL_CHAR 1273
  21. # define MEMCMP wmemcmp
  22. # define MEMSET wmemset
  23. # define STRNLEN wcsnlen
  24. #else
  25. # define CHAR char
  26. # define UCHAR unsigned char
  27. # define BIG_CHAR CHAR_MAX
  28. # define SMALL_CHAR 127
  29. # define MEMCMP memcmp
  30. # define MEMSET memset
  31. # define STRNLEN strnlen
  32. #endif /* !WIDE */
  33. #ifndef STRNCPY_RESULT
  34. # define STRNCPY_RESULT(dst, len, n) dst
  35. # define TEST_MAIN
  36. # ifndef WIDE
  37. # define TEST_NAME "strncpy"
  38. # else
  39. # define TEST_NAME "wcsncpy"
  40. # endif /* WIDE */
  41. # include "test-string.h"
  42. # ifndef WIDE
  43. # define SIMPLE_STRNCPY simple_strncpy
  44. # define STRNCPY strncpy
  45. # else
  46. # define SIMPLE_STRNCPY simple_wcsncpy
  47. # define STRNCPY wcsncpy
  48. # endif /* WIDE */
  49. IMPL (STRNCPY, 1)
  50. /* Naive implementation to verify results. */
  51. CHAR *
  52. SIMPLE_STRNCPY (CHAR *dst, const CHAR *src, size_t n)
  53. {
  54. CHAR *ret = dst;
  55. while (n--)
  56. if ((*dst++ = *src++) == '\0')
  57. {
  58. while (n--)
  59. *dst++ = '\0';
  60. return ret;
  61. }
  62. return ret;
  63. }
  64. #endif /* !STRNCPY_RESULT */
  65. typedef CHAR *(*proto_t) (CHAR *, const CHAR *, size_t);
  66. static void
  67. do_one_test (impl_t *impl, CHAR *dst, const CHAR *src, size_t len, size_t n)
  68. {
  69. if (CALL (impl, dst, src, n) != STRNCPY_RESULT (dst, len, n))
  70. {
  71. error (0, 0, "Wrong result in function %s %p %p", impl->name,
  72. CALL (impl, dst, src, n), dst);
  73. ret = 1;
  74. return;
  75. }
  76. if (memcmp (dst, src, (len > n ? n : len) * sizeof (CHAR)) != 0)
  77. {
  78. error (0, 0, "Wrong result in function %s", impl->name);
  79. ret = 1;
  80. return;
  81. }
  82. if (n > len)
  83. {
  84. size_t i;
  85. for (i = len; i < n; ++i)
  86. if (dst [i] != '\0')
  87. {
  88. error (0, 0, "Wrong result in function %s", impl->name);
  89. ret = 1;
  90. return;
  91. }
  92. }
  93. }
  94. static void
  95. do_test (size_t align1, size_t align2, size_t len, size_t n, int max_char)
  96. {
  97. size_t i;
  98. CHAR *s1, *s2;
  99. /* For wcsncpy: align1 and align2 here mean alignment not in bytes,
  100. but in wchar_ts, in bytes it will equal to align * (sizeof (wchar_t)). */
  101. align1 &= 7;
  102. if ((align1 + len) * sizeof (CHAR) >= page_size)
  103. return;
  104. align2 &= 7;
  105. if ((align2 + len) * sizeof (CHAR) >= page_size)
  106. return;
  107. s1 = (CHAR *) (buf1) + align1;
  108. s2 = (CHAR *) (buf2) + align2;
  109. for (i = 0; i < len; ++i)
  110. s1[i] = 32 + 23 * i % (max_char - 32);
  111. s1[len] = 0;
  112. for (i = len + 1; (i + align1) * sizeof (CHAR) < page_size && i < len + 64;
  113. ++i)
  114. s1[i] = 32 + 32 * i % (max_char - 32);
  115. FOR_EACH_IMPL (impl, 0)
  116. do_one_test (impl, s2, s1, len, n);
  117. }
  118. static void
  119. do_page_tests (void)
  120. {
  121. CHAR *s1, *s2;
  122. const size_t maxoffset = 64;
  123. /* Put s1 at the maxoffset from the edge of buf1's last page. */
  124. s1 = (CHAR *) buf1 + BUF1PAGES * page_size / sizeof(CHAR) - maxoffset;
  125. /* s2 needs room to put a string with size of maxoffset + 1 at s2 +
  126. (maxoffset - 1). */
  127. s2 = (CHAR *) buf2 + page_size / sizeof(CHAR) - maxoffset * 2;
  128. MEMSET (s1, 'a', maxoffset - 1);
  129. s1[maxoffset - 1] = '\0';
  130. /* Both strings are bounded to a page with read/write access and the next
  131. page is protected with PROT_NONE (meaning that any access outside of the
  132. page regions will trigger an invalid memory access).
  133. The loop copies the string s1 for all possible offsets up to maxoffset
  134. for both inputs with a size larger than s1 (so memory access outside the
  135. expected memory regions might trigger invalid access). */
  136. for (size_t off1 = 0; off1 < maxoffset; off1++)
  137. {
  138. for (size_t off2 = 0; off2 < maxoffset; off2++)
  139. {
  140. FOR_EACH_IMPL (impl, 0)
  141. do_one_test (impl, s2 + off2, s1 + off1, maxoffset - off1 - 1,
  142. maxoffset + (maxoffset - off2));
  143. }
  144. }
  145. }
  146. static void
  147. do_random_tests (void)
  148. {
  149. size_t i, j, n, align1, align2, len, size, mode;
  150. UCHAR *p1 = (UCHAR *) (buf1 + page_size) - 512;
  151. UCHAR *p2 = (UCHAR *) (buf2 + page_size) - 512;
  152. UCHAR *res;
  153. for (n = 0; n < ITERATIONS; n++)
  154. {
  155. /* For wcsncpy: align1 and align2 here mean align not in bytes,
  156. but in wchar_ts, in bytes it will equal to align * (sizeof
  157. (wchar_t)). */
  158. mode = random ();
  159. if (mode & 1)
  160. {
  161. size = random () & 255;
  162. align1 = 512 - size - (random () & 15);
  163. if (mode & 2)
  164. align2 = align1 - (random () & 24);
  165. else
  166. align2 = align1 - (random () & 31);
  167. if (mode & 4)
  168. {
  169. j = align1;
  170. align1 = align2;
  171. align2 = j;
  172. }
  173. if (mode & 8)
  174. len = size - (random () & 31);
  175. else
  176. len = 512;
  177. if (len >= 512)
  178. len = random () & 511;
  179. }
  180. else
  181. {
  182. align1 = random () & 31;
  183. if (mode & 2)
  184. align2 = random () & 31;
  185. else
  186. align2 = align1 + (random () & 24);
  187. len = random () & 511;
  188. j = align1;
  189. if (align2 > j)
  190. j = align2;
  191. if (mode & 4)
  192. {
  193. size = random () & 511;
  194. if (size + j > 512)
  195. size = 512 - j - (random () & 31);
  196. }
  197. else
  198. size = 512 - j;
  199. if ((mode & 8) && len + j >= 512)
  200. len = 512 - j - (random () & 7);
  201. }
  202. j = len + align1 + 64;
  203. if (j > 512)
  204. j = 512;
  205. for (i = 0; i < j; i++)
  206. {
  207. if (i == len + align1)
  208. p1[i] = 0;
  209. else
  210. {
  211. p1[i] = random () & BIG_CHAR;
  212. if (i >= align1 && i < len + align1 && !p1[i])
  213. p1[i] = (random () & SMALL_CHAR) + 3;
  214. }
  215. }
  216. FOR_EACH_IMPL (impl, 1)
  217. {
  218. MEMSET (p2 - 64, '\1', 512 + 64);
  219. res = (UCHAR *) CALL (impl, (CHAR *) (p2 + align2),
  220. (CHAR *) (p1 + align1), size);
  221. if (res != STRNCPY_RESULT (p2 + align2, len, size))
  222. {
  223. error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %zd, %zd) %p != %p",
  224. n, impl->name, align1, align2, len, res,
  225. STRNCPY_RESULT (p2 + align2, len, size));
  226. ret = 1;
  227. }
  228. for (j = 0; j < align2 + 64; ++j)
  229. {
  230. if (p2[j - 64] != '\1')
  231. {
  232. error (0, 0, "Iteration %zd - garbage before, %s (%zd, %zd, %zd)",
  233. n, impl->name, align1, align2, len);
  234. ret = 1;
  235. break;
  236. }
  237. }
  238. j = align2 + len + 1;
  239. if (size + align2 > j)
  240. j = size + align2;
  241. for (; j < 512; ++j)
  242. {
  243. if (p2[j] != '\1')
  244. {
  245. error (0, 0, "Iteration %zd - garbage after, %s (%zd, %zd, %zd)",
  246. n, impl->name, align1, align2, len);
  247. ret = 1;
  248. break;
  249. }
  250. }
  251. for (j = align2 + len + 1; j < align2 + size; ++j)
  252. if (p2[j])
  253. {
  254. error (0, 0, "Iteration %zd - garbage after size, %s (%zd, %zd, %zd)",
  255. n, impl->name, align1, align2, len);
  256. ret = 1;
  257. break;
  258. }
  259. j = len + 1;
  260. if (size < j)
  261. j = size;
  262. if (MEMCMP (p1 + align1, p2 + align2, j))
  263. {
  264. error (0, 0, "Iteration %zd - different strings, %s (%zd, %zd, %zd)",
  265. n, impl->name, align1, align2, len);
  266. ret = 1;
  267. }
  268. }
  269. }
  270. }
  271. int
  272. test_main (void)
  273. {
  274. size_t i;
  275. test_init ();
  276. printf ("%28s", "");
  277. FOR_EACH_IMPL (impl, 0)
  278. printf ("\t%s", impl->name);
  279. putchar ('\n');
  280. for (i = 1; i < 8; ++i)
  281. {
  282. do_test (i, i, 16, 16, SMALL_CHAR);
  283. do_test (i, i, 16, 16, BIG_CHAR);
  284. do_test (i, 2 * i, 16, 16, SMALL_CHAR);
  285. do_test (2 * i, i, 16, 16, BIG_CHAR);
  286. do_test (8 - i, 2 * i, 1 << i, 2 << i, SMALL_CHAR);
  287. do_test (2 * i, 8 - i, 2 << i, 1 << i, SMALL_CHAR);
  288. do_test (8 - i, 2 * i, 1 << i, 2 << i, BIG_CHAR);
  289. do_test (2 * i, 8 - i, 2 << i, 1 << i, BIG_CHAR);
  290. }
  291. for (i = 1; i < 8; ++i)
  292. {
  293. do_test (0, 0, 4 << i, 8 << i, SMALL_CHAR);
  294. do_test (0, 0, 16 << i, 8 << i, SMALL_CHAR);
  295. do_test (8 - i, 2 * i, 4 << i, 8 << i, SMALL_CHAR);
  296. do_test (8 - i, 2 * i, 16 << i, 8 << i, SMALL_CHAR);
  297. }
  298. do_random_tests ();
  299. do_page_tests ();
  300. return ret;
  301. }
  302. #include <support/test-driver.c>