1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Test cases for memcpy(), memmove(), and memset(). 4 */ 5 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 6 7 #include <kunit/test.h> 8 #include <linux/device.h> 9 #include <linux/init.h> 10 #include <linux/kernel.h> 11 #include <linux/mm.h> 12 #include <linux/module.h> 13 #include <linux/overflow.h> 14 #include <linux/slab.h> 15 #include <linux/types.h> 16 #include <linux/vmalloc.h> 17 18 struct some_bytes { 19 union { 20 u8 data[32]; 21 struct { 22 u32 one; 23 u16 two; 24 u8 three; 25 /* 1 byte hole */ 26 u32 four[4]; 27 }; 28 }; 29 }; 30 31 #define check(instance, v) do { \ 32 BUILD_BUG_ON(sizeof(instance.data) != 32); \ 33 for (size_t i = 0; i < sizeof(instance.data); i++) { \ 34 KUNIT_ASSERT_EQ_MSG(test, instance.data[i], v, \ 35 "line %d: '%s' not initialized to 0x%02x @ %d (saw 0x%02x)\n", \ 36 __LINE__, #instance, v, i, instance.data[i]); \ 37 } \ 38 } while (0) 39 40 #define compare(name, one, two) do { \ 41 BUILD_BUG_ON(sizeof(one) != sizeof(two)); \ 42 for (size_t i = 0; i < sizeof(one); i++) { \ 43 KUNIT_EXPECT_EQ_MSG(test, one.data[i], two.data[i], \ 44 "line %d: %s.data[%d] (0x%02x) != %s.data[%d] (0x%02x)\n", \ 45 __LINE__, #one, i, one.data[i], #two, i, two.data[i]); \ 46 } \ 47 kunit_info(test, "ok: " TEST_OP "() " name "\n"); \ 48 } while (0) 49 50 static void memcpy_test(struct kunit *test) 51 { 52 #define TEST_OP "memcpy" 53 struct some_bytes control = { 54 .data = { 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 55 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 56 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 57 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 58 }, 59 }; 60 struct some_bytes zero = { }; 61 struct some_bytes middle = { 62 .data = { 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 63 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 64 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 65 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 66 }, 67 }; 68 struct some_bytes three = { 69 .data = { 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 70 0x20, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 71 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 72 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 73 }, 74 }; 75 struct some_bytes dest = { }; 76 int count; 77 u8 *ptr; 78 79 /* Verify static initializers. */ 80 check(control, 0x20); 81 check(zero, 0); 82 compare("static initializers", dest, zero); 83 84 /* Verify assignment. */ 85 dest = control; 86 compare("direct assignment", dest, control); 87 88 /* Verify complete overwrite. */ 89 memcpy(dest.data, zero.data, sizeof(dest.data)); 90 compare("complete overwrite", dest, zero); 91 92 /* Verify middle overwrite. */ 93 dest = control; 94 memcpy(dest.data + 12, zero.data, 7); 95 compare("middle overwrite", dest, middle); 96 97 /* Verify argument side-effects aren't repeated. */ 98 dest = control; 99 ptr = dest.data; 100 count = 1; 101 memcpy(ptr++, zero.data, count++); 102 ptr += 8; 103 memcpy(ptr++, zero.data, count++); 104 compare("argument side-effects", dest, three); 105 #undef TEST_OP 106 } 107 108 static void memmove_test(struct kunit *test) 109 { 110 #define TEST_OP "memmove" 111 struct some_bytes control = { 112 .data = { 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 113 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 114 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 115 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 116 }, 117 }; 118 struct some_bytes zero = { }; 119 struct some_bytes middle = { 120 .data = { 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 121 0x99, 0x99, 0x99, 0x99, 0x00, 0x00, 0x00, 0x00, 122 0x00, 0x00, 0x00, 0x99, 0x99, 0x99, 0x99, 0x99, 123 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 124 }, 125 }; 126 struct some_bytes five = { 127 .data = { 0x00, 0x00, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 128 0x99, 0x99, 0x00, 0x00, 0x00, 0x99, 0x99, 0x99, 129 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 130 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 131 }, 132 }; 133 struct some_bytes overlap = { 134 .data = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 135 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 136 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 137 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 138 }, 139 }; 140 struct some_bytes overlap_expected = { 141 .data = { 0x00, 0x01, 0x00, 0x01, 0x02, 0x03, 0x04, 0x07, 142 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 143 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 144 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 145 }, 146 }; 147 struct some_bytes dest = { }; 148 int count; 149 u8 *ptr; 150 151 /* Verify static initializers. */ 152 check(control, 0x99); 153 check(zero, 0); 154 compare("static initializers", zero, dest); 155 156 /* Verify assignment. */ 157 dest = control; 158 compare("direct assignment", dest, control); 159 160 /* Verify complete overwrite. */ 161 memmove(dest.data, zero.data, sizeof(dest.data)); 162 compare("complete overwrite", dest, zero); 163 164 /* Verify middle overwrite. */ 165 dest = control; 166 memmove(dest.data + 12, zero.data, 7); 167 compare("middle overwrite", dest, middle); 168 169 /* Verify argument side-effects aren't repeated. */ 170 dest = control; 171 ptr = dest.data; 172 count = 2; 173 memmove(ptr++, zero.data, count++); 174 ptr += 9; 175 memmove(ptr++, zero.data, count++); 176 compare("argument side-effects", dest, five); 177 178 /* Verify overlapping overwrite is correct. */ 179 ptr = &overlap.data[2]; 180 memmove(ptr, overlap.data, 5); 181 compare("overlapping write", overlap, overlap_expected); 182 #undef TEST_OP 183 } 184 185 static void memset_test(struct kunit *test) 186 { 187 #define TEST_OP "memset" 188 struct some_bytes control = { 189 .data = { 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 190 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 191 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 192 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 193 }, 194 }; 195 struct some_bytes complete = { 196 .data = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 197 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 198 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 199 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 200 }, 201 }; 202 struct some_bytes middle = { 203 .data = { 0x30, 0x30, 0x30, 0x30, 0x31, 0x31, 0x31, 0x31, 204 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 205 0x31, 0x31, 0x31, 0x31, 0x30, 0x30, 0x30, 0x30, 206 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 207 }, 208 }; 209 struct some_bytes three = { 210 .data = { 0x60, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 211 0x30, 0x61, 0x61, 0x30, 0x30, 0x30, 0x30, 0x30, 212 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 213 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 214 }, 215 }; 216 struct some_bytes after = { 217 .data = { 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x72, 218 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 219 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 220 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 221 }, 222 }; 223 struct some_bytes startat = { 224 .data = { 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 225 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 226 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 227 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 228 }, 229 }; 230 struct some_bytes dest = { }; 231 int count, value; 232 u8 *ptr; 233 234 /* Verify static initializers. */ 235 check(control, 0x30); 236 check(dest, 0); 237 238 /* Verify assignment. */ 239 dest = control; 240 compare("direct assignment", dest, control); 241 242 /* Verify complete overwrite. */ 243 memset(dest.data, 0xff, sizeof(dest.data)); 244 compare("complete overwrite", dest, complete); 245 246 /* Verify middle overwrite. */ 247 dest = control; 248 memset(dest.data + 4, 0x31, 16); 249 compare("middle overwrite", dest, middle); 250 251 /* Verify argument side-effects aren't repeated. */ 252 dest = control; 253 ptr = dest.data; 254 value = 0x60; 255 count = 1; 256 memset(ptr++, value++, count++); 257 ptr += 8; 258 memset(ptr++, value++, count++); 259 compare("argument side-effects", dest, three); 260 261 /* Verify memset_after() */ 262 dest = control; 263 memset_after(&dest, 0x72, three); 264 compare("memset_after()", dest, after); 265 266 /* Verify memset_startat() */ 267 dest = control; 268 memset_startat(&dest, 0x79, four); 269 compare("memset_startat()", dest, startat); 270 #undef TEST_OP 271 } 272 273 static void strtomem_test(struct kunit *test) 274 { 275 static const char input[sizeof(unsigned long)] = "hi"; 276 static const char truncate[] = "this is too long"; 277 struct { 278 unsigned long canary1; 279 unsigned char output[sizeof(unsigned long)] __nonstring; 280 unsigned long canary2; 281 } wrap; 282 283 memset(&wrap, 0xFF, sizeof(wrap)); 284 KUNIT_EXPECT_EQ_MSG(test, wrap.canary1, ULONG_MAX, 285 "bad initial canary value"); 286 KUNIT_EXPECT_EQ_MSG(test, wrap.canary2, ULONG_MAX, 287 "bad initial canary value"); 288 289 /* Check unpadded copy leaves surroundings untouched. */ 290 strtomem(wrap.output, input); 291 KUNIT_EXPECT_EQ(test, wrap.canary1, ULONG_MAX); 292 KUNIT_EXPECT_EQ(test, wrap.output[0], input[0]); 293 KUNIT_EXPECT_EQ(test, wrap.output[1], input[1]); 294 for (size_t i = 2; i < sizeof(wrap.output); i++) 295 KUNIT_EXPECT_EQ(test, wrap.output[i], 0xFF); 296 KUNIT_EXPECT_EQ(test, wrap.canary2, ULONG_MAX); 297 298 /* Check truncated copy leaves surroundings untouched. */ 299 memset(&wrap, 0xFF, sizeof(wrap)); 300 strtomem(wrap.output, truncate); 301 KUNIT_EXPECT_EQ(test, wrap.canary1, ULONG_MAX); 302 for (size_t i = 0; i < sizeof(wrap.output); i++) 303 KUNIT_EXPECT_EQ(test, wrap.output[i], truncate[i]); 304 KUNIT_EXPECT_EQ(test, wrap.canary2, ULONG_MAX); 305 306 /* Check padded copy leaves only string padded. */ 307 memset(&wrap, 0xFF, sizeof(wrap)); 308 strtomem_pad(wrap.output, input, 0xAA); 309 KUNIT_EXPECT_EQ(test, wrap.canary1, ULONG_MAX); 310 KUNIT_EXPECT_EQ(test, wrap.output[0], input[0]); 311 KUNIT_EXPECT_EQ(test, wrap.output[1], input[1]); 312 for (size_t i = 2; i < sizeof(wrap.output); i++) 313 KUNIT_EXPECT_EQ(test, wrap.output[i], 0xAA); 314 KUNIT_EXPECT_EQ(test, wrap.canary2, ULONG_MAX); 315 316 /* Check truncated padded copy has no padding. */ 317 memset(&wrap, 0xFF, sizeof(wrap)); 318 strtomem(wrap.output, truncate); 319 KUNIT_EXPECT_EQ(test, wrap.canary1, ULONG_MAX); 320 for (size_t i = 0; i < sizeof(wrap.output); i++) 321 KUNIT_EXPECT_EQ(test, wrap.output[i], truncate[i]); 322 KUNIT_EXPECT_EQ(test, wrap.canary2, ULONG_MAX); 323 } 324 325 static struct kunit_case memcpy_test_cases[] = { 326 KUNIT_CASE(memset_test), 327 KUNIT_CASE(memcpy_test), 328 KUNIT_CASE(memmove_test), 329 KUNIT_CASE(strtomem_test), 330 {} 331 }; 332 333 static struct kunit_suite memcpy_test_suite = { 334 .name = "memcpy", 335 .test_cases = memcpy_test_cases, 336 }; 337 338 kunit_test_suite(memcpy_test_suite); 339 340 MODULE_LICENSE("GPL"); 341