test-Xncmp-nonarray.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. /* Test non-array inputs to string comparison functions.
  2. Copyright (C) 2024-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. /* This skeleton file is included from string/test-strncmp-nonarray.c and
  16. wcsmbs/test-wcsncmp-nonarray.c to test that reading of the arrays stops
  17. at the first null character.
  18. TEST_IDENTIFIER must be the test function identifier. TEST_NAME is
  19. the same as a string.
  20. CHAR must be defined as the character type. */
  21. #include <array_length.h>
  22. #include <string.h>
  23. #include <support/check.h>
  24. #include <support/next_to_fault.h>
  25. #include <support/test-driver.h>
  26. #include <sys/param.h>
  27. #include <unistd.h>
  28. /* Much shorter than test-Xnlen-nonarray.c because of deeply nested loops. */
  29. enum { buffer_length = 80 };
  30. /* The test buffer layout follows what is described test-Xnlen-nonarray.c,
  31. except that there two buffers, left and right. The variables
  32. a_count, zero_count, start_offset are all duplicated. */
  33. /* Return the maximum string length for a string that starts at
  34. start_offset. */
  35. static int
  36. string_length (int a_count, int start_offset)
  37. {
  38. if (start_offset == buffer_length || start_offset >= a_count)
  39. return 0;
  40. else
  41. return a_count - start_offset;
  42. }
  43. /* This is the valid maximum length argument computation for
  44. strnlen/wcsnlen. See text-Xnlen-nonarray.c. */
  45. static int
  46. maximum_length (int start_offset, int zero_count)
  47. {
  48. if (start_offset == buffer_length)
  49. return 0;
  50. else if (zero_count > 0)
  51. /* Effectively unbounded, but we need to stop fairly low,
  52. otherwise testing takes too long. */
  53. return buffer_length + 32;
  54. else
  55. return buffer_length - start_offset;
  56. }
  57. typedef __typeof (TEST_IDENTIFIER) *proto_t;
  58. #define TEST_MAIN
  59. #include "test-string.h"
  60. IMPL (TEST_IDENTIFIER, 1)
  61. static int
  62. test_main (void)
  63. {
  64. TEST_VERIFY_EXIT (sysconf (_SC_PAGESIZE) >= buffer_length);
  65. test_init ();
  66. struct support_next_to_fault left_ntf
  67. = support_next_to_fault_allocate (buffer_length * sizeof (CHAR));
  68. CHAR *left_buffer = (CHAR *) left_ntf.buffer;
  69. struct support_next_to_fault right_ntf
  70. = support_next_to_fault_allocate (buffer_length * sizeof (CHAR));
  71. CHAR *right_buffer = (CHAR *) right_ntf.buffer;
  72. FOR_EACH_IMPL (impl, 0)
  73. {
  74. printf ("info: testing %s\n", impl->name);
  75. for (size_t i = 0; i < buffer_length; ++i)
  76. left_buffer[i] = 'A';
  77. for (int left_zero_count = 0; left_zero_count <= buffer_length;
  78. ++left_zero_count)
  79. {
  80. if (left_zero_count > 0)
  81. left_buffer[buffer_length - left_zero_count] = 0;
  82. int left_a_count = buffer_length - left_zero_count;
  83. for (size_t i = 0; i < buffer_length; ++i)
  84. right_buffer[i] = 'A';
  85. for (int right_zero_count = 0; right_zero_count <= buffer_length;
  86. ++right_zero_count)
  87. {
  88. if (right_zero_count > 0)
  89. right_buffer[buffer_length - right_zero_count] = 0;
  90. int right_a_count = buffer_length - right_zero_count;
  91. for (int left_start_offset = 0;
  92. left_start_offset <= buffer_length;
  93. ++left_start_offset)
  94. {
  95. CHAR *left_start_pointer = left_buffer + left_start_offset;
  96. int left_maxlen
  97. = maximum_length (left_start_offset, left_zero_count);
  98. int left_length
  99. = string_length (left_a_count, left_start_offset);
  100. for (int right_start_offset = 0;
  101. right_start_offset <= buffer_length;
  102. ++right_start_offset)
  103. {
  104. CHAR *right_start_pointer
  105. = right_buffer + right_start_offset;
  106. int right_maxlen
  107. = maximum_length (right_start_offset, right_zero_count);
  108. int right_length
  109. = string_length (right_a_count, right_start_offset);
  110. /* Maximum length is modelled after strnlen/wcsnlen,
  111. and must be valid for both pointer arguments at
  112. the same time. */
  113. int maxlen = MIN (left_maxlen, right_maxlen);
  114. for (int length_argument = 0; length_argument <= maxlen;
  115. ++length_argument)
  116. {
  117. if (test_verbose)
  118. {
  119. printf ("left: zero_count=%d"
  120. " a_count=%d start_offset=%d\n",
  121. left_zero_count, left_a_count,
  122. left_start_offset);
  123. printf ("right: zero_count=%d"
  124. " a_count=%d start_offset=%d\n",
  125. right_zero_count, right_a_count,
  126. right_start_offset);
  127. printf ("length argument: %d\n",
  128. length_argument);
  129. }
  130. /* Effective lengths bounded by length argument.
  131. The effective length determines the
  132. outcome of the comparison. */
  133. int left_effective
  134. = MIN (left_length, length_argument);
  135. int right_effective
  136. = MIN (right_length, length_argument);
  137. if (left_effective == right_effective)
  138. TEST_COMPARE (CALL (impl,
  139. left_start_pointer,
  140. right_start_pointer,
  141. length_argument), 0);
  142. else if (left_effective < right_effective)
  143. TEST_COMPARE (CALL (impl,
  144. left_start_pointer,
  145. right_start_pointer,
  146. length_argument) < 0, 1);
  147. else
  148. TEST_COMPARE (CALL (impl,
  149. left_start_pointer,
  150. right_start_pointer,
  151. length_argument) > 0, 1);
  152. }
  153. }
  154. }
  155. }
  156. }
  157. }
  158. return 0;
  159. }
  160. #include <support/test-driver.c>