Merge tag 'ucount-rlimits-cleanups-for-v5.19' of git://git.kernel.org/pub/scm/linux...
[platform/kernel/linux-starfive.git] / lib / memcpy_kunit.c
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");