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 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 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 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 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 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 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 210 static __exit void string_selftest_remove(void) 211 { 212 } 213 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