1 // SPDX-License-Identifier: GPL-2.1+
2 /*
3  * Copyright (C) 2021 Sean Anderson <seanga2@gmail.com>
4  * Copyright (C) 2011-2021 Free Software Foundation, Inc.
5  *
6  * These tests adapted from glibc's string/test-strncat.c
7  */
8 
9 #include <test/lib.h>
10 #include <test/test.h>
11 #include <test/ut.h>
12 
13 #define BUF_SIZE 4096
14 char buf1[BUF_SIZE], buf2[BUF_SIZE];
15 
do_test_strlcat(struct unit_test_state * uts,int line,size_t align1,size_t align2,size_t len1,size_t len2,size_t n)16 static int do_test_strlcat(struct unit_test_state *uts, int line, size_t align1,
17 			   size_t align2, size_t len1, size_t len2, size_t n)
18 {
19 	char *s1, *s2;
20 	size_t i, len, expected, actual;
21 
22 	align1 &= 7;
23 	if (align1 + len1 >= BUF_SIZE)
24 		return 0;
25 	if (align1 + n > BUF_SIZE)
26 		return 0;
27 
28 	align2 &= 7;
29 	if (align2 + len1 + len2 >= BUF_SIZE)
30 		return 0;
31 	if (align2 + len1 + n > BUF_SIZE)
32 		return 0;
33 
34 	s1 = buf1 + align1;
35 	s2 = buf2 + align2;
36 
37 	for (i = 0; i < len1 - 1; i++)
38 		s1[i] = 32 + 23 * i % (127 - 32);
39 	s1[len1 - 1] = '\0';
40 
41 	for (i = 0; i < len2 - 1; i++)
42 		s2[i] = 32 + 23 * i % (127 - 32);
43 	s2[len2 - 1] = '\0';
44 
45 	expected = min(strlen(s2), n) + strlen(s1);
46 	actual = strlcat(s2, s1, n);
47 	if (expected != actual) {
48 		ut_failf(uts, __FILE__, line, __func__,
49 			 "strlcat(s2, s1, n) == min(len2, n) + len1",
50 			 "Expected %#zx (%zd), got %#zx (%zd)",
51 			 expected, expected, actual, actual);
52 		return CMD_RET_FAILURE;
53 	}
54 
55 	len = min3(len1, n - len2, (size_t)0);
56 	if (memcmp(s2 + len2, s1, len)) {
57 		ut_failf(uts, __FILE__, line, __func__,
58 			 "s2 + len1 == s1",
59 			 "Expected \"%.*s\", got \"%.*s\"",
60 			 (int)len, s1, (int)len, s2 + len2);
61 		return CMD_RET_FAILURE;
62 	}
63 
64 	i = min(n, len1 + len2 - 1) - 1;
65 	if (len2 < n && s2[i] != '\0') {
66 		ut_failf(uts, __FILE__, line, __func__,
67 			 "n < len1 && s2[len2 + n] == '\\0'",
68 			 "Expected s2[%zd] = '\\0', got %d ('%c')",
69 			 i, s2[i], s2[i]);
70 		return CMD_RET_FAILURE;
71 	}
72 
73 	return 0;
74 }
75 
76 #define test_strlcat(align1, align2, len1, len2, n) do { \
77 	int ret = do_test_strlcat(uts, __LINE__, align1, align2, len1, len2, \
78 				  n); \
79 	if (ret) \
80 		return ret; \
81 } while (0)
82 
lib_test_strlcat(struct unit_test_state * uts)83 static int lib_test_strlcat(struct unit_test_state *uts)
84 {
85 	size_t i, n;
86 
87 	test_strlcat(0, 2, 2, 2, SIZE_MAX);
88 	test_strlcat(0, 0, 4, 4, SIZE_MAX);
89 	test_strlcat(4, 0, 4, 4, SIZE_MAX);
90 	test_strlcat(0, 0, 8, 8, SIZE_MAX);
91 	test_strlcat(0, 8, 8, 8, SIZE_MAX);
92 
93 	for (i = 1; i < 8; i++) {
94 		test_strlcat(0, 0, 8 << i, 8 << i, SIZE_MAX);
95 		test_strlcat(8 - i, 2 * i, 8 << i, 8 << i, SIZE_MAX);
96 		test_strlcat(0, 0, 8 << i, 2 << i, SIZE_MAX);
97 		test_strlcat(8 - i, 2 * i, 8 << i, 2 << i, SIZE_MAX);
98 
99 		test_strlcat(i, 2 * i, 8 << i, 1, SIZE_MAX);
100 		test_strlcat(2 * i, i, 8 << i, 1, SIZE_MAX);
101 		test_strlcat(i, i, 8 << i, 10, SIZE_MAX);
102 	}
103 
104 	for (n = 2; n <= 2048; n *= 4) {
105 		test_strlcat(0, 2, 2, 2, n);
106 		test_strlcat(0, 0, 4, 4, n);
107 		test_strlcat(4, 0, 4, 4, n);
108 		test_strlcat(0, 0, 8, 8, n);
109 		test_strlcat(0, 8, 8, 8, n);
110 
111 		for (i = 1; i < 8; i++) {
112 			test_strlcat(0, 0, 8 << i, 8 << i, n);
113 			test_strlcat(8 - i, 2 * i, 8 << i, 8 << i, n);
114 			test_strlcat(0, 0, 8 << i, 2 << i, n);
115 			test_strlcat(8 - i, 2 * i, 8 << i, 2 << i, n);
116 
117 			test_strlcat(i, 2 * i, 8 << i, 1, n);
118 			test_strlcat(2 * i, i, 8 << i, 1, n);
119 			test_strlcat(i, i, 8 << i, 10, n);
120 		}
121 	}
122 
123 	return 0;
124 }
125 LIB_TEST(lib_test_strlcat, 0);
126