1 // SPDX-License-Identifier: GPL-2.0-only
2 #include <linux/module.h>
3 #include <linux/printk.h>
4 #include <linux/slab.h>
5 #include <linux/string.h>
6 
memset16_selftest(void)7 static __init int memset16_selftest(void)
8 {
9 	unsigned i, j, k;
10 	u16 v, *p;
11 
12 	p = kmalloc(256 * 2 * 2, GFP_KERNEL);
13 	if (!p)
14 		return -1;
15 
16 	for (i = 0; i < 256; i++) {
17 		for (j = 0; j < 256; j++) {
18 			memset(p, 0xa1, 256 * 2 * sizeof(v));
19 			memset16(p + i, 0xb1b2, j);
20 			for (k = 0; k < 512; k++) {
21 				v = p[k];
22 				if (k < i) {
23 					if (v != 0xa1a1)
24 						goto fail;
25 				} else if (k < i + j) {
26 					if (v != 0xb1b2)
27 						goto fail;
28 				} else {
29 					if (v != 0xa1a1)
30 						goto fail;
31 				}
32 			}
33 		}
34 	}
35 
36 fail:
37 	kfree(p);
38 	if (i < 256)
39 		return (i << 24) | (j << 16) | k | 0x8000;
40 	return 0;
41 }
42 
memset32_selftest(void)43 static __init int memset32_selftest(void)
44 {
45 	unsigned i, j, k;
46 	u32 v, *p;
47 
48 	p = kmalloc(256 * 2 * 4, GFP_KERNEL);
49 	if (!p)
50 		return -1;
51 
52 	for (i = 0; i < 256; i++) {
53 		for (j = 0; j < 256; j++) {
54 			memset(p, 0xa1, 256 * 2 * sizeof(v));
55 			memset32(p + i, 0xb1b2b3b4, j);
56 			for (k = 0; k < 512; k++) {
57 				v = p[k];
58 				if (k < i) {
59 					if (v != 0xa1a1a1a1)
60 						goto fail;
61 				} else if (k < i + j) {
62 					if (v != 0xb1b2b3b4)
63 						goto fail;
64 				} else {
65 					if (v != 0xa1a1a1a1)
66 						goto fail;
67 				}
68 			}
69 		}
70 	}
71 
72 fail:
73 	kfree(p);
74 	if (i < 256)
75 		return (i << 24) | (j << 16) | k | 0x8000;
76 	return 0;
77 }
78 
memset64_selftest(void)79 static __init int memset64_selftest(void)
80 {
81 	unsigned i, j, k;
82 	u64 v, *p;
83 
84 	p = kmalloc(256 * 2 * 8, GFP_KERNEL);
85 	if (!p)
86 		return -1;
87 
88 	for (i = 0; i < 256; i++) {
89 		for (j = 0; j < 256; j++) {
90 			memset(p, 0xa1, 256 * 2 * sizeof(v));
91 			memset64(p + i, 0xb1b2b3b4b5b6b7b8ULL, j);
92 			for (k = 0; k < 512; k++) {
93 				v = p[k];
94 				if (k < i) {
95 					if (v != 0xa1a1a1a1a1a1a1a1ULL)
96 						goto fail;
97 				} else if (k < i + j) {
98 					if (v != 0xb1b2b3b4b5b6b7b8ULL)
99 						goto fail;
100 				} else {
101 					if (v != 0xa1a1a1a1a1a1a1a1ULL)
102 						goto fail;
103 				}
104 			}
105 		}
106 	}
107 
108 fail:
109 	kfree(p);
110 	if (i < 256)
111 		return (i << 24) | (j << 16) | k | 0x8000;
112 	return 0;
113 }
114 
strchr_selftest(void)115 static __init int strchr_selftest(void)
116 {
117 	const char *test_string = "abcdefghijkl";
118 	const char *empty_string = "";
119 	char *result;
120 	int i;
121 
122 	for (i = 0; i < strlen(test_string) + 1; i++) {
123 		result = strchr(test_string, test_string[i]);
124 		if (result - test_string != i)
125 			return i + 'a';
126 	}
127 
128 	result = strchr(empty_string, '\0');
129 	if (result != empty_string)
130 		return 0x101;
131 
132 	result = strchr(empty_string, 'a');
133 	if (result)
134 		return 0x102;
135 
136 	result = strchr(test_string, 'z');
137 	if (result)
138 		return 0x103;
139 
140 	return 0;
141 }
142 
strnchr_selftest(void)143 static __init int strnchr_selftest(void)
144 {
145 	const char *test_string = "abcdefghijkl";
146 	const char *empty_string = "";
147 	char *result;
148 	int i, j;
149 
150 	for (i = 0; i < strlen(test_string) + 1; i++) {
151 		for (j = 0; j < strlen(test_string) + 2; j++) {
152 			result = strnchr(test_string, j, test_string[i]);
153 			if (j <= i) {
154 				if (!result)
155 					continue;
156 				return ((i + 'a') << 8) | j;
157 			}
158 			if (result - test_string != i)
159 				return ((i + 'a') << 8) | j;
160 		}
161 	}
162 
163 	result = strnchr(empty_string, 0, '\0');
164 	if (result)
165 		return 0x10001;
166 
167 	result = strnchr(empty_string, 1, '\0');
168 	if (result != empty_string)
169 		return 0x10002;
170 
171 	result = strnchr(empty_string, 1, 'a');
172 	if (result)
173 		return 0x10003;
174 
175 	result = strnchr(NULL, 0, '\0');
176 	if (result)
177 		return 0x10004;
178 
179 	return 0;
180 }
181 
strspn_selftest(void)182 static __init int strspn_selftest(void)
183 {
184 	static const struct strspn_test {
185 		const char str[16];
186 		const char accept[16];
187 		const char reject[16];
188 		unsigned a;
189 		unsigned r;
190 	} tests[] __initconst = {
191 		{ "foobar", "", "", 0, 6 },
192 		{ "abba", "abc", "ABBA", 4, 4 },
193 		{ "abba", "a", "b", 1, 1 },
194 		{ "", "abc", "abc", 0, 0},
195 	};
196 	const struct strspn_test *s = tests;
197 	size_t i, res;
198 
199 	for (i = 0; i < ARRAY_SIZE(tests); ++i, ++s) {
200 		res = strspn(s->str, s->accept);
201 		if (res != s->a)
202 			return 0x100 + 2*i;
203 		res = strcspn(s->str, s->reject);
204 		if (res != s->r)
205 			return 0x100 + 2*i + 1;
206 	}
207 	return 0;
208 }
209 
string_selftest_remove(void)210 static __exit void string_selftest_remove(void)
211 {
212 }
213 
string_selftest_init(void)214 static __init int string_selftest_init(void)
215 {
216 	int test, subtest;
217 
218 	test = 1;
219 	subtest = memset16_selftest();
220 	if (subtest)
221 		goto fail;
222 
223 	test = 2;
224 	subtest = memset32_selftest();
225 	if (subtest)
226 		goto fail;
227 
228 	test = 3;
229 	subtest = memset64_selftest();
230 	if (subtest)
231 		goto fail;
232 
233 	test = 4;
234 	subtest = strchr_selftest();
235 	if (subtest)
236 		goto fail;
237 
238 	test = 5;
239 	subtest = strnchr_selftest();
240 	if (subtest)
241 		goto fail;
242 
243 	test = 6;
244 	subtest = strspn_selftest();
245 	if (subtest)
246 		goto fail;
247 
248 	pr_info("String selftests succeeded\n");
249 	return 0;
250 fail:
251 	pr_crit("String selftest failure %d.%08x\n", test, subtest);
252 	return 0;
253 }
254 
255 module_init(string_selftest_init);
256 module_exit(string_selftest_remove);
257 MODULE_LICENSE("GPL v2");
258