tst-cmp.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. /* Alignment/padding coverage test for string comparison.
  2. Copyright (C) 2016-2019 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. <http://www.gnu.org/licenses/>. */
  15. /* This performs test comparisons with various (mis)alignments and
  16. characters in the padding. It is partly a regression test for bug
  17. 20327. */
  18. #include <limits.h>
  19. #include <malloc.h>
  20. #include <stdbool.h>
  21. #include <stdint.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include <libc-diag.h>
  25. static int
  26. signum (int val)
  27. {
  28. if (val < 0)
  29. return -1;
  30. if (val > 0)
  31. return 1;
  32. else
  33. return 0;
  34. }
  35. static size_t
  36. max_size_t (size_t left, size_t right)
  37. {
  38. if (left > right)
  39. return left;
  40. else
  41. return right;
  42. }
  43. /* Wrappers for strncmp and strncasecmp which determine the maximum
  44. string length in some, either based on the input string length, or
  45. using fixed constants. */
  46. static int
  47. strncmp_no_terminator (const char *left, const char *right)
  48. {
  49. size_t left_len = strlen (left);
  50. size_t right_len = strlen (right);
  51. return strncmp (left, right, max_size_t (left_len, right_len));
  52. }
  53. static int
  54. strncasecmp_no_terminator (const char *left, const char *right)
  55. {
  56. size_t left_len = strlen (left);
  57. size_t right_len = strlen (right);
  58. return strncasecmp (left, right, max_size_t (left_len, right_len));
  59. }
  60. static int
  61. strncmp_terminator (const char *left, const char *right)
  62. {
  63. size_t left_len = strlen (left);
  64. size_t right_len = strlen (right);
  65. return strncmp (left, right, max_size_t (left_len, right_len));
  66. }
  67. static int
  68. strncasecmp_terminator (const char *left, const char *right)
  69. {
  70. size_t left_len = strlen (left);
  71. size_t right_len = strlen (right);
  72. return strncasecmp (left, right, max_size_t (left_len, right_len));
  73. }
  74. static int
  75. strncmp_64 (const char *left, const char *right)
  76. {
  77. return strncmp (left, right, 64);
  78. }
  79. static int
  80. strncasecmp_64 (const char *left, const char *right)
  81. {
  82. return strncasecmp (left, right, 64);
  83. }
  84. static int
  85. strncmp_max (const char *left, const char *right)
  86. {
  87. DIAG_PUSH_NEEDS_COMMENT;
  88. #if __GNUC_PREREQ (7, 0)
  89. /* GCC 9 warns about the size passed to strncmp being larger than
  90. PTRDIFF_MAX; the use of SIZE_MAX is deliberate here. */
  91. DIAG_IGNORE_NEEDS_COMMENT (9, "-Wstringop-overflow=");
  92. #endif
  93. return strncmp (left, right, SIZE_MAX);
  94. DIAG_POP_NEEDS_COMMENT;
  95. }
  96. static int
  97. strncasecmp_max (const char *left, const char *right)
  98. {
  99. DIAG_PUSH_NEEDS_COMMENT;
  100. #if __GNUC_PREREQ (7, 0)
  101. /* GCC 9 warns about the size passed to strncasecmp being larger
  102. than PTRDIFF_MAX; the use of SIZE_MAX is deliberate here. */
  103. DIAG_IGNORE_NEEDS_COMMENT (9, "-Wstringop-overflow=");
  104. #endif
  105. return strncasecmp (left, right, SIZE_MAX);
  106. DIAG_POP_NEEDS_COMMENT;
  107. }
  108. int
  109. do_test (void)
  110. {
  111. enum {
  112. max_align = 64,
  113. max_string_length = 33
  114. };
  115. size_t blob_size = max_align + max_string_length + 1;
  116. char *left = memalign (max_align, blob_size);
  117. char *right = memalign (max_align, blob_size);
  118. if (left == NULL || right == NULL)
  119. {
  120. printf ("error: out of memory\n");
  121. return 1;
  122. }
  123. const struct
  124. {
  125. const char *name;
  126. int (*implementation) (const char *, const char *);
  127. } functions[] =
  128. {
  129. { "strcmp", strcmp },
  130. { "strcasecmp", strcasecmp },
  131. { "strncmp (without NUL)", strncmp_no_terminator},
  132. { "strncasecmp (without NUL)", strncasecmp_no_terminator},
  133. { "strncmp (with NUL)", strncmp_terminator},
  134. { "strncasecmp (with NUL)", strncasecmp_terminator},
  135. { "strncmp (length 64)", strncmp_64},
  136. { "strncasecmp (length 64)", strncasecmp_64},
  137. { "strncmp (length SIZE_MAX)", strncmp_max},
  138. { "strncasecmp (length SIZE_MAX)", strncasecmp_max},
  139. { NULL, NULL }
  140. };
  141. const char *const strings[] =
  142. {
  143. "",
  144. "0",
  145. "01",
  146. "01234567",
  147. "0123456789abcde",
  148. "0123456789abcdef",
  149. "0123456789abcdefg",
  150. "1",
  151. "10",
  152. "123456789abcdef",
  153. "123456789abcdefg",
  154. "23456789abcdef",
  155. "23456789abcdefg",
  156. "abcdefghijklmnopqrstuvwxyzABCDEF",
  157. NULL
  158. };
  159. const unsigned char pads[] =
  160. { 0, 1, 32, 64, 128, '0', '1', 'e', 'f', 'g', 127, 192, 255 };
  161. bool errors = false;
  162. for (int left_idx = 0; strings[left_idx] != NULL; ++left_idx)
  163. for (int left_align = 0; left_align < max_align; ++left_align)
  164. for (unsigned pad_left = 0; pad_left < sizeof (pads); ++pad_left)
  165. {
  166. memset (left, pads[pad_left], blob_size);
  167. strcpy (left + left_align, strings[left_idx]);
  168. for (int right_idx = 0; strings[right_idx] != NULL; ++right_idx)
  169. for (unsigned pad_right = 0; pad_right < sizeof (pads);
  170. ++pad_right)
  171. for (int right_align = 0; right_align < max_align;
  172. ++right_align)
  173. {
  174. memset (right, pads[pad_right], blob_size);
  175. strcpy (right + right_align, strings[right_idx]);
  176. for (int func = 0; functions[func].name != NULL; ++func)
  177. {
  178. int expected = left_idx - right_idx;
  179. int actual = functions[func].implementation
  180. (left + left_align, right + right_align);
  181. if (signum (actual) != signum (expected))
  182. {
  183. printf ("error: mismatch for %s: %d\n"
  184. " left: \"%s\"\n"
  185. " right: \"%s\"\n"
  186. " pad_left = %u, pad_right = %u,\n"
  187. " left_align = %d, right_align = %d\n",
  188. functions[func].name, actual,
  189. strings[left_idx], strings[right_idx],
  190. pad_left, pad_right,
  191. left_align, right_align);
  192. errors = true;
  193. }
  194. }
  195. }
  196. }
  197. free (right);
  198. free (left);
  199. return errors;
  200. }
  201. /* The nested loops need a long time to complete on slower
  202. machines. */
  203. #define TIMEOUT 600
  204. #include <support/test-driver.c>