stratcliff.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618
  1. /* Test for string function add boundaries of usable memory.
  2. Copyright (C) 1996-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 _GNU_SOURCE 1
  16. /* Make sure we don't test the optimized inline functions if we want to
  17. test the real implementation. */
  18. #undef __USE_STRING_INLINES
  19. #include <errno.h>
  20. #include <stdio.h>
  21. #include <string.h>
  22. #include <unistd.h>
  23. #include <sys/mman.h>
  24. #include <sys/param.h>
  25. #ifndef CHAR
  26. # define L(c) c
  27. # define CHAR char
  28. # define MEMSET memset
  29. # define STRLEN strlen
  30. # define STRNLEN strnlen
  31. # define STRCHR strchr
  32. # define STRRCHR strrchr
  33. # define STRCPY strcpy
  34. # define STRNCPY strncpy
  35. # define MEMCMP memcmp
  36. # define STPCPY stpcpy
  37. # define STPNCPY stpncpy
  38. # define MEMCPY memcpy
  39. # define MEMPCPY mempcpy
  40. # define MEMCHR memchr
  41. # define STRCMP strcmp
  42. # define STRNCMP strncmp
  43. #endif
  44. #define STRINGIFY(s) STRINGIFY2 (s)
  45. #define STRINGIFY2(s) #s
  46. int
  47. do_test (void)
  48. {
  49. size_t size = sysconf (_SC_PAGESIZE);
  50. size_t nchars = size / sizeof (CHAR);
  51. CHAR *adr;
  52. CHAR *dest;
  53. int result = 0;
  54. adr = (CHAR *) mmap (NULL, 3 * size, PROT_READ | PROT_WRITE,
  55. MAP_PRIVATE | MAP_ANON, -1, 0);
  56. dest = (CHAR *) mmap (NULL, 3 * size, PROT_READ | PROT_WRITE,
  57. MAP_PRIVATE | MAP_ANON, -1, 0);
  58. if (adr == MAP_FAILED || dest == MAP_FAILED)
  59. {
  60. if (errno == ENOSYS)
  61. puts ("No test, mmap not available.");
  62. else
  63. {
  64. printf ("mmap failed: %m");
  65. result = 1;
  66. }
  67. }
  68. else
  69. {
  70. size_t inner, middle, outer, nchars64, max128;
  71. if (nchars > 64)
  72. nchars64 = nchars - 64;
  73. else
  74. nchars64 = 0;
  75. if (nchars > 128)
  76. max128 = nchars - 128;
  77. else
  78. max128 = 0;
  79. mprotect (adr, size, PROT_NONE);
  80. mprotect (adr + 2 * nchars, size, PROT_NONE);
  81. adr += nchars;
  82. mprotect (dest, size, PROT_NONE);
  83. mprotect (dest + 2 * nchars, size, PROT_NONE);
  84. dest += nchars;
  85. MEMSET (adr, L('T'), nchars);
  86. /* strlen/wcslen test */
  87. for (outer = nchars - 1; outer >= max128; --outer)
  88. {
  89. for (inner = MAX (outer, nchars64); inner < nchars; ++inner)
  90. {
  91. adr[inner] = L('\0');
  92. if (STRLEN (&adr[outer]) != (size_t) (inner - outer))
  93. {
  94. printf ("%s flunked for outer = %zu, inner = %zu\n",
  95. STRINGIFY (STRLEN), outer, inner);
  96. result = 1;
  97. }
  98. adr[inner] = L('T');
  99. }
  100. if (outer == 0)
  101. break;
  102. }
  103. /* strnlen/wcsnlen test */
  104. for (outer = nchars; outer >= max128; --outer)
  105. {
  106. for (inner = MAX (outer, nchars64); inner < nchars; ++inner)
  107. {
  108. adr[inner] = L('\0');
  109. if (STRNLEN (&adr[outer], inner - outer + 1)
  110. != (size_t) (inner - outer))
  111. {
  112. printf ("%s flunked for outer = %zu, inner = %zu\n",
  113. STRINGIFY (STRNLEN), outer, inner);
  114. result = 1;
  115. }
  116. adr[inner] = L('T');
  117. }
  118. if (outer == 0)
  119. break;
  120. }
  121. for (outer = nchars; outer >= max128; --outer)
  122. {
  123. for (inner = MAX (outer, nchars64); inner <= nchars; ++inner)
  124. {
  125. if (STRNLEN (&adr[outer], inner - outer)
  126. != (size_t) (inner - outer))
  127. {
  128. printf ("%s flunked bounded for outer = %zu, inner = %zu\n",
  129. STRINGIFY (STRNLEN), outer, inner);
  130. result = 1;
  131. }
  132. }
  133. if (outer == 0)
  134. break;
  135. }
  136. /* strchr/wcschr test */
  137. for (outer = nchars - 1; outer >= max128; --outer)
  138. {
  139. for (middle = MAX (outer, nchars64); middle < nchars; ++middle)
  140. {
  141. for (inner = middle; inner < nchars; ++inner)
  142. {
  143. adr[middle] = L('V');
  144. adr[inner] = L('\0');
  145. CHAR *cp = STRCHR (&adr[outer], L('V'));
  146. if ((inner == middle && cp != NULL)
  147. || (inner != middle
  148. && (cp - &adr[outer]) != middle - outer))
  149. {
  150. printf ("%s flunked for outer = %zu, middle = %zu, "
  151. "inner = %zu\n",
  152. STRINGIFY (STRCHR), outer, middle, inner);
  153. result = 1;
  154. }
  155. adr[inner] = L('T');
  156. adr[middle] = L('T');
  157. }
  158. }
  159. if (outer == 0)
  160. break;
  161. }
  162. /* Special test. */
  163. adr[nchars - 1] = L('\0');
  164. if (STRCHR (&adr[nchars - 1], L('\n')) != NULL)
  165. {
  166. printf ("%s flunked test of empty string at end of page\n",
  167. STRINGIFY (STRCHR));
  168. result = 1;
  169. }
  170. /* strrchr/wcsrchr test */
  171. for (outer = nchars - 1; outer >= max128; --outer)
  172. {
  173. for (middle = MAX (outer, nchars64); middle < nchars; ++middle)
  174. {
  175. for (inner = middle; inner < nchars; ++inner)
  176. {
  177. adr[middle] = L('V');
  178. adr[inner] = L('\0');
  179. CHAR *cp = STRRCHR (&adr[outer], L('V'));
  180. if ((inner == middle && cp != NULL)
  181. || (inner != middle
  182. && (cp - &adr[outer]) != middle - outer))
  183. {
  184. printf ("%s flunked for outer = %zu, middle = %zu, "
  185. "inner = %zu\n",
  186. STRINGIFY (STRRCHR), outer, middle, inner);
  187. result = 1;
  188. }
  189. adr[inner] = L('T');
  190. adr[middle] = L('T');
  191. }
  192. }
  193. if (outer == 0)
  194. break;
  195. }
  196. /* memchr test */
  197. for (outer = nchars - 1; outer >= max128; --outer)
  198. {
  199. for (middle = MAX (outer, nchars64); middle < nchars; ++middle)
  200. {
  201. adr[middle] = L('V');
  202. CHAR *cp = MEMCHR (&adr[outer], L('V'), 3 * size);
  203. if (cp - &adr[outer] != middle - outer)
  204. {
  205. printf ("%s flunked for outer = %zu, middle = %zu\n",
  206. STRINGIFY (MEMCHR), outer, middle);
  207. result = 1;
  208. }
  209. adr[middle] = L('T');
  210. }
  211. if (outer == 0)
  212. break;
  213. }
  214. for (outer = nchars; outer >= max128; --outer)
  215. {
  216. CHAR *cp = MEMCHR (&adr[outer], L('V'), nchars - outer);
  217. if (cp != NULL)
  218. {
  219. printf ("%s flunked for outer = %zu\n",
  220. STRINGIFY (MEMCHR), outer);
  221. result = 1;
  222. }
  223. if (outer == 0)
  224. break;
  225. }
  226. /* These functions only exist for single-byte characters. */
  227. #ifndef WCSTEST
  228. /* rawmemchr test */
  229. for (outer = nchars - 1; outer >= max128; --outer)
  230. {
  231. for (middle = MAX (outer, nchars64); middle < nchars; ++middle)
  232. {
  233. adr[middle] = L('V');
  234. CHAR *cp = rawmemchr (&adr[outer], L('V'));
  235. if (cp - &adr[outer] != middle - outer)
  236. {
  237. printf ("%s flunked for outer = %zu, middle = %zu\n",
  238. STRINGIFY (rawmemchr), outer, middle);
  239. result = 1;
  240. }
  241. adr[middle] = L('T');
  242. }
  243. if (outer == 0)
  244. break;
  245. }
  246. /* memrchr test */
  247. for (outer = nchars - 1; outer >= max128; --outer)
  248. {
  249. for (middle = MAX (outer, nchars64); middle < nchars; ++middle)
  250. {
  251. adr[middle] = L('V');
  252. CHAR *cp = memrchr (&adr[outer], L('V'), nchars - outer);
  253. if (cp - &adr[outer] != middle - outer)
  254. {
  255. printf ("%s flunked for outer = %zu, middle = %zu\n",
  256. STRINGIFY (memrchr), outer, middle);
  257. result = 1;
  258. }
  259. adr[middle] = L('T');
  260. }
  261. if (outer == 0)
  262. break;
  263. }
  264. for (outer = nchars; outer >= max128; --outer)
  265. {
  266. CHAR *cp = memrchr (&adr[outer], L('V'), nchars - outer);
  267. if (cp != NULL)
  268. {
  269. printf ("%s flunked for outer = %zu\n",
  270. STRINGIFY (memrchr), outer);
  271. result = 1;
  272. }
  273. if (outer == 0)
  274. break;
  275. }
  276. #endif
  277. /* strcpy/wcscpy test */
  278. for (outer = nchars - 1; outer >= max128; --outer)
  279. {
  280. for (inner = MAX (outer, nchars64); inner < nchars; ++inner)
  281. {
  282. adr[inner] = L('\0');
  283. if (STRCPY (dest, &adr[outer]) != dest
  284. || STRLEN (dest) != (size_t) (inner - outer))
  285. {
  286. printf ("%s flunked for outer = %zu, inner = %zu\n",
  287. STRINGIFY (STRCPY), outer, inner);
  288. result = 1;
  289. }
  290. adr[inner] = L('T');
  291. }
  292. if (outer == 0)
  293. break;
  294. }
  295. /* strcmp/wcscmp tests */
  296. for (outer = 1; outer < 32; ++outer)
  297. for (middle = 0; middle < 16; ++middle)
  298. {
  299. MEMSET (adr + middle, L('T'), 256);
  300. adr[256] = L('\0');
  301. MEMSET (dest + nchars - outer, L('T'), outer - 1);
  302. dest[nchars - 1] = L('\0');
  303. if (STRCMP (adr + middle, dest + nchars - outer) <= 0)
  304. {
  305. printf ("%s 1 flunked for outer = %zu, middle = %zu\n",
  306. STRINGIFY (STRCMP), outer, middle);
  307. result = 1;
  308. }
  309. if (STRCMP (dest + nchars - outer, adr + middle) >= 0)
  310. {
  311. printf ("%s 2 flunked for outer = %zu, middle = %zu\n",
  312. STRINGIFY (STRCMP), outer, middle);
  313. result = 1;
  314. }
  315. }
  316. /* strncmp/wcsncmp tests */
  317. for (outer = 1; outer < 32; ++outer)
  318. for (middle = 0; middle < 16; ++middle)
  319. {
  320. MEMSET (adr + middle, L('T'), 256);
  321. adr[256] = L('\0');
  322. MEMSET (dest + nchars - outer, L('T'), outer - 1);
  323. dest[nchars - 1] = L('U');
  324. for (inner = 0; inner < outer; ++inner)
  325. {
  326. if (STRNCMP (adr + middle, dest + nchars - outer, inner) != 0)
  327. {
  328. printf ("%s 1 flunked for outer = %zu, middle = %zu, "
  329. "inner = %zu\n",
  330. STRINGIFY (STRNCMP), outer, middle, inner);
  331. result = 1;
  332. }
  333. if (STRNCMP (dest + nchars - outer, adr + middle, inner) != 0)
  334. {
  335. printf ("%s 2 flunked for outer = %zu, middle = %zu, "
  336. "inner = %zu\n",
  337. STRINGIFY (STRNCMP), outer, middle, inner);
  338. result = 1;
  339. }
  340. }
  341. if (STRNCMP (adr + middle, dest + nchars - outer, outer) >= 0)
  342. {
  343. printf ("%s 1 flunked for outer = %zu, middle = %zu, full\n",
  344. STRINGIFY (STRNCMP), outer, middle);
  345. result = 1;
  346. }
  347. if (STRNCMP (dest + nchars - outer, adr + middle, outer) <= 0)
  348. {
  349. printf ("%s 2 flunked for outer = %zu, middle = %zu, full\n",
  350. STRINGIFY (STRNCMP), outer, middle);
  351. result = 1;
  352. }
  353. }
  354. /* strncpy/wcsncpy tests */
  355. adr[nchars - 1] = L('T');
  356. for (outer = nchars; outer >= max128; --outer)
  357. {
  358. size_t len;
  359. for (len = 0; len < nchars - outer; ++len)
  360. {
  361. if (STRNCPY (dest, &adr[outer], len) != dest
  362. || MEMCMP (dest, &adr[outer], len) != 0)
  363. {
  364. printf ("outer %s flunked for outer = %zu, len = %zu\n",
  365. STRINGIFY (STRNCPY), outer, len);
  366. result = 1;
  367. }
  368. }
  369. if (outer == 0)
  370. break;
  371. }
  372. adr[nchars - 1] = L('\0');
  373. for (outer = nchars - 1; outer >= max128; --outer)
  374. {
  375. for (inner = MAX (outer, nchars64); inner < nchars; ++inner)
  376. {
  377. size_t len;
  378. adr[inner] = L('\0');
  379. for (len = 0; len < nchars - outer + 64; ++len)
  380. {
  381. if (STRNCPY (dest, &adr[outer], len) != dest
  382. || MEMCMP (dest, &adr[outer],
  383. MIN (inner - outer, len)) != 0
  384. || (inner - outer < len
  385. && STRLEN (dest) != (inner - outer)))
  386. {
  387. printf ("%s flunked for outer = %zu, inner = %zu, "
  388. "len = %zu\n",
  389. STRINGIFY (STRNCPY), outer, inner, len);
  390. result = 1;
  391. }
  392. if (STRNCPY (dest + 1, &adr[outer], len) != dest + 1
  393. || MEMCMP (dest + 1, &adr[outer],
  394. MIN (inner - outer, len)) != 0
  395. || (inner - outer < len
  396. && STRLEN (dest + 1) != (inner - outer)))
  397. {
  398. printf ("%s+1 flunked for outer = %zu, inner = %zu, "
  399. "len = %zu\n",
  400. STRINGIFY (STRNCPY), outer, inner, len);
  401. result = 1;
  402. }
  403. }
  404. adr[inner] = L('T');
  405. }
  406. if (outer == 0)
  407. break;
  408. }
  409. /* stpcpy/wcpcpy test */
  410. for (outer = nchars - 1; outer >= max128; --outer)
  411. {
  412. for (inner = MAX (outer, nchars64); inner < nchars; ++inner)
  413. {
  414. adr[inner] = L('\0');
  415. if ((STPCPY (dest, &adr[outer]) - dest) != inner - outer)
  416. {
  417. printf ("%s flunked for outer = %zu, inner = %zu\n",
  418. STRINGIFY (STPCPY), outer, inner);
  419. result = 1;
  420. }
  421. adr[inner] = L('T');
  422. }
  423. if (outer == 0)
  424. break;
  425. }
  426. /* stpncpy/wcpncpy test */
  427. adr[nchars - 1] = L('T');
  428. for (outer = nchars; outer >= max128; --outer)
  429. {
  430. size_t len;
  431. for (len = 0; len < nchars - outer; ++len)
  432. {
  433. if (STPNCPY (dest, &adr[outer], len) != dest + len
  434. || MEMCMP (dest, &adr[outer], len) != 0)
  435. {
  436. printf ("outer %s flunked for outer = %zu, len = %zu\n",
  437. STRINGIFY (STPNCPY), outer, len);
  438. result = 1;
  439. }
  440. }
  441. if (outer == 0)
  442. break;
  443. }
  444. adr[nchars - 1] = L('\0');
  445. for (outer = nchars - 1; outer >= max128; --outer)
  446. {
  447. for (middle = MAX (outer, nchars64); middle < nchars; ++middle)
  448. {
  449. adr[middle] = L('\0');
  450. for (inner = 0; inner < nchars - outer; ++ inner)
  451. {
  452. if ((STPNCPY (dest, &adr[outer], inner) - dest)
  453. != MIN (inner, middle - outer))
  454. {
  455. printf ("%s flunked for outer = %zu, middle = %zu, "
  456. "inner = %zu\n",
  457. STRINGIFY (STPNCPY), outer, middle, inner);
  458. result = 1;
  459. }
  460. }
  461. adr[middle] = L('T');
  462. }
  463. if (outer == 0)
  464. break;
  465. }
  466. /* memcpy/wmemcpy test */
  467. for (outer = nchars; outer >= max128; --outer)
  468. {
  469. for (inner = 0; inner < nchars - outer; ++inner)
  470. if (MEMCPY (dest, &adr[outer], inner) != dest)
  471. {
  472. printf ("%s flunked for outer = %zu, inner = %zu\n",
  473. STRINGIFY (MEMCPY), outer, inner);
  474. result = 1;
  475. }
  476. if (outer == 0)
  477. break;
  478. }
  479. /* mempcpy/wmempcpy test */
  480. for (outer = nchars; outer >= max128; --outer)
  481. {
  482. for (inner = 0; inner < nchars - outer; ++inner)
  483. if (MEMPCPY (dest, &adr[outer], inner) != dest + inner)
  484. {
  485. printf ("%s flunked for outer = %zu, inner = %zu\n",
  486. STRINGIFY (MEMPCPY), outer, inner);
  487. result = 1;
  488. }
  489. if (outer == 0)
  490. break;
  491. }
  492. /* This function only exists for single-byte characters. */
  493. #ifndef WCSTEST
  494. /* memccpy test */
  495. memset (adr, '\0', nchars);
  496. for (outer = nchars; outer >= max128; --outer)
  497. {
  498. for (inner = 0; inner < nchars - outer; ++inner)
  499. if (memccpy (dest, &adr[outer], L('\1'), inner) != NULL)
  500. {
  501. printf ("memccpy flunked full copy for outer = %zu, inner = %zu\n",
  502. outer, inner);
  503. result = 1;
  504. }
  505. if (outer == 0)
  506. break;
  507. }
  508. for (outer = nchars - 1; outer >= max128; --outer)
  509. {
  510. for (middle = 0; middle < nchars - outer; ++middle)
  511. {
  512. memset (dest, L('\2'), middle + 1);
  513. for (inner = 0; inner < middle; ++inner)
  514. {
  515. adr[outer + inner] = L('\1');
  516. if (memccpy (dest, &adr[outer], '\1', middle + 128)
  517. != dest + inner + 1)
  518. {
  519. printf ("\
  520. memccpy flunked partial copy for outer = %zu, middle = %zu, inner = %zu\n",
  521. outer, middle, inner);
  522. result = 1;
  523. }
  524. else if (dest[inner + 1] != L('\2'))
  525. {
  526. printf ("\
  527. memccpy copied too much for outer = %zu, middle = %zu, inner = %zu\n",
  528. outer, middle, inner);
  529. result = 1;
  530. }
  531. adr[outer + inner] = L('\0');
  532. }
  533. }
  534. if (outer == 0)
  535. break;
  536. }
  537. #endif
  538. }
  539. return result;
  540. }
  541. #include <support/test-driver.c>