1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Test cases for string functions.
4 */
5
6 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
7
8 #include <kunit/test.h>
9 #include <linux/ktime.h>
10 #include <linux/math64.h>
11 #include <linux/minmax.h>
12 #include <linux/mm.h>
13 #include <linux/module.h>
14 #include <linux/prandom.h>
15 #include <linux/printk.h>
16 #include <linux/slab.h>
17 #include <linux/string.h>
18 #include <linux/time64.h>
19 #include <linux/units.h>
20 #include <linux/vmalloc.h>
21
22 #define STRCMP_LARGE_BUF_LEN 2048
23 #define STRCMP_CHANGE_POINT 1337
24 #define STRCMP_TEST_EXPECT_EQUAL(test, fn, ...) KUNIT_EXPECT_EQ(test, fn(__VA_ARGS__), 0)
25 #define STRCMP_TEST_EXPECT_LOWER(test, fn, ...) KUNIT_EXPECT_LT(test, fn(__VA_ARGS__), 0)
26 #define STRCMP_TEST_EXPECT_GREATER(test, fn, ...) KUNIT_EXPECT_GT(test, fn(__VA_ARGS__), 0)
27
28 #define STRING_TEST_MAX_LEN 128
29 #define STRING_TEST_MAX_OFFSET 16
30
31 #define STRING_BENCH_SEED 888
32 #define STRING_BENCH_WORKLOAD (1 * MEGA)
33
string_test_memset16(struct kunit * test)34 static void string_test_memset16(struct kunit *test)
35 {
36 unsigned i, j, k;
37 u16 v, *p;
38
39 p = kunit_kzalloc(test, 256 * 2 * 2, GFP_KERNEL);
40 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, p);
41
42 for (i = 0; i < 256; i++) {
43 for (j = 0; j < 256; j++) {
44 memset(p, 0xa1, 256 * 2 * sizeof(v));
45 memset16(p + i, 0xb1b2, j);
46 for (k = 0; k < 512; k++) {
47 v = p[k];
48 if (k < i) {
49 KUNIT_ASSERT_EQ_MSG(test, v, 0xa1a1,
50 "i:%d j:%d k:%d", i, j, k);
51 } else if (k < i + j) {
52 KUNIT_ASSERT_EQ_MSG(test, v, 0xb1b2,
53 "i:%d j:%d k:%d", i, j, k);
54 } else {
55 KUNIT_ASSERT_EQ_MSG(test, v, 0xa1a1,
56 "i:%d j:%d k:%d", i, j, k);
57 }
58 }
59 }
60 }
61 }
62
string_test_memset32(struct kunit * test)63 static void string_test_memset32(struct kunit *test)
64 {
65 unsigned i, j, k;
66 u32 v, *p;
67
68 p = kunit_kzalloc(test, 256 * 2 * 4, GFP_KERNEL);
69 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, p);
70
71 for (i = 0; i < 256; i++) {
72 for (j = 0; j < 256; j++) {
73 memset(p, 0xa1, 256 * 2 * sizeof(v));
74 memset32(p + i, 0xb1b2b3b4, j);
75 for (k = 0; k < 512; k++) {
76 v = p[k];
77 if (k < i) {
78 KUNIT_ASSERT_EQ_MSG(test, v, 0xa1a1a1a1,
79 "i:%d j:%d k:%d", i, j, k);
80 } else if (k < i + j) {
81 KUNIT_ASSERT_EQ_MSG(test, v, 0xb1b2b3b4,
82 "i:%d j:%d k:%d", i, j, k);
83 } else {
84 KUNIT_ASSERT_EQ_MSG(test, v, 0xa1a1a1a1,
85 "i:%d j:%d k:%d", i, j, k);
86 }
87 }
88 }
89 }
90 }
91
string_test_memset64(struct kunit * test)92 static void string_test_memset64(struct kunit *test)
93 {
94 unsigned i, j, k;
95 u64 v, *p;
96
97 p = kunit_kzalloc(test, 256 * 2 * 8, GFP_KERNEL);
98 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, p);
99
100 for (i = 0; i < 256; i++) {
101 for (j = 0; j < 256; j++) {
102 memset(p, 0xa1, 256 * 2 * sizeof(v));
103 memset64(p + i, 0xb1b2b3b4b5b6b7b8ULL, j);
104 for (k = 0; k < 512; k++) {
105 v = p[k];
106 if (k < i) {
107 KUNIT_ASSERT_EQ_MSG(test, v, 0xa1a1a1a1a1a1a1a1ULL,
108 "i:%d j:%d k:%d", i, j, k);
109 } else if (k < i + j) {
110 KUNIT_ASSERT_EQ_MSG(test, v, 0xb1b2b3b4b5b6b7b8ULL,
111 "i:%d j:%d k:%d", i, j, k);
112 } else {
113 KUNIT_ASSERT_EQ_MSG(test, v, 0xa1a1a1a1a1a1a1a1ULL,
114 "i:%d j:%d k:%d", i, j, k);
115 }
116 }
117 }
118 }
119 }
120
string_test_strlen(struct kunit * test)121 static void string_test_strlen(struct kunit *test)
122 {
123 size_t buf_size;
124 char *buf, *s;
125
126 buf_size = PAGE_ALIGN(STRING_TEST_MAX_LEN + STRING_TEST_MAX_OFFSET + 1);
127 buf = vmalloc(buf_size);
128 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
129
130 memset(buf, 'A', buf_size);
131
132 for (size_t offset = 0; offset < STRING_TEST_MAX_OFFSET; offset++) {
133 for (size_t len = 0; len <= STRING_TEST_MAX_LEN; len++) {
134 s = buf + buf_size - 1 - offset - len;
135 s[len] = '\0';
136 KUNIT_EXPECT_EQ_MSG(test, strlen(s), len,
137 "offset:%zu len:%zu", offset, len);
138 s[len] = 'A';
139 }
140 }
141
142 vfree(buf);
143 }
144
string_test_strnlen(struct kunit * test)145 static void string_test_strnlen(struct kunit *test)
146 {
147 size_t buf_size;
148 char *buf, *s;
149
150 buf_size = PAGE_ALIGN(STRING_TEST_MAX_LEN + STRING_TEST_MAX_OFFSET + 1);
151 buf = vmalloc(buf_size);
152 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
153
154 memset(buf, 'A', buf_size);
155
156 for (size_t offset = 0; offset < STRING_TEST_MAX_OFFSET; offset++) {
157 for (size_t len = 0; len <= STRING_TEST_MAX_LEN; len++) {
158 s = buf + buf_size - 1 - offset - len;
159 s[len] = '\0';
160
161 if (len > 0)
162 KUNIT_EXPECT_EQ(test, strnlen(s, len - 1), len - 1);
163 if (len > 1)
164 KUNIT_EXPECT_EQ(test, strnlen(s, len - 2), len - 2);
165
166 KUNIT_EXPECT_EQ(test, strnlen(s, len), len);
167
168 KUNIT_EXPECT_EQ(test, strnlen(s, len + 1), len);
169 KUNIT_EXPECT_EQ(test, strnlen(s, len + 2), len);
170 KUNIT_EXPECT_EQ(test, strnlen(s, len + 10), len);
171
172 s[len] = 'A';
173 }
174 }
175
176 vfree(buf);
177 }
178
string_test_strchr(struct kunit * test)179 static void string_test_strchr(struct kunit *test)
180 {
181 const char *test_string = "abcdefghijkl";
182 const char *empty_string = "";
183 char *result;
184 int i;
185
186 for (i = 0; i < strlen(test_string) + 1; i++) {
187 result = strchr(test_string, test_string[i]);
188 KUNIT_ASSERT_EQ_MSG(test, result - test_string, i,
189 "char:%c", 'a' + i);
190 }
191
192 result = strchr(empty_string, '\0');
193 KUNIT_ASSERT_PTR_EQ(test, result, empty_string);
194
195 result = strchr(empty_string, 'a');
196 KUNIT_ASSERT_NULL(test, result);
197
198 result = strchr(test_string, 'z');
199 KUNIT_ASSERT_NULL(test, result);
200 }
201
string_test_strrchr(struct kunit * test)202 static void string_test_strrchr(struct kunit *test)
203 {
204 size_t buf_size;
205 char *buf, *s;
206
207 buf_size = PAGE_ALIGN(STRING_TEST_MAX_LEN + STRING_TEST_MAX_OFFSET + 1);
208 buf = vmalloc(buf_size);
209 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
210
211 memset(buf, 'A', buf_size);
212
213 for (size_t offset = 0; offset < STRING_TEST_MAX_OFFSET; offset++) {
214 for (size_t len = 0; len <= STRING_TEST_MAX_LEN; len++) {
215 s = buf + buf_size - 1 - offset - len;
216 s[len] = '\0';
217
218 KUNIT_EXPECT_PTR_EQ(test, strrchr(s, 'Z'), NULL);
219
220 if (len > 0)
221 KUNIT_EXPECT_PTR_EQ(test, strrchr(s, 'A'), s + len - 1);
222 else
223 KUNIT_EXPECT_PTR_EQ(test, strrchr(s, 'A'), NULL);
224
225 s[len] = 'A';
226 }
227 }
228
229 vfree(buf);
230 }
231
string_test_strnchr(struct kunit * test)232 static void string_test_strnchr(struct kunit *test)
233 {
234 const char *test_string = "abcdefghijkl";
235 const char *empty_string = "";
236 char *result;
237 int i, j;
238
239 for (i = 0; i < strlen(test_string) + 1; i++) {
240 for (j = 0; j < strlen(test_string) + 2; j++) {
241 result = strnchr(test_string, j, test_string[i]);
242 if (j <= i) {
243 KUNIT_ASSERT_NULL_MSG(test, result,
244 "char:%c i:%d j:%d", 'a' + i, i, j);
245 } else {
246 KUNIT_ASSERT_EQ_MSG(test, result - test_string, i,
247 "char:%c i:%d j:%d", 'a' + i, i, j);
248 }
249 }
250 }
251
252 result = strnchr(empty_string, 0, '\0');
253 KUNIT_ASSERT_NULL(test, result);
254
255 result = strnchr(empty_string, 1, '\0');
256 KUNIT_ASSERT_PTR_EQ(test, result, empty_string);
257
258 result = strnchr(empty_string, 1, 'a');
259 KUNIT_ASSERT_NULL(test, result);
260
261 result = strnchr(NULL, 0, '\0');
262 KUNIT_ASSERT_NULL(test, result);
263 }
264
string_test_strspn(struct kunit * test)265 static void string_test_strspn(struct kunit *test)
266 {
267 static const struct strspn_test {
268 const char str[16];
269 const char accept[16];
270 const char reject[16];
271 unsigned a;
272 unsigned r;
273 } tests[] = {
274 { "foobar", "", "", 0, 6 },
275 { "abba", "abc", "ABBA", 4, 4 },
276 { "abba", "a", "b", 1, 1 },
277 { "", "abc", "abc", 0, 0},
278 };
279 const struct strspn_test *s = tests;
280 size_t i;
281
282 for (i = 0; i < ARRAY_SIZE(tests); ++i, ++s) {
283 KUNIT_ASSERT_EQ_MSG(test, s->a, strspn(s->str, s->accept),
284 "i:%zu", i);
285 KUNIT_ASSERT_EQ_MSG(test, s->r, strcspn(s->str, s->reject),
286 "i:%zu", i);
287 }
288 }
289
290 static char strcmp_buffer1[STRCMP_LARGE_BUF_LEN];
291 static char strcmp_buffer2[STRCMP_LARGE_BUF_LEN];
292
strcmp_fill_buffers(char fill1,char fill2)293 static void strcmp_fill_buffers(char fill1, char fill2)
294 {
295 memset(strcmp_buffer1, fill1, STRCMP_LARGE_BUF_LEN);
296 memset(strcmp_buffer2, fill2, STRCMP_LARGE_BUF_LEN);
297 strcmp_buffer1[STRCMP_LARGE_BUF_LEN - 1] = 0;
298 strcmp_buffer2[STRCMP_LARGE_BUF_LEN - 1] = 0;
299 }
300
string_test_strcmp(struct kunit * test)301 static void string_test_strcmp(struct kunit *test)
302 {
303 /* Equal strings */
304 STRCMP_TEST_EXPECT_EQUAL(test, strcmp, "Hello, Kernel!", "Hello, Kernel!");
305 /* First string is lexicographically less than the second */
306 STRCMP_TEST_EXPECT_LOWER(test, strcmp, "Hello, KUnit!", "Hello, Kernel!");
307 /* First string is lexicographically larger than the second */
308 STRCMP_TEST_EXPECT_GREATER(test, strcmp, "Hello, Kernel!", "Hello, KUnit!");
309 /* Empty string is always lexicographically less than any non-empty string */
310 STRCMP_TEST_EXPECT_LOWER(test, strcmp, "", "Non-empty string");
311 /* Two empty strings should be equal */
312 STRCMP_TEST_EXPECT_EQUAL(test, strcmp, "", "");
313 /* Compare two strings which have only one char difference */
314 STRCMP_TEST_EXPECT_LOWER(test, strcmp, "Abacaba", "Abadaba");
315 /* Compare two strings which have the same prefix*/
316 STRCMP_TEST_EXPECT_LOWER(test, strcmp, "Just a string", "Just a string and something else");
317 }
318
string_test_strcmp_long_strings(struct kunit * test)319 static void string_test_strcmp_long_strings(struct kunit *test)
320 {
321 strcmp_fill_buffers('B', 'B');
322 STRCMP_TEST_EXPECT_EQUAL(test, strcmp, strcmp_buffer1, strcmp_buffer2);
323
324 strcmp_buffer1[STRCMP_CHANGE_POINT] = 'A';
325 STRCMP_TEST_EXPECT_LOWER(test, strcmp, strcmp_buffer1, strcmp_buffer2);
326
327 strcmp_buffer1[STRCMP_CHANGE_POINT] = 'C';
328 STRCMP_TEST_EXPECT_GREATER(test, strcmp, strcmp_buffer1, strcmp_buffer2);
329 }
330
string_test_strncmp(struct kunit * test)331 static void string_test_strncmp(struct kunit *test)
332 {
333 /* Equal strings */
334 STRCMP_TEST_EXPECT_EQUAL(test, strncmp, "Hello, KUnit!", "Hello, KUnit!", 13);
335 /* First string is lexicographically less than the second */
336 STRCMP_TEST_EXPECT_LOWER(test, strncmp, "Hello, KUnit!", "Hello, Kernel!", 13);
337 /* Result is always 'equal' when count = 0 */
338 STRCMP_TEST_EXPECT_EQUAL(test, strncmp, "Hello, Kernel!", "Hello, KUnit!", 0);
339 /* Strings with common prefix are equal if count = length of prefix */
340 STRCMP_TEST_EXPECT_EQUAL(test, strncmp, "Abacaba", "Abadaba", 3);
341 /* Strings with common prefix are not equal when count = length of prefix + 1 */
342 STRCMP_TEST_EXPECT_LOWER(test, strncmp, "Abacaba", "Abadaba", 4);
343 /* If one string is a prefix of another, the shorter string is lexicographically smaller */
344 STRCMP_TEST_EXPECT_LOWER(test, strncmp, "Just a string", "Just a string and something else",
345 strlen("Just a string and something else"));
346 /*
347 * If one string is a prefix of another, and we check first length
348 * of prefix chars, the result is 'equal'
349 */
350 STRCMP_TEST_EXPECT_EQUAL(test, strncmp, "Just a string", "Just a string and something else",
351 strlen("Just a string"));
352 }
353
string_test_strncmp_long_strings(struct kunit * test)354 static void string_test_strncmp_long_strings(struct kunit *test)
355 {
356 strcmp_fill_buffers('B', 'B');
357 STRCMP_TEST_EXPECT_EQUAL(test, strncmp, strcmp_buffer1,
358 strcmp_buffer2, STRCMP_LARGE_BUF_LEN);
359
360 strcmp_buffer1[STRCMP_CHANGE_POINT] = 'A';
361 STRCMP_TEST_EXPECT_LOWER(test, strncmp, strcmp_buffer1,
362 strcmp_buffer2, STRCMP_LARGE_BUF_LEN);
363
364 strcmp_buffer1[STRCMP_CHANGE_POINT] = 'C';
365 STRCMP_TEST_EXPECT_GREATER(test, strncmp, strcmp_buffer1,
366 strcmp_buffer2, STRCMP_LARGE_BUF_LEN);
367 /* the strings are equal up to STRCMP_CHANGE_POINT */
368 STRCMP_TEST_EXPECT_EQUAL(test, strncmp, strcmp_buffer1,
369 strcmp_buffer2, STRCMP_CHANGE_POINT);
370 STRCMP_TEST_EXPECT_GREATER(test, strncmp, strcmp_buffer1,
371 strcmp_buffer2, STRCMP_CHANGE_POINT + 1);
372 }
373
string_test_strcasecmp(struct kunit * test)374 static void string_test_strcasecmp(struct kunit *test)
375 {
376 /* Same strings in different case should be equal */
377 STRCMP_TEST_EXPECT_EQUAL(test, strcasecmp, "Hello, Kernel!", "HeLLO, KErNeL!");
378 /* Empty strings should be equal */
379 STRCMP_TEST_EXPECT_EQUAL(test, strcasecmp, "", "");
380 /* Despite ascii code for 'a' is larger than ascii code for 'B', 'a' < 'B' */
381 STRCMP_TEST_EXPECT_LOWER(test, strcasecmp, "a", "B");
382 STRCMP_TEST_EXPECT_GREATER(test, strcasecmp, "B", "a");
383 /* Special symbols and numbers should be processed correctly */
384 STRCMP_TEST_EXPECT_EQUAL(test, strcasecmp, "-+**.1230ghTTT~^", "-+**.1230Ghttt~^");
385 }
386
string_test_strcasecmp_long_strings(struct kunit * test)387 static void string_test_strcasecmp_long_strings(struct kunit *test)
388 {
389 strcmp_fill_buffers('b', 'B');
390 STRCMP_TEST_EXPECT_EQUAL(test, strcasecmp, strcmp_buffer1, strcmp_buffer2);
391
392 strcmp_buffer1[STRCMP_CHANGE_POINT] = 'a';
393 STRCMP_TEST_EXPECT_LOWER(test, strcasecmp, strcmp_buffer1, strcmp_buffer2);
394
395 strcmp_buffer1[STRCMP_CHANGE_POINT] = 'C';
396 STRCMP_TEST_EXPECT_GREATER(test, strcasecmp, strcmp_buffer1, strcmp_buffer2);
397 }
398
string_test_strncasecmp(struct kunit * test)399 static void string_test_strncasecmp(struct kunit *test)
400 {
401 /* Same strings in different case should be equal */
402 STRCMP_TEST_EXPECT_EQUAL(test, strncasecmp, "AbAcAbA", "Abacaba", strlen("Abacaba"));
403 /* strncasecmp should check 'count' chars only */
404 STRCMP_TEST_EXPECT_EQUAL(test, strncasecmp, "AbaCaBa", "abaCaDa", 5);
405 STRCMP_TEST_EXPECT_LOWER(test, strncasecmp, "a", "B", 1);
406 STRCMP_TEST_EXPECT_GREATER(test, strncasecmp, "B", "a", 1);
407 /* Result is always 'equal' when count = 0 */
408 STRCMP_TEST_EXPECT_EQUAL(test, strncasecmp, "Abacaba", "Not abacaba", 0);
409 }
410
string_test_strncasecmp_long_strings(struct kunit * test)411 static void string_test_strncasecmp_long_strings(struct kunit *test)
412 {
413 strcmp_fill_buffers('b', 'B');
414 STRCMP_TEST_EXPECT_EQUAL(test, strncasecmp, strcmp_buffer1,
415 strcmp_buffer2, STRCMP_LARGE_BUF_LEN);
416
417 strcmp_buffer1[STRCMP_CHANGE_POINT] = 'a';
418 STRCMP_TEST_EXPECT_LOWER(test, strncasecmp, strcmp_buffer1,
419 strcmp_buffer2, STRCMP_LARGE_BUF_LEN);
420
421 strcmp_buffer1[STRCMP_CHANGE_POINT] = 'C';
422 STRCMP_TEST_EXPECT_GREATER(test, strncasecmp, strcmp_buffer1,
423 strcmp_buffer2, STRCMP_LARGE_BUF_LEN);
424
425 STRCMP_TEST_EXPECT_EQUAL(test, strncasecmp, strcmp_buffer1,
426 strcmp_buffer2, STRCMP_CHANGE_POINT);
427 STRCMP_TEST_EXPECT_GREATER(test, strncasecmp, strcmp_buffer1,
428 strcmp_buffer2, STRCMP_CHANGE_POINT + 1);
429 }
430
431 /**
432 * strscpy_check() - Run a specific test case.
433 * @test: KUnit test context pointer
434 * @src: Source string, argument to strscpy_pad()
435 * @count: Size of destination buffer, argument to strscpy_pad()
436 * @expected: Expected return value from call to strscpy_pad()
437 * @chars: Number of characters from the src string expected to be
438 * written to the dst buffer.
439 * @terminator: 1 if there should be a terminating null byte 0 otherwise.
440 * @pad: Number of pad characters expected (in the tail of dst buffer).
441 * (@pad does not include the null terminator byte.)
442 *
443 * Calls strscpy_pad() and verifies the return value and state of the
444 * destination buffer after the call returns.
445 */
strscpy_check(struct kunit * test,char * src,int count,int expected,int chars,int terminator,int pad)446 static void strscpy_check(struct kunit *test, char *src, int count,
447 int expected, int chars, int terminator, int pad)
448 {
449 int nr_bytes_poison;
450 int max_expected;
451 int max_count;
452 int written;
453 char buf[6];
454 int index, i;
455 const char POISON = 'z';
456
457 KUNIT_ASSERT_TRUE_MSG(test, src != NULL,
458 "null source string not supported");
459
460 memset(buf, POISON, sizeof(buf));
461 /* Future proofing test suite, validate args */
462 max_count = sizeof(buf) - 2; /* Space for null and to verify overflow */
463 max_expected = count - 1; /* Space for the null */
464
465 KUNIT_ASSERT_LE_MSG(test, count, max_count,
466 "count (%d) is too big (%d) ... aborting", count, max_count);
467 KUNIT_EXPECT_LE_MSG(test, expected, max_expected,
468 "expected (%d) is bigger than can possibly be returned (%d)",
469 expected, max_expected);
470
471 written = strscpy_pad(buf, src, count);
472 KUNIT_ASSERT_EQ(test, written, expected);
473
474 if (count && written == -E2BIG) {
475 KUNIT_ASSERT_EQ_MSG(test, 0, strncmp(buf, src, count - 1),
476 "buffer state invalid for -E2BIG");
477 KUNIT_ASSERT_EQ_MSG(test, buf[count - 1], '\0',
478 "too big string is not null terminated correctly");
479 }
480
481 for (i = 0; i < chars; i++)
482 KUNIT_ASSERT_EQ_MSG(test, buf[i], src[i],
483 "buf[i]==%c != src[i]==%c", buf[i], src[i]);
484
485 if (terminator)
486 KUNIT_ASSERT_EQ_MSG(test, buf[count - 1], '\0',
487 "string is not null terminated correctly");
488
489 for (i = 0; i < pad; i++) {
490 index = chars + terminator + i;
491 KUNIT_ASSERT_EQ_MSG(test, buf[index], '\0',
492 "padding missing at index: %d", i);
493 }
494
495 nr_bytes_poison = sizeof(buf) - chars - terminator - pad;
496 for (i = 0; i < nr_bytes_poison; i++) {
497 index = sizeof(buf) - 1 - i; /* Check from the end back */
498 KUNIT_ASSERT_EQ_MSG(test, buf[index], POISON,
499 "poison value missing at index: %d", i);
500 }
501 }
502
string_test_strscpy(struct kunit * test)503 static void string_test_strscpy(struct kunit *test)
504 {
505 char dest[8];
506
507 /*
508 * strscpy_check() uses a destination buffer of size 6 and needs at
509 * least 2 characters spare (one for null and one to check for
510 * overflow). This means we should only call tc() with
511 * strings up to a maximum of 4 characters long and 'count'
512 * should not exceed 4. To test with longer strings increase
513 * the buffer size in tc().
514 */
515
516 /* strscpy_check(test, src, count, expected, chars, terminator, pad) */
517 strscpy_check(test, "a", 0, -E2BIG, 0, 0, 0);
518 strscpy_check(test, "", 0, -E2BIG, 0, 0, 0);
519
520 strscpy_check(test, "a", 1, -E2BIG, 0, 1, 0);
521 strscpy_check(test, "", 1, 0, 0, 1, 0);
522
523 strscpy_check(test, "ab", 2, -E2BIG, 1, 1, 0);
524 strscpy_check(test, "a", 2, 1, 1, 1, 0);
525 strscpy_check(test, "", 2, 0, 0, 1, 1);
526
527 strscpy_check(test, "abc", 3, -E2BIG, 2, 1, 0);
528 strscpy_check(test, "ab", 3, 2, 2, 1, 0);
529 strscpy_check(test, "a", 3, 1, 1, 1, 1);
530 strscpy_check(test, "", 3, 0, 0, 1, 2);
531
532 strscpy_check(test, "abcd", 4, -E2BIG, 3, 1, 0);
533 strscpy_check(test, "abc", 4, 3, 3, 1, 0);
534 strscpy_check(test, "ab", 4, 2, 2, 1, 1);
535 strscpy_check(test, "a", 4, 1, 1, 1, 2);
536 strscpy_check(test, "", 4, 0, 0, 1, 3);
537
538 /* Compile-time-known source strings. */
539 KUNIT_EXPECT_EQ(test, strscpy(dest, "", ARRAY_SIZE(dest)), 0);
540 KUNIT_EXPECT_EQ(test, strscpy(dest, "", 3), 0);
541 KUNIT_EXPECT_EQ(test, strscpy(dest, "", 1), 0);
542 KUNIT_EXPECT_EQ(test, strscpy(dest, "", 0), -E2BIG);
543 KUNIT_EXPECT_EQ(test, strscpy(dest, "Fixed", ARRAY_SIZE(dest)), 5);
544 KUNIT_EXPECT_EQ(test, strscpy(dest, "Fixed", 3), -E2BIG);
545 KUNIT_EXPECT_EQ(test, strscpy(dest, "Fixed", 1), -E2BIG);
546 KUNIT_EXPECT_EQ(test, strscpy(dest, "Fixed", 0), -E2BIG);
547 KUNIT_EXPECT_EQ(test, strscpy(dest, "This is too long", ARRAY_SIZE(dest)), -E2BIG);
548 }
549
550 static volatile int unconst;
551
string_test_strcat(struct kunit * test)552 static void string_test_strcat(struct kunit *test)
553 {
554 char dest[8];
555
556 /* Destination is terminated. */
557 memset(dest, 0, sizeof(dest));
558 KUNIT_EXPECT_EQ(test, strlen(dest), 0);
559 /* Empty copy does nothing. */
560 KUNIT_EXPECT_TRUE(test, strcat(dest, "") == dest);
561 KUNIT_EXPECT_STREQ(test, dest, "");
562 /* 4 characters copied in, stops at %NUL. */
563 KUNIT_EXPECT_TRUE(test, strcat(dest, "four\000123") == dest);
564 KUNIT_EXPECT_STREQ(test, dest, "four");
565 KUNIT_EXPECT_EQ(test, dest[5], '\0');
566 /* 2 more characters copied in okay. */
567 KUNIT_EXPECT_TRUE(test, strcat(dest, "AB") == dest);
568 KUNIT_EXPECT_STREQ(test, dest, "fourAB");
569 }
570
string_test_strncat(struct kunit * test)571 static void string_test_strncat(struct kunit *test)
572 {
573 char dest[8];
574
575 /* Destination is terminated. */
576 memset(dest, 0, sizeof(dest));
577 KUNIT_EXPECT_EQ(test, strlen(dest), 0);
578 /* Empty copy of size 0 does nothing. */
579 KUNIT_EXPECT_TRUE(test, strncat(dest, "", 0 + unconst) == dest);
580 KUNIT_EXPECT_STREQ(test, dest, "");
581 /* Empty copy of size 1 does nothing too. */
582 KUNIT_EXPECT_TRUE(test, strncat(dest, "", 1 + unconst) == dest);
583 KUNIT_EXPECT_STREQ(test, dest, "");
584 /* Copy of max 0 characters should do nothing. */
585 KUNIT_EXPECT_TRUE(test, strncat(dest, "asdf", 0 + unconst) == dest);
586 KUNIT_EXPECT_STREQ(test, dest, "");
587
588 /* 4 characters copied in, even if max is 8. */
589 KUNIT_EXPECT_TRUE(test, strncat(dest, "four\000123", 8 + unconst) == dest);
590 KUNIT_EXPECT_STREQ(test, dest, "four");
591 KUNIT_EXPECT_EQ(test, dest[5], '\0');
592 KUNIT_EXPECT_EQ(test, dest[6], '\0');
593 /* 2 characters copied in okay, 2 ignored. */
594 KUNIT_EXPECT_TRUE(test, strncat(dest, "ABCD", 2 + unconst) == dest);
595 KUNIT_EXPECT_STREQ(test, dest, "fourAB");
596 }
597
string_test_strlcat(struct kunit * test)598 static void string_test_strlcat(struct kunit *test)
599 {
600 char dest[8] = "";
601 int len = sizeof(dest) + unconst;
602
603 /* Destination is terminated. */
604 KUNIT_EXPECT_EQ(test, strlen(dest), 0);
605 /* Empty copy is size 0. */
606 KUNIT_EXPECT_EQ(test, strlcat(dest, "", len), 0);
607 KUNIT_EXPECT_STREQ(test, dest, "");
608 /* Size 1 should keep buffer terminated, report size of source only. */
609 KUNIT_EXPECT_EQ(test, strlcat(dest, "four", 1 + unconst), 4);
610 KUNIT_EXPECT_STREQ(test, dest, "");
611
612 /* 4 characters copied in. */
613 KUNIT_EXPECT_EQ(test, strlcat(dest, "four", len), 4);
614 KUNIT_EXPECT_STREQ(test, dest, "four");
615 /* 2 characters copied in okay, gets to 6 total. */
616 KUNIT_EXPECT_EQ(test, strlcat(dest, "AB", len), 6);
617 KUNIT_EXPECT_STREQ(test, dest, "fourAB");
618 /* 2 characters ignored if max size (7) reached. */
619 KUNIT_EXPECT_EQ(test, strlcat(dest, "CD", 7 + unconst), 8);
620 KUNIT_EXPECT_STREQ(test, dest, "fourAB");
621 /* 1 of 2 characters skipped, now at true max size. */
622 KUNIT_EXPECT_EQ(test, strlcat(dest, "EFG", len), 9);
623 KUNIT_EXPECT_STREQ(test, dest, "fourABE");
624 /* Everything else ignored, now at full size. */
625 KUNIT_EXPECT_EQ(test, strlcat(dest, "1234", len), 11);
626 KUNIT_EXPECT_STREQ(test, dest, "fourABE");
627 }
628
string_test_strtomem(struct kunit * test)629 static void string_test_strtomem(struct kunit *test)
630 {
631 static const char input[sizeof(unsigned long)] = "hi";
632 static const char truncate[] = "this is too long";
633 struct {
634 unsigned long canary1;
635 unsigned char output[sizeof(unsigned long)] __nonstring;
636 unsigned long canary2;
637 } wrap;
638
639 memset(&wrap, 0xFF, sizeof(wrap));
640 KUNIT_EXPECT_EQ_MSG(test, wrap.canary1, ULONG_MAX,
641 "bad initial canary value");
642 KUNIT_EXPECT_EQ_MSG(test, wrap.canary2, ULONG_MAX,
643 "bad initial canary value");
644
645 /* Check unpadded copy leaves surroundings untouched. */
646 strtomem(wrap.output, input);
647 KUNIT_EXPECT_EQ(test, wrap.canary1, ULONG_MAX);
648 KUNIT_EXPECT_EQ(test, wrap.output[0], input[0]);
649 KUNIT_EXPECT_EQ(test, wrap.output[1], input[1]);
650 for (size_t i = 2; i < sizeof(wrap.output); i++)
651 KUNIT_EXPECT_EQ(test, wrap.output[i], 0xFF);
652 KUNIT_EXPECT_EQ(test, wrap.canary2, ULONG_MAX);
653
654 /* Check truncated copy leaves surroundings untouched. */
655 memset(&wrap, 0xFF, sizeof(wrap));
656 strtomem(wrap.output, truncate);
657 KUNIT_EXPECT_EQ(test, wrap.canary1, ULONG_MAX);
658 for (size_t i = 0; i < sizeof(wrap.output); i++)
659 KUNIT_EXPECT_EQ(test, wrap.output[i], truncate[i]);
660 KUNIT_EXPECT_EQ(test, wrap.canary2, ULONG_MAX);
661
662 /* Check padded copy leaves only string padded. */
663 memset(&wrap, 0xFF, sizeof(wrap));
664 strtomem_pad(wrap.output, input, 0xAA);
665 KUNIT_EXPECT_EQ(test, wrap.canary1, ULONG_MAX);
666 KUNIT_EXPECT_EQ(test, wrap.output[0], input[0]);
667 KUNIT_EXPECT_EQ(test, wrap.output[1], input[1]);
668 for (size_t i = 2; i < sizeof(wrap.output); i++)
669 KUNIT_EXPECT_EQ(test, wrap.output[i], 0xAA);
670 KUNIT_EXPECT_EQ(test, wrap.canary2, ULONG_MAX);
671
672 /* Check truncated padded copy has no padding. */
673 memset(&wrap, 0xFF, sizeof(wrap));
674 strtomem(wrap.output, truncate);
675 KUNIT_EXPECT_EQ(test, wrap.canary1, ULONG_MAX);
676 for (size_t i = 0; i < sizeof(wrap.output); i++)
677 KUNIT_EXPECT_EQ(test, wrap.output[i], truncate[i]);
678 KUNIT_EXPECT_EQ(test, wrap.canary2, ULONG_MAX);
679 }
680
681
string_test_memtostr(struct kunit * test)682 static void string_test_memtostr(struct kunit *test)
683 {
684 char nonstring[7] __nonstring = { 'a', 'b', 'c', 'd', 'e', 'f', 'g' };
685 char nonstring_small[3] __nonstring = { 'a', 'b', 'c' };
686 char dest[sizeof(nonstring) + 1];
687
688 /* Copy in a non-NUL-terminated string into exactly right-sized dest. */
689 KUNIT_EXPECT_EQ(test, sizeof(dest), sizeof(nonstring) + 1);
690 memset(dest, 'X', sizeof(dest));
691 memtostr(dest, nonstring);
692 KUNIT_EXPECT_STREQ(test, dest, "abcdefg");
693 memset(dest, 'X', sizeof(dest));
694 memtostr(dest, nonstring_small);
695 KUNIT_EXPECT_STREQ(test, dest, "abc");
696 KUNIT_EXPECT_EQ(test, dest[7], 'X');
697
698 memset(dest, 'X', sizeof(dest));
699 memtostr_pad(dest, nonstring);
700 KUNIT_EXPECT_STREQ(test, dest, "abcdefg");
701 memset(dest, 'X', sizeof(dest));
702 memtostr_pad(dest, nonstring_small);
703 KUNIT_EXPECT_STREQ(test, dest, "abc");
704 KUNIT_EXPECT_EQ(test, dest[7], '\0');
705 }
706
string_test_strends(struct kunit * test)707 static void string_test_strends(struct kunit *test)
708 {
709 KUNIT_EXPECT_TRUE(test, strends("foo-bar", "bar"));
710 KUNIT_EXPECT_TRUE(test, strends("foo-bar", "-bar"));
711 KUNIT_EXPECT_TRUE(test, strends("foobar", "foobar"));
712 KUNIT_EXPECT_TRUE(test, strends("foobar", ""));
713 KUNIT_EXPECT_FALSE(test, strends("bar", "foobar"));
714 KUNIT_EXPECT_FALSE(test, strends("", "foo"));
715 KUNIT_EXPECT_FALSE(test, strends("foobar", "ba"));
716 KUNIT_EXPECT_TRUE(test, strends("", ""));
717 }
718
719 #if IS_ENABLED(CONFIG_STRING_KUNIT_BENCH)
720 /* Target string lengths for benchmarking */
721 static const size_t bench_lens[] = {
722 0, 1, 7, 8, 16, 31, 64, 127, 512, 1024, 3173, 4096,
723 };
724
725 /**
726 * alloc_max_bench_buffer() - Allocate buffer for the max test case.
727 * @test: KUnit context for managed allocation.
728 * @lens: Array of lengths used in the benchmark cases.
729 * @count: Number of elements in the @lens array.
730 * @buf_len: [out] Pointer to store the actually allocated buffer
731 * size (including NUL character).
732 *
733 * Return: Pointer to the allocated memory, or NULL on failure.
734 */
alloc_max_bench_buffer(struct kunit * test,const size_t * lens,size_t count,size_t * buf_len)735 static void *alloc_max_bench_buffer(struct kunit *test, const size_t *lens,
736 size_t count, size_t *buf_len)
737 {
738 size_t max_len = 0;
739 void *buf;
740
741 for (size_t i = 0; i < count; i++)
742 max_len = max(lens[i], max_len);
743
744 /* Add space for NUL character */
745 max_len += 1;
746
747 buf = kunit_kzalloc(test, max_len, GFP_KERNEL);
748 if (!buf)
749 return NULL;
750
751 if (buf_len)
752 *buf_len = max_len;
753
754 return buf;
755 }
756
757 /**
758 * fill_random_string() - Populate a buffer with a random NUL-terminated string.
759 * @buf: Buffer to fill.
760 * @len: Length of the buffer in bytes.
761 *
762 * Fills the buffer with random non-NUL bytes and ensures the string is
763 * properly NUL-terminated.
764 */
fill_random_string(char * buf,size_t len)765 static void fill_random_string(char *buf, size_t len)
766 {
767 struct rnd_state state;
768
769 if (!buf || !len)
770 return;
771
772 /* Use a fixed seed to ensure deterministic benchmark results */
773 prandom_seed_state(&state, STRING_BENCH_SEED);
774 prandom_bytes_state(&state, buf, len);
775
776 /* Replace NUL characters to avoid early string termination */
777 for (size_t i = 0; i < len; i++) {
778 if (buf[i] == '\0')
779 buf[i] = 0x01;
780 }
781
782 buf[len - 1] = '\0';
783 }
784
785 /**
786 * STRING_BENCH() - Benchmark string functions.
787 * @iters: Number of iterations to run.
788 * @func: Function to benchmark.
789 * @...: Variable arguments passed to @func.
790 *
791 * Disables preemption and measures the total time in nanoseconds to execute
792 * @func(@__VA_ARGS__) for @iters times, including a small warm-up phase.
793 *
794 * Context: Disables preemption during measurement.
795 * Return: Total execution time in nanoseconds (u64).
796 */
797 #define STRING_BENCH(iters, func, ...) \
798 ({ \
799 /* Volatile function pointer prevents dead code elimination */ \
800 typeof(func) (* volatile __func) = (func); \
801 size_t __bn_iters = (iters); \
802 size_t __bn_warm_iters; \
803 u64 __bn_t; \
804 \
805 /* Use 10% of the given iterations (maximum 50) to warm up */ \
806 __bn_warm_iters = max(__bn_iters / 10, 50U); \
807 \
808 for (size_t __bn_i = 0; __bn_i < __bn_warm_iters; __bn_i++) \
809 (void)__func(__VA_ARGS__); \
810 \
811 preempt_disable(); \
812 __bn_t = ktime_get_ns(); \
813 for (size_t __bn_i = 0; __bn_i < __bn_iters; __bn_i++) \
814 (void)__func(__VA_ARGS__); \
815 __bn_t = ktime_get_ns() - __bn_t; \
816 preempt_enable(); \
817 __bn_t; \
818 })
819
820 /**
821 * STRING_BENCH_BUF() - Benchmark harness for single-buffer functions.
822 * @test: KUnit context.
823 * @buf_name: Local char * variable name to be defined.
824 * @buf_size: Local size_t variable name to be defined.
825 * @func: Function to benchmark.
826 * @...: Extra arguments for @func.
827 *
828 * Prepares a randomized, NUL-terminated buffer and iterates through lengths
829 * in bench_lens, defining @buf_name and @buf_size in each loop.
830 */
831 #define STRING_BENCH_BUF(test, buf_name, buf_size, func, ...) \
832 do { \
833 size_t _bn_i, _bn_iters, _bn_size = 0; \
834 u64 _bn_t, _bn_mbps = 0, _bn_lat = 0; \
835 char *_bn_buf; \
836 \
837 _bn_buf = alloc_max_bench_buffer(test, bench_lens, \
838 ARRAY_SIZE(bench_lens), &_bn_size); \
839 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, _bn_buf); \
840 \
841 fill_random_string(_bn_buf, _bn_size); \
842 \
843 for (_bn_i = 0; _bn_i < ARRAY_SIZE(bench_lens); _bn_i++) { \
844 size_t buf_size = bench_lens[_bn_i]; \
845 char *buf_name = _bn_buf + _bn_size - buf_size - 1; \
846 _bn_iters = STRING_BENCH_WORKLOAD / max(buf_size, 1U); \
847 \
848 _bn_t = STRING_BENCH(_bn_iters, func, ##__VA_ARGS__); \
849 if (_bn_t > 0) { \
850 _bn_mbps = (u64)(buf_size) * _bn_iters * \
851 (NSEC_PER_SEC / MEGA); \
852 _bn_mbps = div64_u64(_bn_mbps, _bn_t); \
853 _bn_lat = div64_u64(_bn_t, _bn_iters); \
854 } \
855 kunit_info(test, "len=%zu: %llu MB/s (%llu ns/call)\n", \
856 buf_size, _bn_mbps, _bn_lat); \
857 } \
858 } while (0)
859 #else
860 #define STRING_BENCH_BUF(test, buf_name, buf_size, func, ...) \
861 kunit_skip(test, "not enabled")
862 #endif /* IS_ENABLED(CONFIG_STRING_KUNIT_BENCH) */
863
string_bench_strlen(struct kunit * test)864 static void string_bench_strlen(struct kunit *test)
865 {
866 STRING_BENCH_BUF(test, buf, len, strlen, buf);
867 }
868
string_bench_strnlen(struct kunit * test)869 static void string_bench_strnlen(struct kunit *test)
870 {
871 STRING_BENCH_BUF(test, buf, len, strnlen, buf, len);
872 }
873
string_bench_strchr(struct kunit * test)874 static void string_bench_strchr(struct kunit *test)
875 {
876 STRING_BENCH_BUF(test, buf, len, strchr, buf, '\0');
877 }
878
string_bench_strrchr(struct kunit * test)879 static void string_bench_strrchr(struct kunit *test)
880 {
881 STRING_BENCH_BUF(test, buf, len, strrchr, buf, '\0');
882 }
883
884 static struct kunit_case string_test_cases[] = {
885 KUNIT_CASE(string_test_memset16),
886 KUNIT_CASE(string_test_memset32),
887 KUNIT_CASE(string_test_memset64),
888 KUNIT_CASE(string_test_strlen),
889 KUNIT_CASE(string_test_strnlen),
890 KUNIT_CASE(string_test_strchr),
891 KUNIT_CASE(string_test_strnchr),
892 KUNIT_CASE(string_test_strrchr),
893 KUNIT_CASE(string_test_strspn),
894 KUNIT_CASE(string_test_strcmp),
895 KUNIT_CASE(string_test_strcmp_long_strings),
896 KUNIT_CASE(string_test_strncmp),
897 KUNIT_CASE(string_test_strncmp_long_strings),
898 KUNIT_CASE(string_test_strcasecmp),
899 KUNIT_CASE(string_test_strcasecmp_long_strings),
900 KUNIT_CASE(string_test_strncasecmp),
901 KUNIT_CASE(string_test_strncasecmp_long_strings),
902 KUNIT_CASE(string_test_strscpy),
903 KUNIT_CASE(string_test_strcat),
904 KUNIT_CASE(string_test_strncat),
905 KUNIT_CASE(string_test_strlcat),
906 KUNIT_CASE(string_test_strtomem),
907 KUNIT_CASE(string_test_memtostr),
908 KUNIT_CASE(string_test_strends),
909 KUNIT_CASE(string_bench_strlen),
910 KUNIT_CASE(string_bench_strnlen),
911 KUNIT_CASE(string_bench_strchr),
912 KUNIT_CASE(string_bench_strrchr),
913 {}
914 };
915
916 static struct kunit_suite string_test_suite = {
917 .name = "string",
918 .test_cases = string_test_cases,
919 };
920
921 kunit_test_suites(&string_test_suite);
922
923 MODULE_DESCRIPTION("Test cases for string functions");
924 MODULE_LICENSE("GPL v2");
925