test-strnlen.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. /* Test strlen 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. #define TEST_MAIN
  16. #ifndef WIDE
  17. # define TEST_NAME "strnlen"
  18. #else
  19. # define TEST_NAME "wcsnlen"
  20. #endif /* !WIDE */
  21. #include "test-string.h"
  22. #ifndef WIDE
  23. # define STRNLEN strnlen
  24. # define MEMSET memset
  25. # define CHAR char
  26. # define BIG_CHAR CHAR_MAX
  27. # define MIDDLE_CHAR 127
  28. # define SIMPLE_STRNLEN simple_strnlen
  29. #else
  30. # include <wchar.h>
  31. # define STRNLEN wcsnlen
  32. # define MEMSET wmemset
  33. # define CHAR wchar_t
  34. # define BIG_CHAR WCHAR_MAX
  35. # define MIDDLE_CHAR 1121
  36. # define SIMPLE_STRNLEN simple_wcsnlen
  37. #endif /* !WIDE */
  38. typedef size_t (*proto_t) (const CHAR *, size_t);
  39. /* Also check the default implementation. */
  40. #undef STRNLEN
  41. #ifndef WIDE
  42. # define MEMCHR __memchr_default
  43. # define static_weak_alias(a, b)
  44. # define libc_hidden_def(a)
  45. # define libc_hidden_builtin_def(a)
  46. # include "string/memchr.c"
  47. # undef STRNLEN
  48. # define STRNLEN __strnlen_default
  49. # define memchr __memchr_default
  50. # include "string/strnlen.c"
  51. IMPL (__strnlen_default, 1)
  52. #else
  53. # define WMEMCHR __wmemchr_default
  54. # define static_weak_alias(a, b)
  55. # define libc_hidden_def(a)
  56. # define libc_hidden_weak(a)
  57. # include "wcsmbs/wmemchr.c"
  58. # define WCSNLEN __wcsnlen_default
  59. # undef wmemchr
  60. # define wmemchr __wmemchr_default
  61. # include "wcsmbs/wcsnlen.c"
  62. IMPL (__wcsnlen_default, 1)
  63. #endif
  64. static void
  65. do_one_test (impl_t *impl, const CHAR *s, size_t maxlen, size_t exp_len)
  66. {
  67. size_t len = CALL (impl, s, maxlen);
  68. if (len != exp_len)
  69. {
  70. error (0, 0, "Wrong result in function %s %zd %zd", impl->name,
  71. len, exp_len);
  72. ret = 1;
  73. return;
  74. }
  75. }
  76. static void
  77. do_test (size_t align, size_t len, size_t maxlen, int max_char)
  78. {
  79. size_t i;
  80. align &= (getpagesize () / sizeof (CHAR) - 1);
  81. if ((align + len) * sizeof (CHAR) >= page_size)
  82. return;
  83. CHAR *buf = (CHAR *) (buf1);
  84. for (i = 0; i < len; ++i)
  85. buf[align + i] = 1 + 11111 * i % max_char;
  86. buf[align + len] = 0;
  87. FOR_EACH_IMPL (impl, 0)
  88. do_one_test (impl, (CHAR *) (buf + align), maxlen, MIN (len, maxlen));
  89. }
  90. static void
  91. do_overflow_tests (void)
  92. {
  93. size_t i, j, al_idx, repeats, len;
  94. const size_t one = 1;
  95. uintptr_t buf_addr = (uintptr_t) buf1;
  96. const size_t alignments[] = { 0, 1, 7, 9, 31, 33, 63, 65, 95, 97, 127, 129 };
  97. for (al_idx = 0; al_idx < sizeof (alignments) / sizeof (alignments[0]);
  98. al_idx++)
  99. {
  100. for (repeats = 0; repeats < 2; ++repeats)
  101. {
  102. size_t align = repeats ? (getpagesize () - alignments[al_idx])
  103. : alignments[al_idx];
  104. align /= sizeof (CHAR);
  105. for (i = 0; i < 750; ++i)
  106. {
  107. do_test (align, i, SIZE_MAX, BIG_CHAR);
  108. do_test (align, i, SIZE_MAX - i, BIG_CHAR);
  109. do_test (align, i, i - buf_addr, BIG_CHAR);
  110. do_test (align, i, -buf_addr - i, BIG_CHAR);
  111. do_test (align, i, SIZE_MAX - buf_addr - i, BIG_CHAR);
  112. do_test (align, i, SIZE_MAX - buf_addr + i, BIG_CHAR);
  113. len = 0;
  114. for (j = 8 * sizeof (size_t) - 1; j; --j)
  115. {
  116. len |= one << j;
  117. do_test (align, i, len, BIG_CHAR);
  118. do_test (align, i, len - i, BIG_CHAR);
  119. do_test (align, i, len + i, BIG_CHAR);
  120. do_test (align, i, len - buf_addr - i, BIG_CHAR);
  121. do_test (align, i, len - buf_addr + i, BIG_CHAR);
  122. do_test (align, i, ~len - i, BIG_CHAR);
  123. do_test (align, i, ~len + i, BIG_CHAR);
  124. do_test (align, i, ~len - buf_addr - i, BIG_CHAR);
  125. do_test (align, i, ~len - buf_addr + i, BIG_CHAR);
  126. do_test (align, i, -buf_addr, BIG_CHAR);
  127. do_test (align, i, j - buf_addr, BIG_CHAR);
  128. do_test (align, i, -buf_addr - j, BIG_CHAR);
  129. }
  130. }
  131. }
  132. }
  133. }
  134. static void
  135. do_random_tests (void)
  136. {
  137. size_t i, j, n, align, len;
  138. CHAR *p = (CHAR *) (buf1 + page_size - 512 * sizeof (CHAR));
  139. for (n = 0; n < ITERATIONS; n++)
  140. {
  141. align = random () & 15;
  142. len = random () & 511;
  143. if (len + align > 510)
  144. len = 511 - align - (random () & 7);
  145. j = len + align + 64;
  146. if (j > 512)
  147. j = 512;
  148. for (i = 0; i < j; i++)
  149. {
  150. if (i == len + align)
  151. p[i] = 0;
  152. else
  153. {
  154. p[i] = random () & 255;
  155. if (i >= align && i < len + align && !p[i])
  156. p[i] = (random () & 127) + 1;
  157. }
  158. }
  159. FOR_EACH_IMPL (impl, 1)
  160. {
  161. if (len > 0
  162. && CALL (impl, (CHAR *) (p + align), len - 1) != len - 1)
  163. {
  164. error (0, 0, "Iteration %zd (limited) - wrong result in function %s (%zd) %zd != %zd, p %p",
  165. n, impl->name, align,
  166. CALL (impl, (CHAR *) (p + align), len - 1), len - 1, p);
  167. ret = 1;
  168. }
  169. if (CALL (impl, (CHAR *) (p + align), len) != len)
  170. {
  171. error (0, 0, "Iteration %zd (exact) - wrong result in function %s (%zd) %zd != %zd, p %p",
  172. n, impl->name, align,
  173. CALL (impl, (CHAR *) (p + align), len), len, p);
  174. ret = 1;
  175. }
  176. if (CALL (impl, (CHAR *) (p + align), len + 1) != len)
  177. {
  178. error (0, 0, "Iteration %zd (long) - wrong result in function %s (%zd) %zd != %zd, p %p",
  179. n, impl->name, align,
  180. CALL (impl, (CHAR *) (p + align), len + 1), len, p);
  181. ret = 1;
  182. }
  183. }
  184. }
  185. }
  186. /* Tests meant to unveil fail on implementation that does not access bytes
  187. around the page boundary accordingly. */
  188. static void
  189. do_page_tests (void)
  190. {
  191. size_t i, exp_len, start_offset, offset;
  192. /* Calculate the null character offset. */
  193. size_t last_offset = (page_size / sizeof (CHAR)) - 1;
  194. CHAR *s = (CHAR *) buf2;
  195. MEMSET (s, 65, (last_offset - 1));
  196. s[last_offset] = 0;
  197. /* Place short strings ending at page boundary. */
  198. offset = last_offset;
  199. for (i = 0; i < 128; i++)
  200. {
  201. /* Decrease offset to stress several sizes and alignments. */
  202. offset--;
  203. exp_len = last_offset - offset;
  204. FOR_EACH_IMPL (impl, 0)
  205. {
  206. /* Varies maxlen value to cover the cases where it is:
  207. - larger than length;
  208. - slightly greater than length;
  209. - equal to length;
  210. - slightly less than length. */
  211. do_one_test (impl, (CHAR *) (s + offset), page_size, exp_len);
  212. do_one_test (impl, (CHAR *) (s + offset), exp_len + 1, exp_len);
  213. do_one_test (impl, (CHAR *) (s + offset), exp_len, exp_len);
  214. if (exp_len > 0)
  215. do_one_test (impl, (CHAR *) (s + offset), exp_len - 1, exp_len - 1);
  216. }
  217. }
  218. /* Place long strings ending at page boundary. */
  219. start_offset = (last_offset + 1) / 2;
  220. for (i = 0; i < 64; ++i)
  221. {
  222. /* Increase offset to stress several alignments. */
  223. offset = start_offset + i;
  224. if (offset >= (last_offset + 1))
  225. break;
  226. exp_len = last_offset - offset;
  227. FOR_EACH_IMPL (impl, 0)
  228. {
  229. /* Checks only for maxlen much larger than length because smaller
  230. values are already covered in do_random_tests function. */
  231. do_one_test (impl, (CHAR *) (s + offset), page_size, exp_len);
  232. }
  233. }
  234. }
  235. /* Tests meant to unveil fail on implementations that access bytes
  236. beyond the maximum length. */
  237. static void
  238. do_page_2_tests (void)
  239. {
  240. size_t i, exp_len, offset;
  241. size_t last_offset = page_size / sizeof (CHAR);
  242. CHAR *s = (CHAR *) buf2;
  243. MEMSET (s, 65, last_offset);
  244. /* Place short strings ending at page boundary without the null
  245. byte. */
  246. offset = last_offset;
  247. for (i = 0; i < 128; i++)
  248. {
  249. /* Decrease offset to stress several sizes and alignments. */
  250. offset--;
  251. exp_len = last_offset - offset;
  252. FOR_EACH_IMPL (impl, 0)
  253. {
  254. /* If an implementation goes beyond EXP_LEN, it will trigger
  255. the segfault. */
  256. do_one_test (impl, (CHAR *) (s + offset), exp_len, exp_len);
  257. }
  258. }
  259. }
  260. int
  261. test_main (void)
  262. {
  263. size_t i, length, char_per_page;
  264. test_init ();
  265. printf ("%20s", "");
  266. FOR_EACH_IMPL (impl, 0)
  267. printf ("\t%s", impl->name);
  268. putchar ('\n');
  269. for (i = 1; i < 8; ++i)
  270. {
  271. do_test (0, i, i - 1, MIDDLE_CHAR);
  272. do_test (0, i, i, MIDDLE_CHAR);
  273. do_test (0, i, i + 1, MIDDLE_CHAR);
  274. }
  275. for (i = 1; i < 8; ++i)
  276. {
  277. do_test (i, i, i - 1, MIDDLE_CHAR);
  278. do_test (i, i, i, MIDDLE_CHAR);
  279. do_test (i, i, i + 1, MIDDLE_CHAR);
  280. }
  281. for (i = 2; i <= 10; ++i)
  282. {
  283. do_test (0, 1 << i, 5000, MIDDLE_CHAR);
  284. do_test (1, 1 << i, 5000, MIDDLE_CHAR);
  285. }
  286. for (i = 1; i < 8; ++i)
  287. do_test (0, i, 5000, BIG_CHAR);
  288. for (i = 1; i < 8; ++i)
  289. do_test (i, i, 5000, BIG_CHAR);
  290. for (i = 2; i <= 10; ++i)
  291. {
  292. do_test (0, 1 << i, 5000, BIG_CHAR);
  293. do_test (1, 1 << i, 5000, BIG_CHAR);
  294. }
  295. char_per_page = getpagesize () / sizeof (CHAR);
  296. for (i = 0; i <= 127; i++)
  297. for (length = i; length <= 512; length++)
  298. {
  299. do_test (i, length, 512, BIG_CHAR);
  300. do_test (char_per_page - i, length, 512, BIG_CHAR);
  301. }
  302. do_random_tests ();
  303. do_page_tests ();
  304. do_page_2_tests ();
  305. do_overflow_tests ();
  306. return ret;
  307. }
  308. #include <support/test-driver.c>