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 
string_selftest_init(void)182 static __init int string_selftest_init(void)
183 {
184 	int test, subtest;
185 
186 	test = 1;
187 	subtest = memset16_selftest();
188 	if (subtest)
189 		goto fail;
190 
191 	test = 2;
192 	subtest = memset32_selftest();
193 	if (subtest)
194 		goto fail;
195 
196 	test = 3;
197 	subtest = memset64_selftest();
198 	if (subtest)
199 		goto fail;
200 
201 	test = 4;
202 	subtest = strchr_selftest();
203 	if (subtest)
204 		goto fail;
205 
206 	test = 5;
207 	subtest = strnchr_selftest();
208 	if (subtest)
209 		goto fail;
210 
211 	pr_info("String selftests succeeded\n");
212 	return 0;
213 fail:
214 	pr_crit("String selftest failure %d.%08x\n", test, subtest);
215 	return 0;
216 }
217 
218 module_init(string_selftest_init);
219 MODULE_LICENSE("GPL v2");
220