stratcliff.c 15 KB

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