test-memmem.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. /* Test and measure memmem functions.
  2. Copyright (C) 2008-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. #define TEST_NAME "memmem"
  17. #define BUF1PAGES 20
  18. #define ITERATIONS 500
  19. #include "test-string.h"
  20. typedef char *(*proto_t) (const void *, size_t, const void *, size_t);
  21. IMPL (memmem, 1)
  22. /* Naive implementation to verify results. */
  23. void *
  24. simple_memmem (const void *haystack, size_t haystack_len, const void *needle,
  25. size_t needle_len)
  26. {
  27. const char *begin;
  28. const char *const last_possible
  29. = (const char *) haystack + haystack_len - needle_len;
  30. if (needle_len == 0)
  31. /* The first occurrence of the empty string is deemed to occur at
  32. the beginning of the string. */
  33. return (void *) haystack;
  34. /* Sanity check, otherwise the loop might search through the whole
  35. memory. */
  36. if (__glibc_unlikely (haystack_len < needle_len))
  37. return NULL;
  38. for (begin = (const char *) haystack; begin <= last_possible; ++begin)
  39. if (begin[0] == ((const char *) needle)[0]
  40. && !memcmp ((const void *) &begin[1],
  41. (const void *) ((const char *) needle + 1),
  42. needle_len - 1))
  43. return (void *) begin;
  44. return NULL;
  45. }
  46. static int
  47. check_result (impl_t *impl, const void *haystack, size_t haystack_len,
  48. const void *needle, size_t needle_len, const void *expected)
  49. {
  50. void *res;
  51. res = CALL (impl, haystack, haystack_len, needle, needle_len);
  52. if (res != expected)
  53. {
  54. error (0, 0, "Wrong result in function %s %p %p", impl->name,
  55. res, expected);
  56. ret = 1;
  57. return -1;
  58. }
  59. return 0;
  60. }
  61. static void
  62. do_one_test (impl_t *impl, const void *haystack, size_t haystack_len,
  63. const void *needle, size_t needle_len, const void *expected)
  64. {
  65. if (check_result (impl, haystack, haystack_len, needle, needle_len,
  66. expected) < 0)
  67. return;
  68. }
  69. static void
  70. do_test (const char *str, size_t len, size_t idx)
  71. {
  72. char tmpbuf[len];
  73. memcpy (tmpbuf, buf1 + idx, len);
  74. memcpy (buf1 + idx, str, len);
  75. FOR_EACH_IMPL (impl, 0)
  76. do_one_test (impl, buf1, BUF1PAGES * page_size, str, len, buf1 + idx);
  77. memcpy (buf1 + idx, tmpbuf, len);
  78. }
  79. static void
  80. do_random_tests (void)
  81. {
  82. for (size_t n = 0; n < ITERATIONS; ++n)
  83. {
  84. char tmpbuf[32];
  85. size_t shift = random () % 11;
  86. size_t rel = random () % ((2 << (shift + 1)) * 64);
  87. size_t idx = MIN ((2 << shift) * 64 + rel, BUF1PAGES * page_size - 2);
  88. size_t len = random () % (sizeof (tmpbuf) - 1) + 1;
  89. len = MIN (len, BUF1PAGES * page_size - idx - 1);
  90. memcpy (tmpbuf, buf1 + idx, len);
  91. for (size_t i = random () % len / 2 + 1; i > 0; --i)
  92. {
  93. size_t off = random () % len;
  94. char ch = '0' + random () % 10;
  95. buf1[idx + off] = ch;
  96. }
  97. FOR_EACH_IMPL (impl, 0)
  98. do_one_test (impl, buf1, BUF1PAGES * page_size, buf1 + idx, len,
  99. buf1 + idx);
  100. memcpy (buf1 + idx, tmpbuf, len);
  101. }
  102. }
  103. static void
  104. check1 (void)
  105. {
  106. const char search_buf_data[5] = { 0x56, 0x34, 0x12, 0x78, 0x78 };
  107. const char pattern[2] = { 0x78, 0x56 };
  108. void *search_buf = (void *) buf1 + page_size - sizeof search_buf_data;
  109. void *exp_result;
  110. memcpy (search_buf, search_buf_data, sizeof search_buf_data);
  111. exp_result = simple_memmem (search_buf, sizeof search_buf_data,
  112. pattern, sizeof pattern);
  113. FOR_EACH_IMPL (impl, 0)
  114. check_result (impl, search_buf, sizeof search_buf_data,
  115. pattern, sizeof pattern, exp_result);
  116. }
  117. static const char *const strs[] =
  118. {
  119. "00000", "00112233", "0123456789", "0000111100001111",
  120. "00000111110000022222", "012345678901234567890",
  121. "abc0", "aaaa0", "abcabc0"
  122. };
  123. int
  124. test_main (void)
  125. {
  126. size_t i;
  127. test_init ();
  128. check1 ();
  129. printf ("%23s", "");
  130. FOR_EACH_IMPL (impl, 0)
  131. printf ("\t%s", impl->name);
  132. putchar ('\n');
  133. for (i = 0; i < BUF1PAGES * page_size; ++i)
  134. buf1[i] = 60 + random () % 32;
  135. for (i = 0; i < sizeof (strs) / sizeof (strs[0]); ++i)
  136. for (size_t j = 0; j < 120; j += 7)
  137. {
  138. size_t len = strlen (strs[i]);
  139. do_test (strs[i], len, j);
  140. }
  141. do_random_tests ();
  142. return ret;
  143. }
  144. #include <support/test-driver.c>