Linux 6.9-rc5
[sfrench/cifs-2.6.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         int i;  \
33         BUILD_BUG_ON(sizeof(instance.data) != 32);      \
34         for (i = 0; i < sizeof(instance.data); i++) {   \
35                 KUNIT_ASSERT_EQ_MSG(test, instance.data[i], v, \
36                         "line %d: '%s' not initialized to 0x%02x @ %d (saw 0x%02x)\n", \
37                         __LINE__, #instance, v, i, instance.data[i]);   \
38         }       \
39 } while (0)
40
41 #define compare(name, one, two) do { \
42         int i; \
43         BUILD_BUG_ON(sizeof(one) != sizeof(two)); \
44         for (i = 0; i < sizeof(one); i++) {     \
45                 KUNIT_EXPECT_EQ_MSG(test, one.data[i], two.data[i], \
46                         "line %d: %s.data[%d] (0x%02x) != %s.data[%d] (0x%02x)\n", \
47                         __LINE__, #one, i, one.data[i], #two, i, two.data[i]); \
48         }       \
49         kunit_info(test, "ok: " TEST_OP "() " name "\n");       \
50 } while (0)
51
52 static void memcpy_test(struct kunit *test)
53 {
54 #define TEST_OP "memcpy"
55         struct some_bytes control = {
56                 .data = { 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
57                           0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
58                           0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
59                           0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
60                         },
61         };
62         struct some_bytes zero = { };
63         struct some_bytes middle = {
64                 .data = { 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
65                           0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00,
66                           0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20,
67                           0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
68                         },
69         };
70         struct some_bytes three = {
71                 .data = { 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
72                           0x20, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20,
73                           0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
74                           0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
75                         },
76         };
77         struct some_bytes dest = { };
78         int count;
79         u8 *ptr;
80
81         /* Verify static initializers. */
82         check(control, 0x20);
83         check(zero, 0);
84         compare("static initializers", dest, zero);
85
86         /* Verify assignment. */
87         dest = control;
88         compare("direct assignment", dest, control);
89
90         /* Verify complete overwrite. */
91         memcpy(dest.data, zero.data, sizeof(dest.data));
92         compare("complete overwrite", dest, zero);
93
94         /* Verify middle overwrite. */
95         dest = control;
96         memcpy(dest.data + 12, zero.data, 7);
97         compare("middle overwrite", dest, middle);
98
99         /* Verify argument side-effects aren't repeated. */
100         dest = control;
101         ptr = dest.data;
102         count = 1;
103         memcpy(ptr++, zero.data, count++);
104         ptr += 8;
105         memcpy(ptr++, zero.data, count++);
106         compare("argument side-effects", dest, three);
107 #undef TEST_OP
108 }
109
110 static void memmove_test(struct kunit *test)
111 {
112 #define TEST_OP "memmove"
113         struct some_bytes control = {
114                 .data = { 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
115                           0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
116                           0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
117                           0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
118                         },
119         };
120         struct some_bytes zero = { };
121         struct some_bytes middle = {
122                 .data = { 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
123                           0x99, 0x99, 0x99, 0x99, 0x00, 0x00, 0x00, 0x00,
124                           0x00, 0x00, 0x00, 0x99, 0x99, 0x99, 0x99, 0x99,
125                           0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
126                         },
127         };
128         struct some_bytes five = {
129                 .data = { 0x00, 0x00, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
130                           0x99, 0x99, 0x00, 0x00, 0x00, 0x99, 0x99, 0x99,
131                           0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
132                           0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
133                         },
134         };
135         struct some_bytes overlap = {
136                 .data = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
137                           0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
138                           0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
139                           0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
140                         },
141         };
142         struct some_bytes overlap_expected = {
143                 .data = { 0x00, 0x01, 0x00, 0x01, 0x02, 0x03, 0x04, 0x07,
144                           0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
145                           0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
146                           0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
147                         },
148         };
149         struct some_bytes dest = { };
150         int count;
151         u8 *ptr;
152
153         /* Verify static initializers. */
154         check(control, 0x99);
155         check(zero, 0);
156         compare("static initializers", zero, dest);
157
158         /* Verify assignment. */
159         dest = control;
160         compare("direct assignment", dest, control);
161
162         /* Verify complete overwrite. */
163         memmove(dest.data, zero.data, sizeof(dest.data));
164         compare("complete overwrite", dest, zero);
165
166         /* Verify middle overwrite. */
167         dest = control;
168         memmove(dest.data + 12, zero.data, 7);
169         compare("middle overwrite", dest, middle);
170
171         /* Verify argument side-effects aren't repeated. */
172         dest = control;
173         ptr = dest.data;
174         count = 2;
175         memmove(ptr++, zero.data, count++);
176         ptr += 9;
177         memmove(ptr++, zero.data, count++);
178         compare("argument side-effects", dest, five);
179
180         /* Verify overlapping overwrite is correct. */
181         ptr = &overlap.data[2];
182         memmove(ptr, overlap.data, 5);
183         compare("overlapping write", overlap, overlap_expected);
184 #undef TEST_OP
185 }
186
187 static void memset_test(struct kunit *test)
188 {
189 #define TEST_OP "memset"
190         struct some_bytes control = {
191                 .data = { 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
192                           0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
193                           0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
194                           0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
195                         },
196         };
197         struct some_bytes complete = {
198                 .data = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
199                           0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
200                           0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
201                           0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
202                         },
203         };
204         struct some_bytes middle = {
205                 .data = { 0x30, 0x30, 0x30, 0x30, 0x31, 0x31, 0x31, 0x31,
206                           0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
207                           0x31, 0x31, 0x31, 0x31, 0x30, 0x30, 0x30, 0x30,
208                           0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
209                         },
210         };
211         struct some_bytes three = {
212                 .data = { 0x60, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
213                           0x30, 0x61, 0x61, 0x30, 0x30, 0x30, 0x30, 0x30,
214                           0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
215                           0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
216                         },
217         };
218         struct some_bytes after = {
219                 .data = { 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x72,
220                           0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72,
221                           0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72,
222                           0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72,
223                         },
224         };
225         struct some_bytes startat = {
226                 .data = { 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
227                           0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79,
228                           0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79,
229                           0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79,
230                         },
231         };
232         struct some_bytes dest = { };
233         int count, value;
234         u8 *ptr;
235
236         /* Verify static initializers. */
237         check(control, 0x30);
238         check(dest, 0);
239
240         /* Verify assignment. */
241         dest = control;
242         compare("direct assignment", dest, control);
243
244         /* Verify complete overwrite. */
245         memset(dest.data, 0xff, sizeof(dest.data));
246         compare("complete overwrite", dest, complete);
247
248         /* Verify middle overwrite. */
249         dest = control;
250         memset(dest.data + 4, 0x31, 16);
251         compare("middle overwrite", dest, middle);
252
253         /* Verify argument side-effects aren't repeated. */
254         dest = control;
255         ptr = dest.data;
256         value = 0x60;
257         count = 1;
258         memset(ptr++, value++, count++);
259         ptr += 8;
260         memset(ptr++, value++, count++);
261         compare("argument side-effects", dest, three);
262
263         /* Verify memset_after() */
264         dest = control;
265         memset_after(&dest, 0x72, three);
266         compare("memset_after()", dest, after);
267
268         /* Verify memset_startat() */
269         dest = control;
270         memset_startat(&dest, 0x79, four);
271         compare("memset_startat()", dest, startat);
272 #undef TEST_OP
273 }
274
275 static struct kunit_case memcpy_test_cases[] = {
276         KUNIT_CASE(memset_test),
277         KUNIT_CASE(memcpy_test),
278         KUNIT_CASE(memmove_test),
279         {}
280 };
281
282 static struct kunit_suite memcpy_test_suite = {
283         .name = "memcpy",
284         .test_cases = memcpy_test_cases,
285 };
286
287 kunit_test_suite(memcpy_test_suite);
288
289 MODULE_LICENSE("GPL");