xref: /openbmc/linux/lib/overflow_kunit.c (revision 2612e3bbc0386368a850140a6c9b990cd496a5ec)
1617f55e2SKees Cook // SPDX-License-Identifier: GPL-2.0 OR MIT
2617f55e2SKees Cook /*
3617f55e2SKees Cook  * Test cases for arithmetic overflow checks. See:
40f3f1123STales Aparecida  * "Running tests with kunit_tool" at Documentation/dev-tools/kunit/start.rst
5617f55e2SKees Cook  *	./tools/testing/kunit/kunit.py run overflow [--raw_output]
6617f55e2SKees Cook  */
7617f55e2SKees Cook #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
8617f55e2SKees Cook 
9617f55e2SKees Cook #include <kunit/test.h>
10617f55e2SKees Cook #include <linux/device.h>
11617f55e2SKees Cook #include <linux/kernel.h>
12617f55e2SKees Cook #include <linux/mm.h>
13617f55e2SKees Cook #include <linux/module.h>
14617f55e2SKees Cook #include <linux/overflow.h>
15617f55e2SKees Cook #include <linux/slab.h>
16617f55e2SKees Cook #include <linux/types.h>
17617f55e2SKees Cook #include <linux/vmalloc.h>
18617f55e2SKees Cook 
1972c3ebeaSKees Cook #define SKIP(cond, reason)		do {			\
2072c3ebeaSKees Cook 	if (cond) {						\
2172c3ebeaSKees Cook 		kunit_skip(test, reason);			\
2272c3ebeaSKees Cook 		return;						\
2372c3ebeaSKees Cook 	}							\
2472c3ebeaSKees Cook } while (0)
2572c3ebeaSKees Cook 
2672c3ebeaSKees Cook /*
2772c3ebeaSKees Cook  * Clang 11 and earlier generate unwanted libcalls for signed output
2872c3ebeaSKees Cook  * on unsigned input.
2972c3ebeaSKees Cook  */
3072c3ebeaSKees Cook #if defined(CONFIG_CC_IS_CLANG) && __clang_major__ <= 11
3172c3ebeaSKees Cook # define SKIP_SIGN_MISMATCH(t)	SKIP(t, "Clang 11 unwanted libcalls")
3272c3ebeaSKees Cook #else
3372c3ebeaSKees Cook # define SKIP_SIGN_MISMATCH(t)	do { } while (0)
3472c3ebeaSKees Cook #endif
3572c3ebeaSKees Cook 
3672c3ebeaSKees Cook /*
3772c3ebeaSKees Cook  * Clang 13 and earlier generate unwanted libcalls for 64-bit tests on
3872c3ebeaSKees Cook  * 32-bit hosts.
3972c3ebeaSKees Cook  */
4072c3ebeaSKees Cook #if defined(CONFIG_CC_IS_CLANG) && __clang_major__ <= 13 &&	\
4172c3ebeaSKees Cook     BITS_PER_LONG != 64
4272c3ebeaSKees Cook # define SKIP_64_ON_32(t)	SKIP(t, "Clang 13 unwanted libcalls")
4372c3ebeaSKees Cook #else
4472c3ebeaSKees Cook # define SKIP_64_ON_32(t)	do { } while (0)
4572c3ebeaSKees Cook #endif
4672c3ebeaSKees Cook 
47d219d2a9SKees Cook #define DEFINE_TEST_ARRAY_TYPED(t1, t2, t)			\
48d219d2a9SKees Cook 	static const struct test_ ## t1 ## _ ## t2 ## __ ## t {	\
49d219d2a9SKees Cook 		t1 a;						\
50d219d2a9SKees Cook 		t2 b;						\
51617f55e2SKees Cook 		t sum, diff, prod;				\
52617f55e2SKees Cook 		bool s_of, d_of, p_of;				\
53d219d2a9SKees Cook 	} t1 ## _ ## t2 ## __ ## t ## _tests[]
54d219d2a9SKees Cook 
55d219d2a9SKees Cook #define DEFINE_TEST_ARRAY(t)	DEFINE_TEST_ARRAY_TYPED(t, t, t)
56617f55e2SKees Cook 
57617f55e2SKees Cook DEFINE_TEST_ARRAY(u8) = {
58617f55e2SKees Cook 	{0, 0, 0, 0, 0, false, false, false},
59617f55e2SKees Cook 	{1, 1, 2, 0, 1, false, false, false},
60617f55e2SKees Cook 	{0, 1, 1, U8_MAX, 0, false, true, false},
61617f55e2SKees Cook 	{1, 0, 1, 1, 0, false, false, false},
62617f55e2SKees Cook 	{0, U8_MAX, U8_MAX, 1, 0, false, true, false},
63617f55e2SKees Cook 	{U8_MAX, 0, U8_MAX, U8_MAX, 0, false, false, false},
64617f55e2SKees Cook 	{1, U8_MAX, 0, 2, U8_MAX, true, true, false},
65617f55e2SKees Cook 	{U8_MAX, 1, 0, U8_MAX-1, U8_MAX, true, false, false},
66617f55e2SKees Cook 	{U8_MAX, U8_MAX, U8_MAX-1, 0, 1, true, false, true},
67617f55e2SKees Cook 
68617f55e2SKees Cook 	{U8_MAX, U8_MAX-1, U8_MAX-2, 1, 2, true, false, true},
69617f55e2SKees Cook 	{U8_MAX-1, U8_MAX, U8_MAX-2, U8_MAX, 2, true, true, true},
70617f55e2SKees Cook 
71617f55e2SKees Cook 	{1U << 3, 1U << 3, 1U << 4, 0, 1U << 6, false, false, false},
72617f55e2SKees Cook 	{1U << 4, 1U << 4, 1U << 5, 0, 0, false, false, true},
73617f55e2SKees Cook 	{1U << 4, 1U << 3, 3*(1U << 3), 1U << 3, 1U << 7, false, false, false},
74617f55e2SKees Cook 	{1U << 7, 1U << 7, 0, 0, 0, true, false, true},
75617f55e2SKees Cook 
76617f55e2SKees Cook 	{48, 32, 80, 16, 0, false, false, true},
77617f55e2SKees Cook 	{128, 128, 0, 0, 0, true, false, true},
78617f55e2SKees Cook 	{123, 234, 101, 145, 110, true, true, true},
79617f55e2SKees Cook };
80617f55e2SKees Cook DEFINE_TEST_ARRAY(u16) = {
81617f55e2SKees Cook 	{0, 0, 0, 0, 0, false, false, false},
82617f55e2SKees Cook 	{1, 1, 2, 0, 1, false, false, false},
83617f55e2SKees Cook 	{0, 1, 1, U16_MAX, 0, false, true, false},
84617f55e2SKees Cook 	{1, 0, 1, 1, 0, false, false, false},
85617f55e2SKees Cook 	{0, U16_MAX, U16_MAX, 1, 0, false, true, false},
86617f55e2SKees Cook 	{U16_MAX, 0, U16_MAX, U16_MAX, 0, false, false, false},
87617f55e2SKees Cook 	{1, U16_MAX, 0, 2, U16_MAX, true, true, false},
88617f55e2SKees Cook 	{U16_MAX, 1, 0, U16_MAX-1, U16_MAX, true, false, false},
89617f55e2SKees Cook 	{U16_MAX, U16_MAX, U16_MAX-1, 0, 1, true, false, true},
90617f55e2SKees Cook 
91617f55e2SKees Cook 	{U16_MAX, U16_MAX-1, U16_MAX-2, 1, 2, true, false, true},
92617f55e2SKees Cook 	{U16_MAX-1, U16_MAX, U16_MAX-2, U16_MAX, 2, true, true, true},
93617f55e2SKees Cook 
94617f55e2SKees Cook 	{1U << 7, 1U << 7, 1U << 8, 0, 1U << 14, false, false, false},
95617f55e2SKees Cook 	{1U << 8, 1U << 8, 1U << 9, 0, 0, false, false, true},
96617f55e2SKees Cook 	{1U << 8, 1U << 7, 3*(1U << 7), 1U << 7, 1U << 15, false, false, false},
97617f55e2SKees Cook 	{1U << 15, 1U << 15, 0, 0, 0, true, false, true},
98617f55e2SKees Cook 
99617f55e2SKees Cook 	{123, 234, 357, 65425, 28782, false, true, false},
100617f55e2SKees Cook 	{1234, 2345, 3579, 64425, 10146, false, true, true},
101617f55e2SKees Cook };
102617f55e2SKees Cook DEFINE_TEST_ARRAY(u32) = {
103617f55e2SKees Cook 	{0, 0, 0, 0, 0, false, false, false},
104617f55e2SKees Cook 	{1, 1, 2, 0, 1, false, false, false},
105617f55e2SKees Cook 	{0, 1, 1, U32_MAX, 0, false, true, false},
106617f55e2SKees Cook 	{1, 0, 1, 1, 0, false, false, false},
107617f55e2SKees Cook 	{0, U32_MAX, U32_MAX, 1, 0, false, true, false},
108617f55e2SKees Cook 	{U32_MAX, 0, U32_MAX, U32_MAX, 0, false, false, false},
109617f55e2SKees Cook 	{1, U32_MAX, 0, 2, U32_MAX, true, true, false},
110617f55e2SKees Cook 	{U32_MAX, 1, 0, U32_MAX-1, U32_MAX, true, false, false},
111617f55e2SKees Cook 	{U32_MAX, U32_MAX, U32_MAX-1, 0, 1, true, false, true},
112617f55e2SKees Cook 
113617f55e2SKees Cook 	{U32_MAX, U32_MAX-1, U32_MAX-2, 1, 2, true, false, true},
114617f55e2SKees Cook 	{U32_MAX-1, U32_MAX, U32_MAX-2, U32_MAX, 2, true, true, true},
115617f55e2SKees Cook 
116617f55e2SKees Cook 	{1U << 15, 1U << 15, 1U << 16, 0, 1U << 30, false, false, false},
117617f55e2SKees Cook 	{1U << 16, 1U << 16, 1U << 17, 0, 0, false, false, true},
118617f55e2SKees Cook 	{1U << 16, 1U << 15, 3*(1U << 15), 1U << 15, 1U << 31, false, false, false},
119617f55e2SKees Cook 	{1U << 31, 1U << 31, 0, 0, 0, true, false, true},
120617f55e2SKees Cook 
121617f55e2SKees Cook 	{-2U, 1U, -1U, -3U, -2U, false, false, false},
122617f55e2SKees Cook 	{-4U, 5U, 1U, -9U, -20U, true, false, true},
123617f55e2SKees Cook };
124617f55e2SKees Cook 
125617f55e2SKees Cook DEFINE_TEST_ARRAY(u64) = {
126617f55e2SKees Cook 	{0, 0, 0, 0, 0, false, false, false},
127617f55e2SKees Cook 	{1, 1, 2, 0, 1, false, false, false},
128617f55e2SKees Cook 	{0, 1, 1, U64_MAX, 0, false, true, false},
129617f55e2SKees Cook 	{1, 0, 1, 1, 0, false, false, false},
130617f55e2SKees Cook 	{0, U64_MAX, U64_MAX, 1, 0, false, true, false},
131617f55e2SKees Cook 	{U64_MAX, 0, U64_MAX, U64_MAX, 0, false, false, false},
132617f55e2SKees Cook 	{1, U64_MAX, 0, 2, U64_MAX, true, true, false},
133617f55e2SKees Cook 	{U64_MAX, 1, 0, U64_MAX-1, U64_MAX, true, false, false},
134617f55e2SKees Cook 	{U64_MAX, U64_MAX, U64_MAX-1, 0, 1, true, false, true},
135617f55e2SKees Cook 
136617f55e2SKees Cook 	{U64_MAX, U64_MAX-1, U64_MAX-2, 1, 2, true, false, true},
137617f55e2SKees Cook 	{U64_MAX-1, U64_MAX, U64_MAX-2, U64_MAX, 2, true, true, true},
138617f55e2SKees Cook 
139617f55e2SKees Cook 	{1ULL << 31, 1ULL << 31, 1ULL << 32, 0, 1ULL << 62, false, false, false},
140617f55e2SKees Cook 	{1ULL << 32, 1ULL << 32, 1ULL << 33, 0, 0, false, false, true},
141617f55e2SKees Cook 	{1ULL << 32, 1ULL << 31, 3*(1ULL << 31), 1ULL << 31, 1ULL << 63, false, false, false},
142617f55e2SKees Cook 	{1ULL << 63, 1ULL << 63, 0, 0, 0, true, false, true},
143617f55e2SKees Cook 	{1000000000ULL /* 10^9 */, 10000000000ULL /* 10^10 */,
144617f55e2SKees Cook 	 11000000000ULL, 18446744064709551616ULL, 10000000000000000000ULL,
145617f55e2SKees Cook 	 false, true, false},
146617f55e2SKees Cook 	{-15ULL, 10ULL, -5ULL, -25ULL, -150ULL, false, false, true},
147617f55e2SKees Cook };
148617f55e2SKees Cook 
149617f55e2SKees Cook DEFINE_TEST_ARRAY(s8) = {
150617f55e2SKees Cook 	{0, 0, 0, 0, 0, false, false, false},
151617f55e2SKees Cook 
152617f55e2SKees Cook 	{0, S8_MAX, S8_MAX, -S8_MAX, 0, false, false, false},
153617f55e2SKees Cook 	{S8_MAX, 0, S8_MAX, S8_MAX, 0, false, false, false},
154617f55e2SKees Cook 	{0, S8_MIN, S8_MIN, S8_MIN, 0, false, true, false},
155617f55e2SKees Cook 	{S8_MIN, 0, S8_MIN, S8_MIN, 0, false, false, false},
156617f55e2SKees Cook 
157617f55e2SKees Cook 	{-1, S8_MIN, S8_MAX, S8_MAX, S8_MIN, true, false, true},
158617f55e2SKees Cook 	{S8_MIN, -1, S8_MAX, -S8_MAX, S8_MIN, true, false, true},
159617f55e2SKees Cook 	{-1, S8_MAX, S8_MAX-1, S8_MIN, -S8_MAX, false, false, false},
160617f55e2SKees Cook 	{S8_MAX, -1, S8_MAX-1, S8_MIN, -S8_MAX, false, true, false},
161617f55e2SKees Cook 	{-1, -S8_MAX, S8_MIN, S8_MAX-1, S8_MAX, false, false, false},
162617f55e2SKees Cook 	{-S8_MAX, -1, S8_MIN, S8_MIN+2, S8_MAX, false, false, false},
163617f55e2SKees Cook 
164617f55e2SKees Cook 	{1, S8_MIN, -S8_MAX, -S8_MAX, S8_MIN, false, true, false},
165617f55e2SKees Cook 	{S8_MIN, 1, -S8_MAX, S8_MAX, S8_MIN, false, true, false},
166617f55e2SKees Cook 	{1, S8_MAX, S8_MIN, S8_MIN+2, S8_MAX, true, false, false},
167617f55e2SKees Cook 	{S8_MAX, 1, S8_MIN, S8_MAX-1, S8_MAX, true, false, false},
168617f55e2SKees Cook 
169617f55e2SKees Cook 	{S8_MIN, S8_MIN, 0, 0, 0, true, false, true},
170617f55e2SKees Cook 	{S8_MAX, S8_MAX, -2, 0, 1, true, false, true},
171617f55e2SKees Cook 
172617f55e2SKees Cook 	{-4, -32, -36, 28, -128, false, false, true},
173617f55e2SKees Cook 	{-4, 32, 28, -36, -128, false, false, false},
174617f55e2SKees Cook };
175617f55e2SKees Cook 
176617f55e2SKees Cook DEFINE_TEST_ARRAY(s16) = {
177617f55e2SKees Cook 	{0, 0, 0, 0, 0, false, false, false},
178617f55e2SKees Cook 
179617f55e2SKees Cook 	{0, S16_MAX, S16_MAX, -S16_MAX, 0, false, false, false},
180617f55e2SKees Cook 	{S16_MAX, 0, S16_MAX, S16_MAX, 0, false, false, false},
181617f55e2SKees Cook 	{0, S16_MIN, S16_MIN, S16_MIN, 0, false, true, false},
182617f55e2SKees Cook 	{S16_MIN, 0, S16_MIN, S16_MIN, 0, false, false, false},
183617f55e2SKees Cook 
184617f55e2SKees Cook 	{-1, S16_MIN, S16_MAX, S16_MAX, S16_MIN, true, false, true},
185617f55e2SKees Cook 	{S16_MIN, -1, S16_MAX, -S16_MAX, S16_MIN, true, false, true},
186617f55e2SKees Cook 	{-1, S16_MAX, S16_MAX-1, S16_MIN, -S16_MAX, false, false, false},
187617f55e2SKees Cook 	{S16_MAX, -1, S16_MAX-1, S16_MIN, -S16_MAX, false, true, false},
188617f55e2SKees Cook 	{-1, -S16_MAX, S16_MIN, S16_MAX-1, S16_MAX, false, false, false},
189617f55e2SKees Cook 	{-S16_MAX, -1, S16_MIN, S16_MIN+2, S16_MAX, false, false, false},
190617f55e2SKees Cook 
191617f55e2SKees Cook 	{1, S16_MIN, -S16_MAX, -S16_MAX, S16_MIN, false, true, false},
192617f55e2SKees Cook 	{S16_MIN, 1, -S16_MAX, S16_MAX, S16_MIN, false, true, false},
193617f55e2SKees Cook 	{1, S16_MAX, S16_MIN, S16_MIN+2, S16_MAX, true, false, false},
194617f55e2SKees Cook 	{S16_MAX, 1, S16_MIN, S16_MAX-1, S16_MAX, true, false, false},
195617f55e2SKees Cook 
196617f55e2SKees Cook 	{S16_MIN, S16_MIN, 0, 0, 0, true, false, true},
197617f55e2SKees Cook 	{S16_MAX, S16_MAX, -2, 0, 1, true, false, true},
198617f55e2SKees Cook };
199617f55e2SKees Cook DEFINE_TEST_ARRAY(s32) = {
200617f55e2SKees Cook 	{0, 0, 0, 0, 0, false, false, false},
201617f55e2SKees Cook 
202617f55e2SKees Cook 	{0, S32_MAX, S32_MAX, -S32_MAX, 0, false, false, false},
203617f55e2SKees Cook 	{S32_MAX, 0, S32_MAX, S32_MAX, 0, false, false, false},
204617f55e2SKees Cook 	{0, S32_MIN, S32_MIN, S32_MIN, 0, false, true, false},
205617f55e2SKees Cook 	{S32_MIN, 0, S32_MIN, S32_MIN, 0, false, false, false},
206617f55e2SKees Cook 
207617f55e2SKees Cook 	{-1, S32_MIN, S32_MAX, S32_MAX, S32_MIN, true, false, true},
208617f55e2SKees Cook 	{S32_MIN, -1, S32_MAX, -S32_MAX, S32_MIN, true, false, true},
209617f55e2SKees Cook 	{-1, S32_MAX, S32_MAX-1, S32_MIN, -S32_MAX, false, false, false},
210617f55e2SKees Cook 	{S32_MAX, -1, S32_MAX-1, S32_MIN, -S32_MAX, false, true, false},
211617f55e2SKees Cook 	{-1, -S32_MAX, S32_MIN, S32_MAX-1, S32_MAX, false, false, false},
212617f55e2SKees Cook 	{-S32_MAX, -1, S32_MIN, S32_MIN+2, S32_MAX, false, false, false},
213617f55e2SKees Cook 
214617f55e2SKees Cook 	{1, S32_MIN, -S32_MAX, -S32_MAX, S32_MIN, false, true, false},
215617f55e2SKees Cook 	{S32_MIN, 1, -S32_MAX, S32_MAX, S32_MIN, false, true, false},
216617f55e2SKees Cook 	{1, S32_MAX, S32_MIN, S32_MIN+2, S32_MAX, true, false, false},
217617f55e2SKees Cook 	{S32_MAX, 1, S32_MIN, S32_MAX-1, S32_MAX, true, false, false},
218617f55e2SKees Cook 
219617f55e2SKees Cook 	{S32_MIN, S32_MIN, 0, 0, 0, true, false, true},
220617f55e2SKees Cook 	{S32_MAX, S32_MAX, -2, 0, 1, true, false, true},
221617f55e2SKees Cook };
2226a022dd2SKees Cook 
223617f55e2SKees Cook DEFINE_TEST_ARRAY(s64) = {
224617f55e2SKees Cook 	{0, 0, 0, 0, 0, false, false, false},
225617f55e2SKees Cook 
226617f55e2SKees Cook 	{0, S64_MAX, S64_MAX, -S64_MAX, 0, false, false, false},
227617f55e2SKees Cook 	{S64_MAX, 0, S64_MAX, S64_MAX, 0, false, false, false},
228617f55e2SKees Cook 	{0, S64_MIN, S64_MIN, S64_MIN, 0, false, true, false},
229617f55e2SKees Cook 	{S64_MIN, 0, S64_MIN, S64_MIN, 0, false, false, false},
230617f55e2SKees Cook 
231617f55e2SKees Cook 	{-1, S64_MIN, S64_MAX, S64_MAX, S64_MIN, true, false, true},
232617f55e2SKees Cook 	{S64_MIN, -1, S64_MAX, -S64_MAX, S64_MIN, true, false, true},
233617f55e2SKees Cook 	{-1, S64_MAX, S64_MAX-1, S64_MIN, -S64_MAX, false, false, false},
234617f55e2SKees Cook 	{S64_MAX, -1, S64_MAX-1, S64_MIN, -S64_MAX, false, true, false},
235617f55e2SKees Cook 	{-1, -S64_MAX, S64_MIN, S64_MAX-1, S64_MAX, false, false, false},
236617f55e2SKees Cook 	{-S64_MAX, -1, S64_MIN, S64_MIN+2, S64_MAX, false, false, false},
237617f55e2SKees Cook 
238617f55e2SKees Cook 	{1, S64_MIN, -S64_MAX, -S64_MAX, S64_MIN, false, true, false},
239617f55e2SKees Cook 	{S64_MIN, 1, -S64_MAX, S64_MAX, S64_MIN, false, true, false},
240617f55e2SKees Cook 	{1, S64_MAX, S64_MIN, S64_MIN+2, S64_MAX, true, false, false},
241617f55e2SKees Cook 	{S64_MAX, 1, S64_MIN, S64_MAX-1, S64_MAX, true, false, false},
242617f55e2SKees Cook 
243617f55e2SKees Cook 	{S64_MIN, S64_MIN, 0, 0, 0, true, false, true},
244617f55e2SKees Cook 	{S64_MAX, S64_MAX, -2, 0, 1, true, false, true},
245617f55e2SKees Cook 
246617f55e2SKees Cook 	{-1, -1, -2, 0, 1, false, false, false},
247617f55e2SKees Cook 	{-1, -128, -129, 127, 128, false, false, false},
248617f55e2SKees Cook 	{-128, -1, -129, -127, 128, false, false, false},
249617f55e2SKees Cook 	{0, -S64_MAX, -S64_MAX, S64_MAX, 0, false, false, false},
250617f55e2SKees Cook };
251617f55e2SKees Cook 
252617f55e2SKees Cook #define check_one_op(t, fmt, op, sym, a, b, r, of) do {			\
253d219d2a9SKees Cook 	int _a_orig = a, _a_bump = a + 1;				\
254d219d2a9SKees Cook 	int _b_orig = b, _b_bump = b + 1;				\
255617f55e2SKees Cook 	bool _of;							\
256d219d2a9SKees Cook 	t _r;								\
257617f55e2SKees Cook 									\
258617f55e2SKees Cook 	_of = check_ ## op ## _overflow(a, b, &_r);			\
259617f55e2SKees Cook 	KUNIT_EXPECT_EQ_MSG(test, _of, of,				\
260617f55e2SKees Cook 		"expected "fmt" "sym" "fmt" to%s overflow (type %s)\n",	\
261617f55e2SKees Cook 		a, b, of ? "" : " not", #t);				\
262617f55e2SKees Cook 	KUNIT_EXPECT_EQ_MSG(test, _r, r,				\
263617f55e2SKees Cook 		"expected "fmt" "sym" "fmt" == "fmt", got "fmt" (type %s)\n", \
264617f55e2SKees Cook 		a, b, r, _r, #t);					\
265d219d2a9SKees Cook 	/* Check for internal macro side-effects. */			\
266d219d2a9SKees Cook 	_of = check_ ## op ## _overflow(_a_orig++, _b_orig++, &_r);	\
267d219d2a9SKees Cook 	KUNIT_EXPECT_EQ_MSG(test, _a_orig, _a_bump, "Unexpected " #op " macro side-effect!\n"); \
268d219d2a9SKees Cook 	KUNIT_EXPECT_EQ_MSG(test, _b_orig, _b_bump, "Unexpected " #op " macro side-effect!\n"); \
269617f55e2SKees Cook } while (0)
270617f55e2SKees Cook 
271d219d2a9SKees Cook #define DEFINE_TEST_FUNC_TYPED(n, t, fmt)				\
272d219d2a9SKees Cook static void do_test_ ## n(struct kunit *test, const struct test_ ## n *p) \
273617f55e2SKees Cook {									\
274617f55e2SKees Cook 	check_one_op(t, fmt, add, "+", p->a, p->b, p->sum, p->s_of);	\
275617f55e2SKees Cook 	check_one_op(t, fmt, add, "+", p->b, p->a, p->sum, p->s_of);	\
276617f55e2SKees Cook 	check_one_op(t, fmt, sub, "-", p->a, p->b, p->diff, p->d_of);	\
277617f55e2SKees Cook 	check_one_op(t, fmt, mul, "*", p->a, p->b, p->prod, p->p_of);	\
278617f55e2SKees Cook 	check_one_op(t, fmt, mul, "*", p->b, p->a, p->prod, p->p_of);	\
279617f55e2SKees Cook }									\
280617f55e2SKees Cook 									\
281d219d2a9SKees Cook static void n ## _overflow_test(struct kunit *test) {			\
282617f55e2SKees Cook 	unsigned i;							\
283617f55e2SKees Cook 									\
28472c3ebeaSKees Cook 	SKIP_64_ON_32(__same_type(t, u64));				\
28572c3ebeaSKees Cook 	SKIP_64_ON_32(__same_type(t, s64));				\
28672c3ebeaSKees Cook 	SKIP_SIGN_MISMATCH(__same_type(n ## _tests[0].a, u32) &&	\
28772c3ebeaSKees Cook 			   __same_type(n ## _tests[0].b, u32) &&	\
28872c3ebeaSKees Cook 			   __same_type(n ## _tests[0].sum, int));	\
28972c3ebeaSKees Cook 									\
290d219d2a9SKees Cook 	for (i = 0; i < ARRAY_SIZE(n ## _tests); ++i)			\
291d219d2a9SKees Cook 		do_test_ ## n(test, &n ## _tests[i]);			\
292617f55e2SKees Cook 	kunit_info(test, "%zu %s arithmetic tests finished\n",		\
293d219d2a9SKees Cook 		ARRAY_SIZE(n ## _tests), #n);				\
294617f55e2SKees Cook }
295617f55e2SKees Cook 
296d219d2a9SKees Cook #define DEFINE_TEST_FUNC(t, fmt)					\
297d219d2a9SKees Cook 	DEFINE_TEST_FUNC_TYPED(t ## _ ## t ## __ ## t, t, fmt)
298d219d2a9SKees Cook 
299617f55e2SKees Cook DEFINE_TEST_FUNC(u8, "%d");
300617f55e2SKees Cook DEFINE_TEST_FUNC(s8, "%d");
301617f55e2SKees Cook DEFINE_TEST_FUNC(u16, "%d");
302617f55e2SKees Cook DEFINE_TEST_FUNC(s16, "%d");
303617f55e2SKees Cook DEFINE_TEST_FUNC(u32, "%u");
304617f55e2SKees Cook DEFINE_TEST_FUNC(s32, "%d");
305617f55e2SKees Cook DEFINE_TEST_FUNC(u64, "%llu");
306617f55e2SKees Cook DEFINE_TEST_FUNC(s64, "%lld");
307617f55e2SKees Cook 
308d219d2a9SKees Cook DEFINE_TEST_ARRAY_TYPED(u32, u32, u8) = {
309d219d2a9SKees Cook 	{0, 0, 0, 0, 0, false, false, false},
310d219d2a9SKees Cook 	{U8_MAX, 2, 1, U8_MAX - 2, U8_MAX - 1, true, false, true},
311d219d2a9SKees Cook 	{U8_MAX + 1, 0, 0, 0, 0, true, true, false},
312d219d2a9SKees Cook };
313d219d2a9SKees Cook DEFINE_TEST_FUNC_TYPED(u32_u32__u8, u8, "%d");
314d219d2a9SKees Cook 
315d219d2a9SKees Cook DEFINE_TEST_ARRAY_TYPED(u32, u32, int) = {
316d219d2a9SKees Cook 	{0, 0, 0, 0, 0, false, false, false},
317d219d2a9SKees Cook 	{U32_MAX, 0, -1, -1, 0, true, true, false},
318d219d2a9SKees Cook };
319d219d2a9SKees Cook DEFINE_TEST_FUNC_TYPED(u32_u32__int, int, "%d");
320d219d2a9SKees Cook 
321d219d2a9SKees Cook DEFINE_TEST_ARRAY_TYPED(u8, u8, int) = {
322d219d2a9SKees Cook 	{0, 0, 0, 0, 0, false, false, false},
323d219d2a9SKees Cook 	{U8_MAX, U8_MAX, 2 * U8_MAX, 0, U8_MAX * U8_MAX, false, false, false},
324d219d2a9SKees Cook 	{1, 2, 3, -1, 2, false, false, false},
325d219d2a9SKees Cook };
326d219d2a9SKees Cook DEFINE_TEST_FUNC_TYPED(u8_u8__int, int, "%d");
327d219d2a9SKees Cook 
328d219d2a9SKees Cook DEFINE_TEST_ARRAY_TYPED(int, int, u8) = {
329d219d2a9SKees Cook 	{0, 0, 0, 0, 0, false, false, false},
330d219d2a9SKees Cook 	{1, 2, 3, U8_MAX, 2, false, true, false},
331d219d2a9SKees Cook 	{-1, 0, U8_MAX, U8_MAX, 0, true, true, false},
332d219d2a9SKees Cook };
333d219d2a9SKees Cook DEFINE_TEST_FUNC_TYPED(int_int__u8, u8, "%d");
334d219d2a9SKees Cook 
335617f55e2SKees Cook /* Args are: value, shift, type, expected result, overflow expected */
336617f55e2SKees Cook #define TEST_ONE_SHIFT(a, s, t, expect, of)	do {			\
337617f55e2SKees Cook 	typeof(a) __a = (a);						\
338617f55e2SKees Cook 	typeof(s) __s = (s);						\
339617f55e2SKees Cook 	t __e = (expect);						\
340617f55e2SKees Cook 	t __d;								\
341617f55e2SKees Cook 	bool __of = check_shl_overflow(__a, __s, &__d);			\
342617f55e2SKees Cook 	if (__of != of) {						\
343617f55e2SKees Cook 		KUNIT_EXPECT_EQ_MSG(test, __of, of,			\
344617f55e2SKees Cook 			"expected (%s)(%s << %s) to%s overflow\n",	\
345617f55e2SKees Cook 			#t, #a, #s, of ? "" : " not");			\
346617f55e2SKees Cook 	} else if (!__of && __d != __e) {				\
347617f55e2SKees Cook 		KUNIT_EXPECT_EQ_MSG(test, __d, __e,			\
348617f55e2SKees Cook 			"expected (%s)(%s << %s) == %s\n",		\
349617f55e2SKees Cook 			#t, #a, #s, #expect);				\
350617f55e2SKees Cook 		if ((t)-1 < 0)						\
351617f55e2SKees Cook 			kunit_info(test, "got %lld\n", (s64)__d);	\
352617f55e2SKees Cook 		else							\
353617f55e2SKees Cook 			kunit_info(test, "got %llu\n", (u64)__d);	\
354617f55e2SKees Cook 	}								\
355617f55e2SKees Cook 	count++;							\
356617f55e2SKees Cook } while (0)
357617f55e2SKees Cook 
shift_sane_test(struct kunit * test)35877974225SKees Cook static void shift_sane_test(struct kunit *test)
35977974225SKees Cook {
36077974225SKees Cook 	int count = 0;
36177974225SKees Cook 
362617f55e2SKees Cook 	/* Sane shifts. */
363617f55e2SKees Cook 	TEST_ONE_SHIFT(1, 0, u8, 1 << 0, false);
364617f55e2SKees Cook 	TEST_ONE_SHIFT(1, 4, u8, 1 << 4, false);
365617f55e2SKees Cook 	TEST_ONE_SHIFT(1, 7, u8, 1 << 7, false);
366617f55e2SKees Cook 	TEST_ONE_SHIFT(0xF, 4, u8, 0xF << 4, false);
367617f55e2SKees Cook 	TEST_ONE_SHIFT(1, 0, u16, 1 << 0, false);
368617f55e2SKees Cook 	TEST_ONE_SHIFT(1, 10, u16, 1 << 10, false);
369617f55e2SKees Cook 	TEST_ONE_SHIFT(1, 15, u16, 1 << 15, false);
370617f55e2SKees Cook 	TEST_ONE_SHIFT(0xFF, 8, u16, 0xFF << 8, false);
371617f55e2SKees Cook 	TEST_ONE_SHIFT(1, 0, int, 1 << 0, false);
372617f55e2SKees Cook 	TEST_ONE_SHIFT(1, 16, int, 1 << 16, false);
373617f55e2SKees Cook 	TEST_ONE_SHIFT(1, 30, int, 1 << 30, false);
374617f55e2SKees Cook 	TEST_ONE_SHIFT(1, 0, s32, 1 << 0, false);
375617f55e2SKees Cook 	TEST_ONE_SHIFT(1, 16, s32, 1 << 16, false);
376617f55e2SKees Cook 	TEST_ONE_SHIFT(1, 30, s32, 1 << 30, false);
377617f55e2SKees Cook 	TEST_ONE_SHIFT(1, 0, unsigned int, 1U << 0, false);
378617f55e2SKees Cook 	TEST_ONE_SHIFT(1, 20, unsigned int, 1U << 20, false);
379617f55e2SKees Cook 	TEST_ONE_SHIFT(1, 31, unsigned int, 1U << 31, false);
380617f55e2SKees Cook 	TEST_ONE_SHIFT(0xFFFFU, 16, unsigned int, 0xFFFFU << 16, false);
381617f55e2SKees Cook 	TEST_ONE_SHIFT(1, 0, u32, 1U << 0, false);
382617f55e2SKees Cook 	TEST_ONE_SHIFT(1, 20, u32, 1U << 20, false);
383617f55e2SKees Cook 	TEST_ONE_SHIFT(1, 31, u32, 1U << 31, false);
384617f55e2SKees Cook 	TEST_ONE_SHIFT(0xFFFFU, 16, u32, 0xFFFFU << 16, false);
385617f55e2SKees Cook 	TEST_ONE_SHIFT(1, 0, u64, 1ULL << 0, false);
386617f55e2SKees Cook 	TEST_ONE_SHIFT(1, 40, u64, 1ULL << 40, false);
387617f55e2SKees Cook 	TEST_ONE_SHIFT(1, 63, u64, 1ULL << 63, false);
388617f55e2SKees Cook 	TEST_ONE_SHIFT(0xFFFFFFFFULL, 32, u64, 0xFFFFFFFFULL << 32, false);
389617f55e2SKees Cook 
390617f55e2SKees Cook 	/* Sane shift: start and end with 0, without a too-wide shift. */
391617f55e2SKees Cook 	TEST_ONE_SHIFT(0, 7, u8, 0, false);
392617f55e2SKees Cook 	TEST_ONE_SHIFT(0, 15, u16, 0, false);
393617f55e2SKees Cook 	TEST_ONE_SHIFT(0, 31, unsigned int, 0, false);
394617f55e2SKees Cook 	TEST_ONE_SHIFT(0, 31, u32, 0, false);
395617f55e2SKees Cook 	TEST_ONE_SHIFT(0, 63, u64, 0, false);
396617f55e2SKees Cook 
397617f55e2SKees Cook 	/* Sane shift: start and end with 0, without reaching signed bit. */
398617f55e2SKees Cook 	TEST_ONE_SHIFT(0, 6, s8, 0, false);
399617f55e2SKees Cook 	TEST_ONE_SHIFT(0, 14, s16, 0, false);
400617f55e2SKees Cook 	TEST_ONE_SHIFT(0, 30, int, 0, false);
401617f55e2SKees Cook 	TEST_ONE_SHIFT(0, 30, s32, 0, false);
402617f55e2SKees Cook 	TEST_ONE_SHIFT(0, 62, s64, 0, false);
403617f55e2SKees Cook 
40477974225SKees Cook 	kunit_info(test, "%d sane shift tests finished\n", count);
40577974225SKees Cook }
40677974225SKees Cook 
shift_overflow_test(struct kunit * test)40777974225SKees Cook static void shift_overflow_test(struct kunit *test)
40877974225SKees Cook {
40977974225SKees Cook 	int count = 0;
41077974225SKees Cook 
411617f55e2SKees Cook 	/* Overflow: shifted the bit off the end. */
412617f55e2SKees Cook 	TEST_ONE_SHIFT(1, 8, u8, 0, true);
413617f55e2SKees Cook 	TEST_ONE_SHIFT(1, 16, u16, 0, true);
414617f55e2SKees Cook 	TEST_ONE_SHIFT(1, 32, unsigned int, 0, true);
415617f55e2SKees Cook 	TEST_ONE_SHIFT(1, 32, u32, 0, true);
416617f55e2SKees Cook 	TEST_ONE_SHIFT(1, 64, u64, 0, true);
417617f55e2SKees Cook 
418617f55e2SKees Cook 	/* Overflow: shifted into the signed bit. */
419617f55e2SKees Cook 	TEST_ONE_SHIFT(1, 7, s8, 0, true);
420617f55e2SKees Cook 	TEST_ONE_SHIFT(1, 15, s16, 0, true);
421617f55e2SKees Cook 	TEST_ONE_SHIFT(1, 31, int, 0, true);
422617f55e2SKees Cook 	TEST_ONE_SHIFT(1, 31, s32, 0, true);
423617f55e2SKees Cook 	TEST_ONE_SHIFT(1, 63, s64, 0, true);
424617f55e2SKees Cook 
425617f55e2SKees Cook 	/* Overflow: high bit falls off unsigned types. */
426617f55e2SKees Cook 	/* 10010110 */
427617f55e2SKees Cook 	TEST_ONE_SHIFT(150, 1, u8, 0, true);
428617f55e2SKees Cook 	/* 1000100010010110 */
429617f55e2SKees Cook 	TEST_ONE_SHIFT(34966, 1, u16, 0, true);
430617f55e2SKees Cook 	/* 10000100000010001000100010010110 */
431617f55e2SKees Cook 	TEST_ONE_SHIFT(2215151766U, 1, u32, 0, true);
432617f55e2SKees Cook 	TEST_ONE_SHIFT(2215151766U, 1, unsigned int, 0, true);
433617f55e2SKees Cook 	/* 1000001000010000010000000100000010000100000010001000100010010110 */
434617f55e2SKees Cook 	TEST_ONE_SHIFT(9372061470395238550ULL, 1, u64, 0, true);
435617f55e2SKees Cook 
436617f55e2SKees Cook 	/* Overflow: bit shifted into signed bit on signed types. */
437617f55e2SKees Cook 	/* 01001011 */
438617f55e2SKees Cook 	TEST_ONE_SHIFT(75, 1, s8, 0, true);
439617f55e2SKees Cook 	/* 0100010001001011 */
440617f55e2SKees Cook 	TEST_ONE_SHIFT(17483, 1, s16, 0, true);
441617f55e2SKees Cook 	/* 01000010000001000100010001001011 */
442617f55e2SKees Cook 	TEST_ONE_SHIFT(1107575883, 1, s32, 0, true);
443617f55e2SKees Cook 	TEST_ONE_SHIFT(1107575883, 1, int, 0, true);
444617f55e2SKees Cook 	/* 0100000100001000001000000010000001000010000001000100010001001011 */
445617f55e2SKees Cook 	TEST_ONE_SHIFT(4686030735197619275LL, 1, s64, 0, true);
446617f55e2SKees Cook 
447617f55e2SKees Cook 	/* Overflow: bit shifted past signed bit on signed types. */
448617f55e2SKees Cook 	/* 01001011 */
449617f55e2SKees Cook 	TEST_ONE_SHIFT(75, 2, s8, 0, true);
450617f55e2SKees Cook 	/* 0100010001001011 */
451617f55e2SKees Cook 	TEST_ONE_SHIFT(17483, 2, s16, 0, true);
452617f55e2SKees Cook 	/* 01000010000001000100010001001011 */
453617f55e2SKees Cook 	TEST_ONE_SHIFT(1107575883, 2, s32, 0, true);
454617f55e2SKees Cook 	TEST_ONE_SHIFT(1107575883, 2, int, 0, true);
455617f55e2SKees Cook 	/* 0100000100001000001000000010000001000010000001000100010001001011 */
456617f55e2SKees Cook 	TEST_ONE_SHIFT(4686030735197619275LL, 2, s64, 0, true);
457617f55e2SKees Cook 
45877974225SKees Cook 	kunit_info(test, "%d overflow shift tests finished\n", count);
45977974225SKees Cook }
46077974225SKees Cook 
shift_truncate_test(struct kunit * test)46177974225SKees Cook static void shift_truncate_test(struct kunit *test)
46277974225SKees Cook {
46377974225SKees Cook 	int count = 0;
46477974225SKees Cook 
465617f55e2SKees Cook 	/* Overflow: values larger than destination type. */
466617f55e2SKees Cook 	TEST_ONE_SHIFT(0x100, 0, u8, 0, true);
467617f55e2SKees Cook 	TEST_ONE_SHIFT(0xFF, 0, s8, 0, true);
468617f55e2SKees Cook 	TEST_ONE_SHIFT(0x10000U, 0, u16, 0, true);
469617f55e2SKees Cook 	TEST_ONE_SHIFT(0xFFFFU, 0, s16, 0, true);
470617f55e2SKees Cook 	TEST_ONE_SHIFT(0x100000000ULL, 0, u32, 0, true);
471617f55e2SKees Cook 	TEST_ONE_SHIFT(0x100000000ULL, 0, unsigned int, 0, true);
472617f55e2SKees Cook 	TEST_ONE_SHIFT(0xFFFFFFFFUL, 0, s32, 0, true);
473617f55e2SKees Cook 	TEST_ONE_SHIFT(0xFFFFFFFFUL, 0, int, 0, true);
474617f55e2SKees Cook 	TEST_ONE_SHIFT(0xFFFFFFFFFFFFFFFFULL, 0, s64, 0, true);
475617f55e2SKees Cook 
47677974225SKees Cook 	/* Overflow: shifted at or beyond entire type's bit width. */
47777974225SKees Cook 	TEST_ONE_SHIFT(0, 8, u8, 0, true);
47877974225SKees Cook 	TEST_ONE_SHIFT(0, 9, u8, 0, true);
47977974225SKees Cook 	TEST_ONE_SHIFT(0, 8, s8, 0, true);
48077974225SKees Cook 	TEST_ONE_SHIFT(0, 9, s8, 0, true);
48177974225SKees Cook 	TEST_ONE_SHIFT(0, 16, u16, 0, true);
48277974225SKees Cook 	TEST_ONE_SHIFT(0, 17, u16, 0, true);
48377974225SKees Cook 	TEST_ONE_SHIFT(0, 16, s16, 0, true);
48477974225SKees Cook 	TEST_ONE_SHIFT(0, 17, s16, 0, true);
48577974225SKees Cook 	TEST_ONE_SHIFT(0, 32, u32, 0, true);
48677974225SKees Cook 	TEST_ONE_SHIFT(0, 33, u32, 0, true);
48777974225SKees Cook 	TEST_ONE_SHIFT(0, 32, int, 0, true);
48877974225SKees Cook 	TEST_ONE_SHIFT(0, 33, int, 0, true);
48977974225SKees Cook 	TEST_ONE_SHIFT(0, 32, s32, 0, true);
49077974225SKees Cook 	TEST_ONE_SHIFT(0, 33, s32, 0, true);
49177974225SKees Cook 	TEST_ONE_SHIFT(0, 64, u64, 0, true);
49277974225SKees Cook 	TEST_ONE_SHIFT(0, 65, u64, 0, true);
49377974225SKees Cook 	TEST_ONE_SHIFT(0, 64, s64, 0, true);
49477974225SKees Cook 	TEST_ONE_SHIFT(0, 65, s64, 0, true);
49577974225SKees Cook 
49677974225SKees Cook 	kunit_info(test, "%d truncate shift tests finished\n", count);
49777974225SKees Cook }
49877974225SKees Cook 
shift_nonsense_test(struct kunit * test)49977974225SKees Cook static void shift_nonsense_test(struct kunit *test)
50077974225SKees Cook {
50177974225SKees Cook 	int count = 0;
50277974225SKees Cook 
503617f55e2SKees Cook 	/* Nonsense: negative initial value. */
504617f55e2SKees Cook 	TEST_ONE_SHIFT(-1, 0, s8, 0, true);
505617f55e2SKees Cook 	TEST_ONE_SHIFT(-1, 0, u8, 0, true);
506617f55e2SKees Cook 	TEST_ONE_SHIFT(-5, 0, s16, 0, true);
507617f55e2SKees Cook 	TEST_ONE_SHIFT(-5, 0, u16, 0, true);
508617f55e2SKees Cook 	TEST_ONE_SHIFT(-10, 0, int, 0, true);
509617f55e2SKees Cook 	TEST_ONE_SHIFT(-10, 0, unsigned int, 0, true);
510617f55e2SKees Cook 	TEST_ONE_SHIFT(-100, 0, s32, 0, true);
511617f55e2SKees Cook 	TEST_ONE_SHIFT(-100, 0, u32, 0, true);
512617f55e2SKees Cook 	TEST_ONE_SHIFT(-10000, 0, s64, 0, true);
513617f55e2SKees Cook 	TEST_ONE_SHIFT(-10000, 0, u64, 0, true);
514617f55e2SKees Cook 
515617f55e2SKees Cook 	/* Nonsense: negative shift values. */
516617f55e2SKees Cook 	TEST_ONE_SHIFT(0, -5, s8, 0, true);
517617f55e2SKees Cook 	TEST_ONE_SHIFT(0, -5, u8, 0, true);
518617f55e2SKees Cook 	TEST_ONE_SHIFT(0, -10, s16, 0, true);
519617f55e2SKees Cook 	TEST_ONE_SHIFT(0, -10, u16, 0, true);
520617f55e2SKees Cook 	TEST_ONE_SHIFT(0, -15, int, 0, true);
521617f55e2SKees Cook 	TEST_ONE_SHIFT(0, -15, unsigned int, 0, true);
522617f55e2SKees Cook 	TEST_ONE_SHIFT(0, -20, s32, 0, true);
523617f55e2SKees Cook 	TEST_ONE_SHIFT(0, -20, u32, 0, true);
524617f55e2SKees Cook 	TEST_ONE_SHIFT(0, -30, s64, 0, true);
525617f55e2SKees Cook 	TEST_ONE_SHIFT(0, -30, u64, 0, true);
526617f55e2SKees Cook 
527617f55e2SKees Cook 	/*
528617f55e2SKees Cook 	 * Corner case: for unsigned types, we fail when we've shifted
529617f55e2SKees Cook 	 * through the entire width of bits. For signed types, we might
530617f55e2SKees Cook 	 * want to match this behavior, but that would mean noticing if
531617f55e2SKees Cook 	 * we shift through all but the signed bit, and this is not
532617f55e2SKees Cook 	 * currently detected (but we'll notice an overflow into the
533617f55e2SKees Cook 	 * signed bit). So, for now, we will test this condition but
534617f55e2SKees Cook 	 * mark it as not expected to overflow.
535617f55e2SKees Cook 	 */
536617f55e2SKees Cook 	TEST_ONE_SHIFT(0, 7, s8, 0, false);
537617f55e2SKees Cook 	TEST_ONE_SHIFT(0, 15, s16, 0, false);
538617f55e2SKees Cook 	TEST_ONE_SHIFT(0, 31, int, 0, false);
539617f55e2SKees Cook 	TEST_ONE_SHIFT(0, 31, s32, 0, false);
540617f55e2SKees Cook 	TEST_ONE_SHIFT(0, 63, s64, 0, false);
541617f55e2SKees Cook 
54277974225SKees Cook 	kunit_info(test, "%d nonsense shift tests finished\n", count);
543617f55e2SKees Cook }
54477974225SKees Cook #undef TEST_ONE_SHIFT
545617f55e2SKees Cook 
546617f55e2SKees Cook /*
547617f55e2SKees Cook  * Deal with the various forms of allocator arguments. See comments above
548617f55e2SKees Cook  * the DEFINE_TEST_ALLOC() instances for mapping of the "bits".
549617f55e2SKees Cook  */
550617f55e2SKees Cook #define alloc_GFP		 (GFP_KERNEL | __GFP_NOWARN)
551617f55e2SKees Cook #define alloc010(alloc, arg, sz) alloc(sz, alloc_GFP)
552617f55e2SKees Cook #define alloc011(alloc, arg, sz) alloc(sz, alloc_GFP, NUMA_NO_NODE)
553617f55e2SKees Cook #define alloc000(alloc, arg, sz) alloc(sz)
554617f55e2SKees Cook #define alloc001(alloc, arg, sz) alloc(sz, NUMA_NO_NODE)
555617f55e2SKees Cook #define alloc110(alloc, arg, sz) alloc(arg, sz, alloc_GFP)
556617f55e2SKees Cook #define free0(free, arg, ptr)	 free(ptr)
557617f55e2SKees Cook #define free1(free, arg, ptr)	 free(arg, ptr)
558617f55e2SKees Cook 
559617f55e2SKees Cook /* Wrap around to 16K */
560617f55e2SKees Cook #define TEST_SIZE		(5 * 4096)
561617f55e2SKees Cook 
562617f55e2SKees Cook #define DEFINE_TEST_ALLOC(func, free_func, want_arg, want_gfp, want_node)\
563617f55e2SKees Cook static void test_ ## func (struct kunit *test, void *arg)		\
564617f55e2SKees Cook {									\
565617f55e2SKees Cook 	volatile size_t a = TEST_SIZE;					\
566617f55e2SKees Cook 	volatile size_t b = (SIZE_MAX / TEST_SIZE) + 1;			\
567617f55e2SKees Cook 	void *ptr;							\
568617f55e2SKees Cook 									\
569617f55e2SKees Cook 	/* Tiny allocation test. */					\
570617f55e2SKees Cook 	ptr = alloc ## want_arg ## want_gfp ## want_node (func, arg, 1);\
571617f55e2SKees Cook 	KUNIT_ASSERT_NOT_ERR_OR_NULL_MSG(test, ptr,			\
572617f55e2SKees Cook 			    #func " failed regular allocation?!\n");	\
573617f55e2SKees Cook 	free ## want_arg (free_func, arg, ptr);				\
574617f55e2SKees Cook 									\
575617f55e2SKees Cook 	/* Wrapped allocation test. */					\
576617f55e2SKees Cook 	ptr = alloc ## want_arg ## want_gfp ## want_node (func, arg,	\
577617f55e2SKees Cook 							  a * b);	\
578617f55e2SKees Cook 	KUNIT_ASSERT_NOT_ERR_OR_NULL_MSG(test, ptr,			\
579617f55e2SKees Cook 			    #func " unexpectedly failed bad wrapping?!\n"); \
580617f55e2SKees Cook 	free ## want_arg (free_func, arg, ptr);				\
581617f55e2SKees Cook 									\
582617f55e2SKees Cook 	/* Saturated allocation test. */				\
583617f55e2SKees Cook 	ptr = alloc ## want_arg ## want_gfp ## want_node (func, arg,	\
584617f55e2SKees Cook 						   array_size(a, b));	\
585617f55e2SKees Cook 	if (ptr) {							\
586617f55e2SKees Cook 		KUNIT_FAIL(test, #func " missed saturation!\n");	\
587617f55e2SKees Cook 		free ## want_arg (free_func, arg, ptr);			\
588617f55e2SKees Cook 	}								\
589617f55e2SKees Cook }
590617f55e2SKees Cook 
591617f55e2SKees Cook /*
592617f55e2SKees Cook  * Allocator uses a trailing node argument --------+  (e.g. kmalloc_node())
593617f55e2SKees Cook  * Allocator uses the gfp_t argument -----------+  |  (e.g. kmalloc())
594617f55e2SKees Cook  * Allocator uses a special leading argument +  |  |  (e.g. devm_kmalloc())
595617f55e2SKees Cook  *                                           |  |  |
596617f55e2SKees Cook  */
597617f55e2SKees Cook DEFINE_TEST_ALLOC(kmalloc,	 kfree,	     0, 1, 0);
598617f55e2SKees Cook DEFINE_TEST_ALLOC(kmalloc_node,	 kfree,	     0, 1, 1);
599617f55e2SKees Cook DEFINE_TEST_ALLOC(kzalloc,	 kfree,	     0, 1, 0);
600617f55e2SKees Cook DEFINE_TEST_ALLOC(kzalloc_node,  kfree,	     0, 1, 1);
601617f55e2SKees Cook DEFINE_TEST_ALLOC(__vmalloc,	 vfree,	     0, 1, 0);
602617f55e2SKees Cook DEFINE_TEST_ALLOC(kvmalloc,	 kvfree,     0, 1, 0);
603617f55e2SKees Cook DEFINE_TEST_ALLOC(kvmalloc_node, kvfree,     0, 1, 1);
604617f55e2SKees Cook DEFINE_TEST_ALLOC(kvzalloc,	 kvfree,     0, 1, 0);
605617f55e2SKees Cook DEFINE_TEST_ALLOC(kvzalloc_node, kvfree,     0, 1, 1);
606617f55e2SKees Cook DEFINE_TEST_ALLOC(devm_kmalloc,  devm_kfree, 1, 1, 0);
607617f55e2SKees Cook DEFINE_TEST_ALLOC(devm_kzalloc,  devm_kfree, 1, 1, 0);
608617f55e2SKees Cook 
overflow_allocation_test(struct kunit * test)609617f55e2SKees Cook static void overflow_allocation_test(struct kunit *test)
610617f55e2SKees Cook {
611617f55e2SKees Cook 	const char device_name[] = "overflow-test";
612617f55e2SKees Cook 	struct device *dev;
613617f55e2SKees Cook 	int count = 0;
614617f55e2SKees Cook 
615617f55e2SKees Cook #define check_allocation_overflow(alloc)	do {	\
616617f55e2SKees Cook 	count++;					\
617617f55e2SKees Cook 	test_ ## alloc(test, dev);			\
618617f55e2SKees Cook } while (0)
619617f55e2SKees Cook 
620617f55e2SKees Cook 	/* Create dummy device for devm_kmalloc()-family tests. */
621617f55e2SKees Cook 	dev = root_device_register(device_name);
622617f55e2SKees Cook 	KUNIT_ASSERT_FALSE_MSG(test, IS_ERR(dev),
623617f55e2SKees Cook 			       "Cannot register test device\n");
624617f55e2SKees Cook 
625617f55e2SKees Cook 	check_allocation_overflow(kmalloc);
626617f55e2SKees Cook 	check_allocation_overflow(kmalloc_node);
627617f55e2SKees Cook 	check_allocation_overflow(kzalloc);
628617f55e2SKees Cook 	check_allocation_overflow(kzalloc_node);
629617f55e2SKees Cook 	check_allocation_overflow(__vmalloc);
630617f55e2SKees Cook 	check_allocation_overflow(kvmalloc);
631617f55e2SKees Cook 	check_allocation_overflow(kvmalloc_node);
632617f55e2SKees Cook 	check_allocation_overflow(kvzalloc);
633617f55e2SKees Cook 	check_allocation_overflow(kvzalloc_node);
634617f55e2SKees Cook 	check_allocation_overflow(devm_kmalloc);
635617f55e2SKees Cook 	check_allocation_overflow(devm_kzalloc);
636617f55e2SKees Cook 
637617f55e2SKees Cook 	device_unregister(dev);
638617f55e2SKees Cook 
639617f55e2SKees Cook 	kunit_info(test, "%d allocation overflow tests finished\n", count);
640617f55e2SKees Cook #undef check_allocation_overflow
641617f55e2SKees Cook }
642617f55e2SKees Cook 
643617f55e2SKees Cook struct __test_flex_array {
644617f55e2SKees Cook 	unsigned long flags;
645617f55e2SKees Cook 	size_t count;
646617f55e2SKees Cook 	unsigned long data[];
647617f55e2SKees Cook };
648617f55e2SKees Cook 
overflow_size_helpers_test(struct kunit * test)649617f55e2SKees Cook static void overflow_size_helpers_test(struct kunit *test)
650617f55e2SKees Cook {
651617f55e2SKees Cook 	/* Make sure struct_size() can be used in a constant expression. */
652*d67790ddSKees Cook 	u8 ce_array[struct_size_t(struct __test_flex_array, data, 55)];
653617f55e2SKees Cook 	struct __test_flex_array *obj;
654617f55e2SKees Cook 	int count = 0;
655617f55e2SKees Cook 	int var;
656617f55e2SKees Cook 	volatile int unconst = 0;
657617f55e2SKees Cook 
658617f55e2SKees Cook 	/* Verify constant expression against runtime version. */
659617f55e2SKees Cook 	var = 55;
660617f55e2SKees Cook 	OPTIMIZER_HIDE_VAR(var);
661617f55e2SKees Cook 	KUNIT_EXPECT_EQ(test, sizeof(ce_array), struct_size(obj, data, var));
662617f55e2SKees Cook 
663617f55e2SKees Cook #define check_one_size_helper(expected, func, args...)	do {	\
664617f55e2SKees Cook 	size_t _r = func(args);					\
665617f55e2SKees Cook 	KUNIT_EXPECT_EQ_MSG(test, _r, expected,			\
666617f55e2SKees Cook 		"expected " #func "(" #args ") to return %zu but got %zu instead\n", \
667617f55e2SKees Cook 		(size_t)(expected), _r);			\
668617f55e2SKees Cook 	count++;						\
669617f55e2SKees Cook } while (0)
670617f55e2SKees Cook 
671617f55e2SKees Cook 	var = 4;
672617f55e2SKees Cook 	check_one_size_helper(20,	size_mul, var++, 5);
673617f55e2SKees Cook 	check_one_size_helper(20,	size_mul, 4, var++);
674617f55e2SKees Cook 	check_one_size_helper(0,	size_mul, 0, 3);
675617f55e2SKees Cook 	check_one_size_helper(0,	size_mul, 3, 0);
676617f55e2SKees Cook 	check_one_size_helper(6,	size_mul, 2, 3);
677617f55e2SKees Cook 	check_one_size_helper(SIZE_MAX,	size_mul, SIZE_MAX,  1);
678617f55e2SKees Cook 	check_one_size_helper(SIZE_MAX,	size_mul, SIZE_MAX,  3);
679617f55e2SKees Cook 	check_one_size_helper(SIZE_MAX,	size_mul, SIZE_MAX, -3);
680617f55e2SKees Cook 
681617f55e2SKees Cook 	var = 4;
682617f55e2SKees Cook 	check_one_size_helper(9,	size_add, var++, 5);
683617f55e2SKees Cook 	check_one_size_helper(9,	size_add, 4, var++);
684617f55e2SKees Cook 	check_one_size_helper(9,	size_add, 9, 0);
685617f55e2SKees Cook 	check_one_size_helper(9,	size_add, 0, 9);
686617f55e2SKees Cook 	check_one_size_helper(5,	size_add, 2, 3);
687617f55e2SKees Cook 	check_one_size_helper(SIZE_MAX, size_add, SIZE_MAX,  1);
688617f55e2SKees Cook 	check_one_size_helper(SIZE_MAX, size_add, SIZE_MAX,  3);
689617f55e2SKees Cook 	check_one_size_helper(SIZE_MAX, size_add, SIZE_MAX, -3);
690617f55e2SKees Cook 
691617f55e2SKees Cook 	var = 4;
692617f55e2SKees Cook 	check_one_size_helper(1,	size_sub, var--, 3);
693617f55e2SKees Cook 	check_one_size_helper(1,	size_sub, 4, var--);
694617f55e2SKees Cook 	check_one_size_helper(1,	size_sub, 3, 2);
695617f55e2SKees Cook 	check_one_size_helper(9,	size_sub, 9, 0);
696617f55e2SKees Cook 	check_one_size_helper(SIZE_MAX, size_sub, 9, -3);
697617f55e2SKees Cook 	check_one_size_helper(SIZE_MAX, size_sub, 0, 9);
698617f55e2SKees Cook 	check_one_size_helper(SIZE_MAX, size_sub, 2, 3);
699617f55e2SKees Cook 	check_one_size_helper(SIZE_MAX, size_sub, SIZE_MAX,  0);
700617f55e2SKees Cook 	check_one_size_helper(SIZE_MAX, size_sub, SIZE_MAX, 10);
701617f55e2SKees Cook 	check_one_size_helper(SIZE_MAX, size_sub, 0,  SIZE_MAX);
702617f55e2SKees Cook 	check_one_size_helper(SIZE_MAX, size_sub, 14, SIZE_MAX);
703617f55e2SKees Cook 	check_one_size_helper(SIZE_MAX - 2, size_sub, SIZE_MAX - 1,  1);
704617f55e2SKees Cook 	check_one_size_helper(SIZE_MAX - 4, size_sub, SIZE_MAX - 1,  3);
705617f55e2SKees Cook 	check_one_size_helper(1,		size_sub, SIZE_MAX - 1, -3);
706617f55e2SKees Cook 
707617f55e2SKees Cook 	var = 4;
708617f55e2SKees Cook 	check_one_size_helper(4 * sizeof(*obj->data),
709617f55e2SKees Cook 			      flex_array_size, obj, data, var++);
710617f55e2SKees Cook 	check_one_size_helper(5 * sizeof(*obj->data),
711617f55e2SKees Cook 			      flex_array_size, obj, data, var++);
712617f55e2SKees Cook 	check_one_size_helper(0, flex_array_size, obj, data, 0 + unconst);
713617f55e2SKees Cook 	check_one_size_helper(sizeof(*obj->data),
714617f55e2SKees Cook 			      flex_array_size, obj, data, 1 + unconst);
715617f55e2SKees Cook 	check_one_size_helper(7 * sizeof(*obj->data),
716617f55e2SKees Cook 			      flex_array_size, obj, data, 7 + unconst);
717617f55e2SKees Cook 	check_one_size_helper(SIZE_MAX,
718617f55e2SKees Cook 			      flex_array_size, obj, data, -1 + unconst);
719617f55e2SKees Cook 	check_one_size_helper(SIZE_MAX,
720617f55e2SKees Cook 			      flex_array_size, obj, data, SIZE_MAX - 4 + unconst);
721617f55e2SKees Cook 
722617f55e2SKees Cook 	var = 4;
723617f55e2SKees Cook 	check_one_size_helper(sizeof(*obj) + (4 * sizeof(*obj->data)),
724617f55e2SKees Cook 			      struct_size, obj, data, var++);
725617f55e2SKees Cook 	check_one_size_helper(sizeof(*obj) + (5 * sizeof(*obj->data)),
726617f55e2SKees Cook 			      struct_size, obj, data, var++);
727617f55e2SKees Cook 	check_one_size_helper(sizeof(*obj), struct_size, obj, data, 0 + unconst);
728617f55e2SKees Cook 	check_one_size_helper(sizeof(*obj) + sizeof(*obj->data),
729617f55e2SKees Cook 			      struct_size, obj, data, 1 + unconst);
730617f55e2SKees Cook 	check_one_size_helper(SIZE_MAX,
731617f55e2SKees Cook 			      struct_size, obj, data, -3 + unconst);
732617f55e2SKees Cook 	check_one_size_helper(SIZE_MAX,
733617f55e2SKees Cook 			      struct_size, obj, data, SIZE_MAX - 3 + unconst);
734617f55e2SKees Cook 
735617f55e2SKees Cook 	kunit_info(test, "%d overflow size helper tests finished\n", count);
736617f55e2SKees Cook #undef check_one_size_helper
737617f55e2SKees Cook }
738617f55e2SKees Cook 
overflows_type_test(struct kunit * test)7394b21d25bSKees Cook static void overflows_type_test(struct kunit *test)
7404b21d25bSKees Cook {
7414b21d25bSKees Cook 	int count = 0;
7424b21d25bSKees Cook 	unsigned int var;
7434b21d25bSKees Cook 
7444b21d25bSKees Cook #define __TEST_OVERFLOWS_TYPE(func, arg1, arg2, of)	do {		\
7454b21d25bSKees Cook 	bool __of = func(arg1, arg2);					\
7464b21d25bSKees Cook 	KUNIT_EXPECT_EQ_MSG(test, __of, of,				\
7474b21d25bSKees Cook 		"expected " #func "(" #arg1 ", " #arg2 " to%s overflow\n",\
7484b21d25bSKees Cook 		of ? "" : " not");					\
7494b21d25bSKees Cook 	count++;							\
7504b21d25bSKees Cook } while (0)
7514b21d25bSKees Cook 
7524b21d25bSKees Cook /* Args are: first type, second type, value, overflow expected */
7534b21d25bSKees Cook #define TEST_OVERFLOWS_TYPE(__t1, __t2, v, of) do {			\
7544b21d25bSKees Cook 	__t1 t1 = (v);							\
7554b21d25bSKees Cook 	__t2 t2;							\
7564b21d25bSKees Cook 	__TEST_OVERFLOWS_TYPE(__overflows_type, t1, t2, of);		\
7574b21d25bSKees Cook 	__TEST_OVERFLOWS_TYPE(__overflows_type, t1, __t2, of);		\
7584b21d25bSKees Cook 	__TEST_OVERFLOWS_TYPE(__overflows_type_constexpr, t1, t2, of);	\
7594b21d25bSKees Cook 	__TEST_OVERFLOWS_TYPE(__overflows_type_constexpr, t1, __t2, of);\
7604b21d25bSKees Cook } while (0)
7614b21d25bSKees Cook 
7624b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u8, u8, U8_MAX, false);
7634b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u8, u16, U8_MAX, false);
7644b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u8, s8, U8_MAX, true);
7654b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u8, s8, S8_MAX, false);
7664b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u8, s8, (u8)S8_MAX + 1, true);
7674b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u8, s16, U8_MAX, false);
7684b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s8, u8, S8_MAX, false);
7694b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s8, u8, -1, true);
7704b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s8, u8, S8_MIN, true);
7714b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s8, u16, S8_MAX, false);
7724b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s8, u16, -1, true);
7734b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s8, u16, S8_MIN, true);
7744b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s8, u32, S8_MAX, false);
7754b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s8, u32, -1, true);
7764b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s8, u32, S8_MIN, true);
7774b21d25bSKees Cook #if BITS_PER_LONG == 64
7784b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s8, u64, S8_MAX, false);
7794b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s8, u64, -1, true);
7804b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s8, u64, S8_MIN, true);
7814b21d25bSKees Cook #endif
7824b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s8, s8, S8_MAX, false);
7834b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s8, s8, S8_MIN, false);
7844b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s8, s16, S8_MAX, false);
7854b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s8, s16, S8_MIN, false);
7864b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u16, u8, U8_MAX, false);
7874b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u16, u8, (u16)U8_MAX + 1, true);
7884b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u16, u8, U16_MAX, true);
7894b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u16, s8, S8_MAX, false);
7904b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u16, s8, (u16)S8_MAX + 1, true);
7914b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u16, s8, U16_MAX, true);
7924b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u16, s16, S16_MAX, false);
7934b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u16, s16, (u16)S16_MAX + 1, true);
7944b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u16, s16, U16_MAX, true);
7954b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u16, u32, U16_MAX, false);
7964b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u16, s32, U16_MAX, false);
7974b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s16, u8, U8_MAX, false);
7984b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s16, u8, (s16)U8_MAX + 1, true);
7994b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s16, u8, -1, true);
8004b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s16, u8, S16_MIN, true);
8014b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s16, u16, S16_MAX, false);
8024b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s16, u16, -1, true);
8034b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s16, u16, S16_MIN, true);
8044b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s16, u32, S16_MAX, false);
8054b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s16, u32, -1, true);
8064b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s16, u32, S16_MIN, true);
8074b21d25bSKees Cook #if BITS_PER_LONG == 64
8084b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s16, u64, S16_MAX, false);
8094b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s16, u64, -1, true);
8104b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s16, u64, S16_MIN, true);
8114b21d25bSKees Cook #endif
8124b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s16, s8, S8_MAX, false);
8134b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s16, s8, S8_MIN, false);
8144b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s16, s8, (s16)S8_MAX + 1, true);
8154b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s16, s8, (s16)S8_MIN - 1, true);
8164b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s16, s8, S16_MAX, true);
8174b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s16, s8, S16_MIN, true);
8184b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s16, s16, S16_MAX, false);
8194b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s16, s16, S16_MIN, false);
8204b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s16, s32, S16_MAX, false);
8214b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s16, s32, S16_MIN, false);
8224b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u32, u8, U8_MAX, false);
8234b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u32, u8, (u32)U8_MAX + 1, true);
8244b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u32, u8, U32_MAX, true);
8254b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u32, s8, S8_MAX, false);
8264b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u32, s8, (u32)S8_MAX + 1, true);
8274b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u32, s8, U32_MAX, true);
8284b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u32, u16, U16_MAX, false);
8294b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u32, u16, U16_MAX + 1, true);
8304b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u32, u16, U32_MAX, true);
8314b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u32, s16, S16_MAX, false);
8324b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u32, s16, (u32)S16_MAX + 1, true);
8334b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u32, s16, U32_MAX, true);
8344b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u32, u32, U32_MAX, false);
8354b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u32, s32, S32_MAX, false);
8364b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u32, s32, U32_MAX, true);
8374b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u32, s32, (u32)S32_MAX + 1, true);
8384b21d25bSKees Cook #if BITS_PER_LONG == 64
8394b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u32, u64, U32_MAX, false);
8404b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u32, s64, U32_MAX, false);
8414b21d25bSKees Cook #endif
8424b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s32, u8, U8_MAX, false);
8434b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s32, u8, (s32)U8_MAX + 1, true);
8444b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s32, u16, S32_MAX, true);
8454b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s32, u8, -1, true);
8464b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s32, u8, S32_MIN, true);
8474b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s32, u16, U16_MAX, false);
8484b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s32, u16, (s32)U16_MAX + 1, true);
8494b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s32, u16, S32_MAX, true);
8504b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s32, u16, -1, true);
8514b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s32, u16, S32_MIN, true);
8524b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s32, u32, S32_MAX, false);
8534b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s32, u32, -1, true);
8544b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s32, u32, S32_MIN, true);
8554b21d25bSKees Cook #if BITS_PER_LONG == 64
8564b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s32, u64, S32_MAX, false);
8574b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s32, u64, -1, true);
8584b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s32, u64, S32_MIN, true);
8594b21d25bSKees Cook #endif
8604b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s32, s8, S8_MAX, false);
8614b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s32, s8, S8_MIN, false);
8624b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s32, s8, (s32)S8_MAX + 1, true);
8634b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s32, s8, (s32)S8_MIN - 1, true);
8644b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s32, s8, S32_MAX, true);
8654b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s32, s8, S32_MIN, true);
8664b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s32, s16, S16_MAX, false);
8674b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s32, s16, S16_MIN, false);
8684b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s32, s16, (s32)S16_MAX + 1, true);
8694b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s32, s16, (s32)S16_MIN - 1, true);
8704b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s32, s16, S32_MAX, true);
8714b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s32, s16, S32_MIN, true);
8724b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s32, s32, S32_MAX, false);
8734b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s32, s32, S32_MIN, false);
8744b21d25bSKees Cook #if BITS_PER_LONG == 64
8754b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s32, s64, S32_MAX, false);
8764b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s32, s64, S32_MIN, false);
8774b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u64, u8, U64_MAX, true);
8784b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u64, u8, U8_MAX, false);
8794b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u64, u8, (u64)U8_MAX + 1, true);
8804b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u64, u16, U64_MAX, true);
8814b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u64, u16, U16_MAX, false);
8824b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u64, u16, (u64)U16_MAX + 1, true);
8834b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u64, u32, U64_MAX, true);
8844b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u64, u32, U32_MAX, false);
8854b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u64, u32, (u64)U32_MAX + 1, true);
8864b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u64, u64, U64_MAX, false);
8874b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u64, s8, S8_MAX, false);
8884b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u64, s8, (u64)S8_MAX + 1, true);
8894b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u64, s8, U64_MAX, true);
8904b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u64, s16, S16_MAX, false);
8914b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u64, s16, (u64)S16_MAX + 1, true);
8924b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u64, s16, U64_MAX, true);
8934b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u64, s32, S32_MAX, false);
8944b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u64, s32, (u64)S32_MAX + 1, true);
8954b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u64, s32, U64_MAX, true);
8964b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u64, s64, S64_MAX, false);
8974b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u64, s64, U64_MAX, true);
8984b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(u64, s64, (u64)S64_MAX + 1, true);
8994b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s64, u8, S64_MAX, true);
9004b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s64, u8, S64_MIN, true);
9014b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s64, u8, -1, true);
9024b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s64, u8, U8_MAX, false);
9034b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s64, u8, (s64)U8_MAX + 1, true);
9044b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s64, u16, S64_MAX, true);
9054b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s64, u16, S64_MIN, true);
9064b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s64, u16, -1, true);
9074b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s64, u16, U16_MAX, false);
9084b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s64, u16, (s64)U16_MAX + 1, true);
9094b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s64, u32, S64_MAX, true);
9104b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s64, u32, S64_MIN, true);
9114b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s64, u32, -1, true);
9124b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s64, u32, U32_MAX, false);
9134b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s64, u32, (s64)U32_MAX + 1, true);
9144b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s64, u64, S64_MAX, false);
9154b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s64, u64, S64_MIN, true);
9164b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s64, u64, -1, true);
9174b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s64, s8, S8_MAX, false);
9184b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s64, s8, S8_MIN, false);
9194b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s64, s8, (s64)S8_MAX + 1, true);
9204b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s64, s8, (s64)S8_MIN - 1, true);
9214b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s64, s8, S64_MAX, true);
9224b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s64, s16, S16_MAX, false);
9234b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s64, s16, S16_MIN, false);
9244b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s64, s16, (s64)S16_MAX + 1, true);
9254b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s64, s16, (s64)S16_MIN - 1, true);
9264b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s64, s16, S64_MAX, true);
9274b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s64, s32, S32_MAX, false);
9284b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s64, s32, S32_MIN, false);
9294b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s64, s32, (s64)S32_MAX + 1, true);
9304b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s64, s32, (s64)S32_MIN - 1, true);
9314b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s64, s32, S64_MAX, true);
9324b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s64, s64, S64_MAX, false);
9334b21d25bSKees Cook 	TEST_OVERFLOWS_TYPE(s64, s64, S64_MIN, false);
9344b21d25bSKees Cook #endif
9354b21d25bSKees Cook 
9364b21d25bSKees Cook 	/* Check for macro side-effects. */
9374b21d25bSKees Cook 	var = INT_MAX - 1;
9384b21d25bSKees Cook 	__TEST_OVERFLOWS_TYPE(__overflows_type, var++, int, false);
9394b21d25bSKees Cook 	__TEST_OVERFLOWS_TYPE(__overflows_type, var++, int, false);
9404b21d25bSKees Cook 	__TEST_OVERFLOWS_TYPE(__overflows_type, var++, int, true);
9414b21d25bSKees Cook 	var = INT_MAX - 1;
9424b21d25bSKees Cook 	__TEST_OVERFLOWS_TYPE(overflows_type, var++, int, false);
9434b21d25bSKees Cook 	__TEST_OVERFLOWS_TYPE(overflows_type, var++, int, false);
9444b21d25bSKees Cook 	__TEST_OVERFLOWS_TYPE(overflows_type, var++, int, true);
9454b21d25bSKees Cook 
9464b21d25bSKees Cook 	kunit_info(test, "%d overflows_type() tests finished\n", count);
9474b21d25bSKees Cook #undef TEST_OVERFLOWS_TYPE
9484b21d25bSKees Cook #undef __TEST_OVERFLOWS_TYPE
9494b21d25bSKees Cook }
9504b21d25bSKees Cook 
same_type_test(struct kunit * test)9514b21d25bSKees Cook static void same_type_test(struct kunit *test)
9524b21d25bSKees Cook {
9534b21d25bSKees Cook 	int count = 0;
9544b21d25bSKees Cook 	int var;
9554b21d25bSKees Cook 
9564b21d25bSKees Cook #define TEST_SAME_TYPE(t1, t2, same)			do {	\
9574b21d25bSKees Cook 	typeof(t1) __t1h = type_max(t1);			\
9584b21d25bSKees Cook 	typeof(t1) __t1l = type_min(t1);			\
9594b21d25bSKees Cook 	typeof(t2) __t2h = type_max(t2);			\
9604b21d25bSKees Cook 	typeof(t2) __t2l = type_min(t2);			\
9614b21d25bSKees Cook 	KUNIT_EXPECT_EQ(test, true, __same_type(t1, __t1h));	\
9624b21d25bSKees Cook 	KUNIT_EXPECT_EQ(test, true, __same_type(t1, __t1l));	\
9634b21d25bSKees Cook 	KUNIT_EXPECT_EQ(test, true, __same_type(__t1h, t1));	\
9644b21d25bSKees Cook 	KUNIT_EXPECT_EQ(test, true, __same_type(__t1l, t1));	\
9654b21d25bSKees Cook 	KUNIT_EXPECT_EQ(test, true, __same_type(t2, __t2h));	\
9664b21d25bSKees Cook 	KUNIT_EXPECT_EQ(test, true, __same_type(t2, __t2l));	\
9674b21d25bSKees Cook 	KUNIT_EXPECT_EQ(test, true, __same_type(__t2h, t2));	\
9684b21d25bSKees Cook 	KUNIT_EXPECT_EQ(test, true, __same_type(__t2l, t2));	\
9694b21d25bSKees Cook 	KUNIT_EXPECT_EQ(test, same, __same_type(t1, t2));	\
9704b21d25bSKees Cook 	KUNIT_EXPECT_EQ(test, same, __same_type(t2, __t1h));	\
9714b21d25bSKees Cook 	KUNIT_EXPECT_EQ(test, same, __same_type(t2, __t1l));	\
9724b21d25bSKees Cook 	KUNIT_EXPECT_EQ(test, same, __same_type(__t1h, t2));	\
9734b21d25bSKees Cook 	KUNIT_EXPECT_EQ(test, same, __same_type(__t1l, t2));	\
9744b21d25bSKees Cook 	KUNIT_EXPECT_EQ(test, same, __same_type(t1, __t2h));	\
9754b21d25bSKees Cook 	KUNIT_EXPECT_EQ(test, same, __same_type(t1, __t2l));	\
9764b21d25bSKees Cook 	KUNIT_EXPECT_EQ(test, same, __same_type(__t2h, t1));	\
9774b21d25bSKees Cook 	KUNIT_EXPECT_EQ(test, same, __same_type(__t2l, t1));	\
9784b21d25bSKees Cook } while (0)
9794b21d25bSKees Cook 
9804b21d25bSKees Cook #if BITS_PER_LONG == 64
9814b21d25bSKees Cook # define TEST_SAME_TYPE64(base, t, m)	TEST_SAME_TYPE(base, t, m)
9824b21d25bSKees Cook #else
9834b21d25bSKees Cook # define TEST_SAME_TYPE64(base, t, m)	do { } while (0)
9844b21d25bSKees Cook #endif
9854b21d25bSKees Cook 
9864b21d25bSKees Cook #define TEST_TYPE_SETS(base, mu8, mu16, mu32, ms8, ms16, ms32, mu64, ms64) \
9874b21d25bSKees Cook do {									\
9884b21d25bSKees Cook 	TEST_SAME_TYPE(base,  u8,  mu8);				\
9894b21d25bSKees Cook 	TEST_SAME_TYPE(base, u16, mu16);				\
9904b21d25bSKees Cook 	TEST_SAME_TYPE(base, u32, mu32);				\
9914b21d25bSKees Cook 	TEST_SAME_TYPE(base,  s8,  ms8);				\
9924b21d25bSKees Cook 	TEST_SAME_TYPE(base, s16, ms16);				\
9934b21d25bSKees Cook 	TEST_SAME_TYPE(base, s32, ms32);				\
9944b21d25bSKees Cook 	TEST_SAME_TYPE64(base, u64, mu64);				\
9954b21d25bSKees Cook 	TEST_SAME_TYPE64(base, s64, ms64);				\
9964b21d25bSKees Cook } while (0)
9974b21d25bSKees Cook 
9984b21d25bSKees Cook 	TEST_TYPE_SETS(u8,   true, false, false, false, false, false, false, false);
9994b21d25bSKees Cook 	TEST_TYPE_SETS(u16, false,  true, false, false, false, false, false, false);
10004b21d25bSKees Cook 	TEST_TYPE_SETS(u32, false, false,  true, false, false, false, false, false);
10014b21d25bSKees Cook 	TEST_TYPE_SETS(s8,  false, false, false,  true, false, false, false, false);
10024b21d25bSKees Cook 	TEST_TYPE_SETS(s16, false, false, false, false,  true, false, false, false);
10034b21d25bSKees Cook 	TEST_TYPE_SETS(s32, false, false, false, false, false,  true, false, false);
10044b21d25bSKees Cook #if BITS_PER_LONG == 64
10054b21d25bSKees Cook 	TEST_TYPE_SETS(u64, false, false, false, false, false, false,  true, false);
10064b21d25bSKees Cook 	TEST_TYPE_SETS(s64, false, false, false, false, false, false, false,  true);
10074b21d25bSKees Cook #endif
10084b21d25bSKees Cook 
10094b21d25bSKees Cook 	/* Check for macro side-effects. */
10104b21d25bSKees Cook 	var = 4;
10114b21d25bSKees Cook 	KUNIT_EXPECT_EQ(test, var, 4);
10124b21d25bSKees Cook 	KUNIT_EXPECT_TRUE(test, __same_type(var++, int));
10134b21d25bSKees Cook 	KUNIT_EXPECT_EQ(test, var, 4);
10144b21d25bSKees Cook 	KUNIT_EXPECT_TRUE(test, __same_type(int, var++));
10154b21d25bSKees Cook 	KUNIT_EXPECT_EQ(test, var, 4);
10164b21d25bSKees Cook 	KUNIT_EXPECT_TRUE(test, __same_type(var++, var++));
10174b21d25bSKees Cook 	KUNIT_EXPECT_EQ(test, var, 4);
10184b21d25bSKees Cook 
10194b21d25bSKees Cook 	kunit_info(test, "%d __same_type() tests finished\n", count);
10204b21d25bSKees Cook 
10214b21d25bSKees Cook #undef TEST_TYPE_SETS
10224b21d25bSKees Cook #undef TEST_SAME_TYPE64
10234b21d25bSKees Cook #undef TEST_SAME_TYPE
10244b21d25bSKees Cook }
10254b21d25bSKees Cook 
castable_to_type_test(struct kunit * test)10264b21d25bSKees Cook static void castable_to_type_test(struct kunit *test)
10274b21d25bSKees Cook {
10284b21d25bSKees Cook 	int count = 0;
10294b21d25bSKees Cook 
10304b21d25bSKees Cook #define TEST_CASTABLE_TO_TYPE(arg1, arg2, pass)	do {	\
10314b21d25bSKees Cook 	bool __pass = castable_to_type(arg1, arg2);		\
10324b21d25bSKees Cook 	KUNIT_EXPECT_EQ_MSG(test, __pass, pass,			\
10334b21d25bSKees Cook 		"expected castable_to_type(" #arg1 ", " #arg2 ") to%s pass\n",\
10344b21d25bSKees Cook 		pass ? "" : " not");				\
10354b21d25bSKees Cook 	count++;						\
10364b21d25bSKees Cook } while (0)
10374b21d25bSKees Cook 
10384b21d25bSKees Cook 	TEST_CASTABLE_TO_TYPE(16, u8, true);
10394b21d25bSKees Cook 	TEST_CASTABLE_TO_TYPE(16, u16, true);
10404b21d25bSKees Cook 	TEST_CASTABLE_TO_TYPE(16, u32, true);
10414b21d25bSKees Cook 	TEST_CASTABLE_TO_TYPE(16, s8, true);
10424b21d25bSKees Cook 	TEST_CASTABLE_TO_TYPE(16, s16, true);
10434b21d25bSKees Cook 	TEST_CASTABLE_TO_TYPE(16, s32, true);
10444b21d25bSKees Cook 	TEST_CASTABLE_TO_TYPE(-16, s8, true);
10454b21d25bSKees Cook 	TEST_CASTABLE_TO_TYPE(-16, s16, true);
10464b21d25bSKees Cook 	TEST_CASTABLE_TO_TYPE(-16, s32, true);
10474b21d25bSKees Cook #if BITS_PER_LONG == 64
10484b21d25bSKees Cook 	TEST_CASTABLE_TO_TYPE(16, u64, true);
10494b21d25bSKees Cook 	TEST_CASTABLE_TO_TYPE(-16, s64, true);
10504b21d25bSKees Cook #endif
10514b21d25bSKees Cook 
10524b21d25bSKees Cook #define TEST_CASTABLE_TO_TYPE_VAR(width)	do {				\
10534b21d25bSKees Cook 	u ## width u ## width ## var = 0;					\
10544b21d25bSKees Cook 	s ## width s ## width ## var = 0;					\
10554b21d25bSKees Cook 										\
10564b21d25bSKees Cook 	/* Constant expressions that fit types. */				\
10574b21d25bSKees Cook 	TEST_CASTABLE_TO_TYPE(type_max(u ## width), u ## width, true);		\
10584b21d25bSKees Cook 	TEST_CASTABLE_TO_TYPE(type_min(u ## width), u ## width, true);		\
10594b21d25bSKees Cook 	TEST_CASTABLE_TO_TYPE(type_max(u ## width), u ## width ## var, true);	\
10604b21d25bSKees Cook 	TEST_CASTABLE_TO_TYPE(type_min(u ## width), u ## width ## var, true);	\
10614b21d25bSKees Cook 	TEST_CASTABLE_TO_TYPE(type_max(s ## width), s ## width, true);		\
10624b21d25bSKees Cook 	TEST_CASTABLE_TO_TYPE(type_min(s ## width), s ## width, true);		\
10634b21d25bSKees Cook 	TEST_CASTABLE_TO_TYPE(type_max(s ## width), s ## width ## var, true);	\
10644b21d25bSKees Cook 	TEST_CASTABLE_TO_TYPE(type_min(u ## width), s ## width ## var, true);	\
10654b21d25bSKees Cook 	/* Constant expressions that do not fit types. */			\
10664b21d25bSKees Cook 	TEST_CASTABLE_TO_TYPE(type_max(u ## width), s ## width, false);		\
10674b21d25bSKees Cook 	TEST_CASTABLE_TO_TYPE(type_max(u ## width), s ## width ## var, false);	\
10684b21d25bSKees Cook 	TEST_CASTABLE_TO_TYPE(type_min(s ## width), u ## width, false);		\
10694b21d25bSKees Cook 	TEST_CASTABLE_TO_TYPE(type_min(s ## width), u ## width ## var, false);	\
10704b21d25bSKees Cook 	/* Non-constant expression with mismatched type. */			\
10714b21d25bSKees Cook 	TEST_CASTABLE_TO_TYPE(s ## width ## var, u ## width, false);		\
10724b21d25bSKees Cook 	TEST_CASTABLE_TO_TYPE(u ## width ## var, s ## width, false);		\
10734b21d25bSKees Cook } while (0)
10744b21d25bSKees Cook 
10754b21d25bSKees Cook #define TEST_CASTABLE_TO_TYPE_RANGE(width)	do {				\
10764b21d25bSKees Cook 	unsigned long big = U ## width ## _MAX;					\
10774b21d25bSKees Cook 	signed long small = S ## width ## _MIN;					\
10784b21d25bSKees Cook 	u ## width u ## width ## var = 0;					\
10794b21d25bSKees Cook 	s ## width s ## width ## var = 0;					\
10804b21d25bSKees Cook 										\
10814b21d25bSKees Cook 	/* Constant expression in range. */					\
10824b21d25bSKees Cook 	TEST_CASTABLE_TO_TYPE(U ## width ## _MAX, u ## width, true);		\
10834b21d25bSKees Cook 	TEST_CASTABLE_TO_TYPE(U ## width ## _MAX, u ## width ## var, true);	\
10844b21d25bSKees Cook 	TEST_CASTABLE_TO_TYPE(S ## width ## _MIN, s ## width, true);		\
10854b21d25bSKees Cook 	TEST_CASTABLE_TO_TYPE(S ## width ## _MIN, s ## width ## var, true);	\
10864b21d25bSKees Cook 	/* Constant expression out of range. */					\
10874b21d25bSKees Cook 	TEST_CASTABLE_TO_TYPE((unsigned long)U ## width ## _MAX + 1, u ## width, false); \
10884b21d25bSKees Cook 	TEST_CASTABLE_TO_TYPE((unsigned long)U ## width ## _MAX + 1, u ## width ## var, false); \
10894b21d25bSKees Cook 	TEST_CASTABLE_TO_TYPE((signed long)S ## width ## _MIN - 1, s ## width, false); \
10904b21d25bSKees Cook 	TEST_CASTABLE_TO_TYPE((signed long)S ## width ## _MIN - 1, s ## width ## var, false); \
10914b21d25bSKees Cook 	/* Non-constant expression with mismatched type. */			\
10924b21d25bSKees Cook 	TEST_CASTABLE_TO_TYPE(big, u ## width, false);				\
10934b21d25bSKees Cook 	TEST_CASTABLE_TO_TYPE(big, u ## width ## var, false);			\
10944b21d25bSKees Cook 	TEST_CASTABLE_TO_TYPE(small, s ## width, false);			\
10954b21d25bSKees Cook 	TEST_CASTABLE_TO_TYPE(small, s ## width ## var, false);			\
10964b21d25bSKees Cook } while (0)
10974b21d25bSKees Cook 
10984b21d25bSKees Cook 	TEST_CASTABLE_TO_TYPE_VAR(8);
10994b21d25bSKees Cook 	TEST_CASTABLE_TO_TYPE_VAR(16);
11004b21d25bSKees Cook 	TEST_CASTABLE_TO_TYPE_VAR(32);
11014b21d25bSKees Cook #if BITS_PER_LONG == 64
11024b21d25bSKees Cook 	TEST_CASTABLE_TO_TYPE_VAR(64);
11034b21d25bSKees Cook #endif
11044b21d25bSKees Cook 
11054b21d25bSKees Cook 	TEST_CASTABLE_TO_TYPE_RANGE(8);
11064b21d25bSKees Cook 	TEST_CASTABLE_TO_TYPE_RANGE(16);
11074b21d25bSKees Cook #if BITS_PER_LONG == 64
11084b21d25bSKees Cook 	TEST_CASTABLE_TO_TYPE_RANGE(32);
11094b21d25bSKees Cook #endif
11104b21d25bSKees Cook 	kunit_info(test, "%d castable_to_type() tests finished\n", count);
11114b21d25bSKees Cook 
11124b21d25bSKees Cook #undef TEST_CASTABLE_TO_TYPE_RANGE
11134b21d25bSKees Cook #undef TEST_CASTABLE_TO_TYPE_VAR
11144b21d25bSKees Cook #undef TEST_CASTABLE_TO_TYPE
11154b21d25bSKees Cook }
11164b21d25bSKees Cook 
1117617f55e2SKees Cook static struct kunit_case overflow_test_cases[] = {
1118d219d2a9SKees Cook 	KUNIT_CASE(u8_u8__u8_overflow_test),
1119d219d2a9SKees Cook 	KUNIT_CASE(s8_s8__s8_overflow_test),
1120d219d2a9SKees Cook 	KUNIT_CASE(u16_u16__u16_overflow_test),
1121d219d2a9SKees Cook 	KUNIT_CASE(s16_s16__s16_overflow_test),
1122d219d2a9SKees Cook 	KUNIT_CASE(u32_u32__u32_overflow_test),
1123d219d2a9SKees Cook 	KUNIT_CASE(s32_s32__s32_overflow_test),
1124d219d2a9SKees Cook 	KUNIT_CASE(u64_u64__u64_overflow_test),
1125d219d2a9SKees Cook 	KUNIT_CASE(s64_s64__s64_overflow_test),
1126d219d2a9SKees Cook 	KUNIT_CASE(u32_u32__int_overflow_test),
11270e5b9f25SNick Desaulniers 	KUNIT_CASE(u32_u32__u8_overflow_test),
1128d219d2a9SKees Cook 	KUNIT_CASE(u8_u8__int_overflow_test),
1129d219d2a9SKees Cook 	KUNIT_CASE(int_int__u8_overflow_test),
113077974225SKees Cook 	KUNIT_CASE(shift_sane_test),
113177974225SKees Cook 	KUNIT_CASE(shift_overflow_test),
113277974225SKees Cook 	KUNIT_CASE(shift_truncate_test),
113377974225SKees Cook 	KUNIT_CASE(shift_nonsense_test),
1134617f55e2SKees Cook 	KUNIT_CASE(overflow_allocation_test),
1135617f55e2SKees Cook 	KUNIT_CASE(overflow_size_helpers_test),
11364b21d25bSKees Cook 	KUNIT_CASE(overflows_type_test),
11374b21d25bSKees Cook 	KUNIT_CASE(same_type_test),
11384b21d25bSKees Cook 	KUNIT_CASE(castable_to_type_test),
1139617f55e2SKees Cook 	{}
1140617f55e2SKees Cook };
1141617f55e2SKees Cook 
1142617f55e2SKees Cook static struct kunit_suite overflow_test_suite = {
1143617f55e2SKees Cook 	.name = "overflow",
1144617f55e2SKees Cook 	.test_cases = overflow_test_cases,
1145617f55e2SKees Cook };
1146617f55e2SKees Cook 
1147617f55e2SKees Cook kunit_test_suite(overflow_test_suite);
1148617f55e2SKees Cook 
1149617f55e2SKees Cook MODULE_LICENSE("Dual MIT/GPL");
1150