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