xref: /linux/lib/tests/scanf_kunit.c (revision 97c1f302f2bc318ed88aa4a49641a3b60b33f7a5)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Test cases for sscanf facility.
4  */
5 
6 #include <kunit/test.h>
7 #include <linux/bitops.h>
8 #include <linux/kernel.h>
9 #include <linux/module.h>
10 #include <linux/overflow.h>
11 #include <linux/prandom.h>
12 #include <linux/slab.h>
13 #include <linux/string.h>
14 
15 #define BUF_SIZE 1024
16 
17 static char *test_buffer;
18 static char *fmt_buffer;
19 static struct rnd_state rnd_state;
20 
21 typedef void (*check_fn)(struct kunit *test, const char *file, const int line,
22 			 const void *check_data, const char *string, const char *fmt, int n_args,
23 			 va_list ap);
24 
25 static void __scanf(7, 9)
26 _test(struct kunit *test, const char *file, const int line, check_fn fn, const void *check_data,
27 	const char *string, const char *fmt, int n_args, ...)
28 {
29 	va_list ap, ap_copy;
30 	int ret;
31 
32 	va_start(ap, n_args);
33 	va_copy(ap_copy, ap);
34 	ret = vsscanf(string, fmt, ap_copy);
35 	va_end(ap_copy);
36 
37 	if (ret != n_args) {
38 		KUNIT_FAIL(test, "%s:%d: vsscanf(\"%s\", \"%s\", ...) returned %d expected %d",
39 			   file, line, string, fmt, ret, n_args);
40 	} else {
41 		(*fn)(test, file, line, check_data, string, fmt, n_args, ap);
42 	}
43 
44 	va_end(ap);
45 }
46 
47 #define _check_numbers_template(arg_fmt, expect, str, fmt, n_args, ap)		\
48 do {										\
49 	for (; n_args > 0; n_args--, expect++) {				\
50 		typeof(*expect) got = *va_arg(ap, typeof(expect));		\
51 		if (got != *expect) {						\
52 			KUNIT_FAIL(test,					\
53 				   "%s:%d: vsscanf(\"%s\", \"%s\", ...) expected " arg_fmt " got " arg_fmt, \
54 				   file, line, str, fmt, *expect, got);		\
55 			return;							\
56 		}								\
57 	}									\
58 } while (0)
59 
60 static void check_ull(struct kunit *test, const char *file, const int line, const void *check_data,
61 		      const char *string, const char *fmt, int n_args, va_list ap)
62 {
63 	const unsigned long long *pval = check_data;
64 
65 	_check_numbers_template("%llu", pval, string, fmt, n_args, ap);
66 }
67 
68 static void check_ll(struct kunit *test, const char *file, const int line, const void *check_data,
69 		     const char *string, const char *fmt, int n_args, va_list ap)
70 {
71 	const long long *pval = check_data;
72 
73 	_check_numbers_template("%lld", pval, string, fmt, n_args, ap);
74 }
75 
76 static void check_ulong(struct kunit *test, const char *file, const int line,
77 			const void *check_data, const char *string, const char *fmt, int n_args,
78 			va_list ap)
79 {
80 	const unsigned long *pval = check_data;
81 
82 	_check_numbers_template("%lu", pval, string, fmt, n_args, ap);
83 }
84 
85 static void check_long(struct kunit *test, const char *file, const int line, const void *check_data,
86 		       const char *string, const char *fmt, int n_args, va_list ap)
87 {
88 	const long *pval = check_data;
89 
90 	_check_numbers_template("%ld", pval, string, fmt, n_args, ap);
91 }
92 
93 static void check_uint(struct kunit *test, const char *file, const int line, const void *check_data,
94 		       const char *string, const char *fmt, int n_args, va_list ap)
95 {
96 	const unsigned int *pval = check_data;
97 
98 	_check_numbers_template("%u", pval, string, fmt, n_args, ap);
99 }
100 
101 static void check_int(struct kunit *test, const char *file, const int line, const void *check_data,
102 		      const char *string, const char *fmt, int n_args, va_list ap)
103 {
104 	const int *pval = check_data;
105 
106 	_check_numbers_template("%d", pval, string, fmt, n_args, ap);
107 }
108 
109 static void check_ushort(struct kunit *test, const char *file, const int line,
110 			 const void *check_data, const char *string, const char *fmt, int n_args,
111 			 va_list ap)
112 {
113 	const unsigned short *pval = check_data;
114 
115 	_check_numbers_template("%hu", pval, string, fmt, n_args, ap);
116 }
117 
118 static void check_short(struct kunit *test, const char *file, const int line,
119 			const void *check_data, const char *string, const char *fmt, int n_args,
120 			va_list ap)
121 {
122 	const short *pval = check_data;
123 
124 	_check_numbers_template("%hd", pval, string, fmt, n_args, ap);
125 }
126 
127 static void check_uchar(struct kunit *test, const char *file, const int line,
128 			const void *check_data, const char *string, const char *fmt, int n_args,
129 			va_list ap)
130 {
131 	const unsigned char *pval = check_data;
132 
133 	_check_numbers_template("%hhu", pval, string, fmt, n_args, ap);
134 }
135 
136 static void check_char(struct kunit *test, const char *file, const int line, const void *check_data,
137 		       const char *string, const char *fmt, int n_args, va_list ap)
138 {
139 	const signed char *pval = check_data;
140 
141 	_check_numbers_template("%hhd", pval, string, fmt, n_args, ap);
142 }
143 
144 /* Selection of interesting numbers to test, copied from test-kstrtox.c */
145 static const unsigned long long numbers[] = {
146 	0x0ULL,
147 	0x1ULL,
148 	0x7fULL,
149 	0x80ULL,
150 	0x81ULL,
151 	0xffULL,
152 	0x100ULL,
153 	0x101ULL,
154 	0x7fffULL,
155 	0x8000ULL,
156 	0x8001ULL,
157 	0xffffULL,
158 	0x10000ULL,
159 	0x10001ULL,
160 	0x7fffffffULL,
161 	0x80000000ULL,
162 	0x80000001ULL,
163 	0xffffffffULL,
164 	0x100000000ULL,
165 	0x100000001ULL,
166 	0x7fffffffffffffffULL,
167 	0x8000000000000000ULL,
168 	0x8000000000000001ULL,
169 	0xfffffffffffffffeULL,
170 	0xffffffffffffffffULL,
171 };
172 
173 #define value_representable_in_type(T, val)					 \
174 (is_signed_type(T)								 \
175 	? ((long long)(val) >= type_min(T)) && ((long long)(val) <= type_max(T)) \
176 	: ((unsigned long long)(val) <= type_max(T)))
177 
178 
179 #define test_one_number(T, gen_fmt, scan_fmt, val, fn)			\
180 do {									\
181 	const T expect_val = (T)(val);					\
182 	T result = ~expect_val; /* should be overwritten */		\
183 									\
184 	snprintf(test_buffer, BUF_SIZE, gen_fmt, expect_val);		\
185 	_test(test, __FILE__, __LINE__, fn, &expect_val, test_buffer, "%" scan_fmt, 1, &result);\
186 } while (0)
187 
188 #define simple_numbers_loop(T, gen_fmt, scan_fmt, fn)			\
189 do {									\
190 	int i;								\
191 									\
192 	for (i = 0; i < ARRAY_SIZE(numbers); i++) {			\
193 		if (value_representable_in_type(T, numbers[i]))		\
194 			test_one_number(T, gen_fmt, scan_fmt,		\
195 					numbers[i], fn);		\
196 									\
197 		if (value_representable_in_type(T, -numbers[i]))	\
198 			test_one_number(T, gen_fmt, scan_fmt,		\
199 					-numbers[i], fn);		\
200 	}								\
201 } while (0)
202 
203 static void numbers_simple(struct kunit *test)
204 {
205 	simple_numbers_loop(unsigned long long,	"%llu",	  "llu", check_ull);
206 	simple_numbers_loop(long long,		"%lld",	  "lld", check_ll);
207 	simple_numbers_loop(long long,		"%lld",	  "lli", check_ll);
208 	simple_numbers_loop(unsigned long long,	"%llx",	  "llx", check_ull);
209 	simple_numbers_loop(long long,		"%llx",	  "llx", check_ll);
210 	simple_numbers_loop(long long,		"0x%llx", "lli", check_ll);
211 	simple_numbers_loop(unsigned long long, "0x%llx", "llx", check_ull);
212 	simple_numbers_loop(long long,		"0x%llx", "llx", check_ll);
213 
214 	simple_numbers_loop(unsigned long,	"%lu",	  "lu", check_ulong);
215 	simple_numbers_loop(long,		"%ld",	  "ld", check_long);
216 	simple_numbers_loop(long,		"%ld",	  "li", check_long);
217 	simple_numbers_loop(unsigned long,	"%lx",	  "lx", check_ulong);
218 	simple_numbers_loop(long,		"%lx",	  "lx", check_long);
219 	simple_numbers_loop(long,		"0x%lx",  "li", check_long);
220 	simple_numbers_loop(unsigned long,	"0x%lx",  "lx", check_ulong);
221 	simple_numbers_loop(long,		"0x%lx",  "lx", check_long);
222 
223 	simple_numbers_loop(unsigned int,	"%u",	  "u", check_uint);
224 	simple_numbers_loop(int,		"%d",	  "d", check_int);
225 	simple_numbers_loop(int,		"%d",	  "i", check_int);
226 	simple_numbers_loop(unsigned int,	"%x",	  "x", check_uint);
227 	simple_numbers_loop(int,		"%x",	  "x", check_int);
228 	simple_numbers_loop(int,		"0x%x",   "i", check_int);
229 	simple_numbers_loop(unsigned int,	"0x%x",   "x", check_uint);
230 	simple_numbers_loop(int,		"0x%x",   "x", check_int);
231 
232 	simple_numbers_loop(unsigned short,	"%hu",	  "hu", check_ushort);
233 	simple_numbers_loop(short,		"%hd",	  "hd", check_short);
234 	simple_numbers_loop(short,		"%hd",	  "hi", check_short);
235 	simple_numbers_loop(unsigned short,	"%hx",	  "hx", check_ushort);
236 	simple_numbers_loop(short,		"%hx",	  "hx", check_short);
237 	simple_numbers_loop(short,		"0x%hx",  "hi", check_short);
238 	simple_numbers_loop(unsigned short,	"0x%hx",  "hx", check_ushort);
239 	simple_numbers_loop(short,		"0x%hx",  "hx", check_short);
240 
241 	simple_numbers_loop(unsigned char,	"%hhu",	  "hhu", check_uchar);
242 	simple_numbers_loop(signed char,	"%hhd",	  "hhd", check_char);
243 	simple_numbers_loop(signed char,	"%hhd",	  "hhi", check_char);
244 	simple_numbers_loop(unsigned char,	"%hhx",	  "hhx", check_uchar);
245 	simple_numbers_loop(signed char,	"%hhx",	  "hhx", check_char);
246 	simple_numbers_loop(signed char,	"0x%hhx", "hhi", check_char);
247 	simple_numbers_loop(unsigned char,	"0x%hhx", "hhx", check_uchar);
248 	simple_numbers_loop(signed char,	"0x%hhx", "hhx", check_char);
249 }
250 
251 /*
252  * This gives a better variety of number "lengths" in a small sample than
253  * the raw prandom*() functions (Not mathematically rigorous!!).
254  * Variabilty of length and value is more important than perfect randomness.
255  */
256 static u32 next_test_random(u32 max_bits)
257 {
258 	u32 n_bits = hweight32(prandom_u32_state(&rnd_state)) % (max_bits + 1);
259 
260 	return prandom_u32_state(&rnd_state) & GENMASK(n_bits, 0);
261 }
262 
263 static unsigned long long next_test_random_ull(void)
264 {
265 	u32 rand1 = prandom_u32_state(&rnd_state);
266 	u32 n_bits = (hweight32(rand1) * 3) % 64;
267 	u64 val = (u64)prandom_u32_state(&rnd_state) * rand1;
268 
269 	return val & GENMASK_ULL(n_bits, 0);
270 }
271 
272 #define random_for_type(T)				\
273 	((T)(sizeof(T) <= sizeof(u32)			\
274 		? next_test_random(BITS_PER_TYPE(T))	\
275 		: next_test_random_ull()))
276 
277 /*
278  * Define a pattern of negative and positive numbers to ensure we get
279  * some of both within the small number of samples in a test string.
280  */
281 #define NEGATIVES_PATTERN 0x3246	/* 00110010 01000110 */
282 
283 #define fill_random_array(arr)							\
284 do {										\
285 	unsigned int neg_pattern = NEGATIVES_PATTERN;				\
286 	int i;									\
287 										\
288 	for (i = 0; i < ARRAY_SIZE(arr); i++, neg_pattern >>= 1) {		\
289 		(arr)[i] = random_for_type(typeof((arr)[0]));			\
290 		if (is_signed_type(typeof((arr)[0])) && (neg_pattern & 1))	\
291 			(arr)[i] = -(arr)[i];					\
292 	}									\
293 } while (0)
294 
295 /*
296  * Convenience wrapper around snprintf() to append at buf_pos in buf,
297  * updating buf_pos and returning the number of characters appended.
298  * On error buf_pos is not changed and return value is 0.
299  */
300 static int __printf(4, 5)
301 append_fmt(char *buf, int *buf_pos, int buf_len, const char *val_fmt, ...)
302 {
303 	va_list ap;
304 	int field_len;
305 
306 	va_start(ap, val_fmt);
307 	field_len = vsnprintf(buf + *buf_pos, buf_len - *buf_pos, val_fmt, ap);
308 	va_end(ap);
309 
310 	if (field_len < 0)
311 		field_len = 0;
312 
313 	*buf_pos += field_len;
314 
315 	return field_len;
316 }
317 
318 /*
319  * Convenience function to append the field delimiter string
320  * to both the value string and format string buffers.
321  */
322 static void append_delim(char *str_buf, int *str_buf_pos, int str_buf_len,
323 				char *fmt_buf, int *fmt_buf_pos, int fmt_buf_len,
324 				const char *delim_str)
325 {
326 	append_fmt(str_buf, str_buf_pos, str_buf_len, delim_str);
327 	append_fmt(fmt_buf, fmt_buf_pos, fmt_buf_len, delim_str);
328 }
329 
330 #define test_array_8(fn, check_data, string, fmt, arr)				\
331 do {										\
332 	BUILD_BUG_ON(ARRAY_SIZE(arr) != 8);					\
333 	_test(test, __FILE__, __LINE__, fn, check_data, string, fmt, 8,		\
334 		&(arr)[0], &(arr)[1], &(arr)[2], &(arr)[3],			\
335 		&(arr)[4], &(arr)[5], &(arr)[6], &(arr)[7]);			\
336 } while (0)
337 
338 #define numbers_list_8(T, gen_fmt, field_sep, scan_fmt, fn)			\
339 do {										\
340 	int i, pos = 0, fmt_pos = 0;						\
341 	T expect[8], result[8];							\
342 										\
343 	fill_random_array(expect);						\
344 										\
345 	for (i = 0; i < ARRAY_SIZE(expect); i++) {				\
346 		if (i != 0)							\
347 			append_delim(test_buffer, &pos, BUF_SIZE,		\
348 				     fmt_buffer, &fmt_pos, BUF_SIZE,		\
349 				     field_sep);				\
350 										\
351 		append_fmt(test_buffer, &pos, BUF_SIZE, gen_fmt, expect[i]);	\
352 		append_fmt(fmt_buffer, &fmt_pos, BUF_SIZE, "%%%s", scan_fmt);	\
353 	}									\
354 										\
355 	test_array_8(fn, expect, test_buffer, fmt_buffer, result);		\
356 } while (0)
357 
358 #define numbers_list_fix_width(T, gen_fmt, field_sep, width, scan_fmt, fn)	\
359 do {										\
360 	char full_fmt[16];							\
361 										\
362 	snprintf(full_fmt, sizeof(full_fmt), "%u%s", width, scan_fmt);		\
363 	numbers_list_8(T, gen_fmt, field_sep, full_fmt, fn);			\
364 } while (0)
365 
366 #define numbers_list_val_width(T, gen_fmt, field_sep, scan_fmt, fn)		\
367 do {										\
368 	int i, val_len, pos = 0, fmt_pos = 0;					\
369 	T expect[8], result[8];							\
370 										\
371 	fill_random_array(expect);						\
372 										\
373 	for (i = 0; i < ARRAY_SIZE(expect); i++) {				\
374 		if (i != 0)							\
375 			append_delim(test_buffer, &pos, BUF_SIZE,		\
376 				     fmt_buffer, &fmt_pos, BUF_SIZE, field_sep);\
377 										\
378 		val_len = append_fmt(test_buffer, &pos, BUF_SIZE, gen_fmt,	\
379 				     expect[i]);				\
380 		append_fmt(fmt_buffer, &fmt_pos, BUF_SIZE,			\
381 			   "%%%u%s", val_len, scan_fmt);			\
382 	}									\
383 										\
384 	test_array_8(fn, expect, test_buffer, fmt_buffer, result);		\
385 } while (0)
386 
387 static void numbers_list_ll(struct kunit *test, const char *delim)
388 {
389 	numbers_list_8(unsigned long long, "%llu",   delim, "llu", check_ull);
390 	numbers_list_8(long long,	   "%lld",   delim, "lld", check_ll);
391 	numbers_list_8(long long,	   "%lld",   delim, "lli", check_ll);
392 	numbers_list_8(unsigned long long, "%llx",   delim, "llx", check_ull);
393 	numbers_list_8(unsigned long long, "0x%llx", delim, "llx", check_ull);
394 	numbers_list_8(long long,	   "0x%llx", delim, "lli", check_ll);
395 }
396 
397 static void numbers_list_l(struct kunit *test, const char *delim)
398 {
399 	numbers_list_8(unsigned long,	   "%lu",    delim, "lu", check_ulong);
400 	numbers_list_8(long,		   "%ld",    delim, "ld", check_long);
401 	numbers_list_8(long,		   "%ld",    delim, "li", check_long);
402 	numbers_list_8(unsigned long,	   "%lx",    delim, "lx", check_ulong);
403 	numbers_list_8(unsigned long,	   "0x%lx",  delim, "lx", check_ulong);
404 	numbers_list_8(long,		   "0x%lx",  delim, "li", check_long);
405 }
406 
407 static void numbers_list_d(struct kunit *test, const char *delim)
408 {
409 	numbers_list_8(unsigned int,	   "%u",     delim, "u", check_uint);
410 	numbers_list_8(int,		   "%d",     delim, "d", check_int);
411 	numbers_list_8(int,		   "%d",     delim, "i", check_int);
412 	numbers_list_8(unsigned int,	   "%x",     delim, "x", check_uint);
413 	numbers_list_8(unsigned int,	   "0x%x",   delim, "x", check_uint);
414 	numbers_list_8(int,		   "0x%x",   delim, "i", check_int);
415 }
416 
417 static void numbers_list_h(struct kunit *test, const char *delim)
418 {
419 	numbers_list_8(unsigned short,	   "%hu",    delim, "hu", check_ushort);
420 	numbers_list_8(short,		   "%hd",    delim, "hd", check_short);
421 	numbers_list_8(short,		   "%hd",    delim, "hi", check_short);
422 	numbers_list_8(unsigned short,	   "%hx",    delim, "hx", check_ushort);
423 	numbers_list_8(unsigned short,	   "0x%hx",  delim, "hx", check_ushort);
424 	numbers_list_8(short,		   "0x%hx",  delim, "hi", check_short);
425 }
426 
427 static void numbers_list_hh(struct kunit *test, const char *delim)
428 {
429 	numbers_list_8(unsigned char,	   "%hhu",   delim, "hhu", check_uchar);
430 	numbers_list_8(signed char,	   "%hhd",   delim, "hhd", check_char);
431 	numbers_list_8(signed char,	   "%hhd",   delim, "hhi", check_char);
432 	numbers_list_8(unsigned char,	   "%hhx",   delim, "hhx", check_uchar);
433 	numbers_list_8(unsigned char,	   "0x%hhx", delim, "hhx", check_uchar);
434 	numbers_list_8(signed char,	   "0x%hhx", delim, "hhi", check_char);
435 }
436 
437 static void numbers_list(struct kunit *test, const char *delim)
438 {
439 	numbers_list_ll(test, delim);
440 	numbers_list_l(test, delim);
441 	numbers_list_d(test, delim);
442 	numbers_list_h(test, delim);
443 	numbers_list_hh(test, delim);
444 }
445 
446 static void numbers_list_field_width_ll(struct kunit *test, const char *delim)
447 {
448 	numbers_list_fix_width(unsigned long long, "%llu",   delim, 20, "llu", check_ull);
449 	numbers_list_fix_width(long long,	   "%lld",   delim, 20, "lld", check_ll);
450 	numbers_list_fix_width(long long,	   "%lld",   delim, 20, "lli", check_ll);
451 	numbers_list_fix_width(unsigned long long, "%llx",   delim, 16, "llx", check_ull);
452 	numbers_list_fix_width(unsigned long long, "0x%llx", delim, 18, "llx", check_ull);
453 	numbers_list_fix_width(long long,	   "0x%llx", delim, 18, "lli", check_ll);
454 }
455 
456 static void numbers_list_field_width_l(struct kunit *test, const char *delim)
457 {
458 #if BITS_PER_LONG == 64
459 	numbers_list_fix_width(unsigned long,	"%lu",	     delim, 20, "lu", check_ulong);
460 	numbers_list_fix_width(long,		"%ld",	     delim, 20, "ld", check_long);
461 	numbers_list_fix_width(long,		"%ld",	     delim, 20, "li", check_long);
462 	numbers_list_fix_width(unsigned long,	"%lx",	     delim, 16, "lx", check_ulong);
463 	numbers_list_fix_width(unsigned long,	"0x%lx",     delim, 18, "lx", check_ulong);
464 	numbers_list_fix_width(long,		"0x%lx",     delim, 18, "li", check_long);
465 #else
466 	numbers_list_fix_width(unsigned long,	"%lu",	     delim, 10, "lu", check_ulong);
467 	numbers_list_fix_width(long,		"%ld",	     delim, 11, "ld", check_long);
468 	numbers_list_fix_width(long,		"%ld",	     delim, 11, "li", check_long);
469 	numbers_list_fix_width(unsigned long,	"%lx",	     delim, 8,  "lx", check_ulong);
470 	numbers_list_fix_width(unsigned long,	"0x%lx",     delim, 10, "lx", check_ulong);
471 	numbers_list_fix_width(long,		"0x%lx",     delim, 10, "li", check_long);
472 #endif
473 }
474 
475 static void numbers_list_field_width_d(struct kunit *test, const char *delim)
476 {
477 	numbers_list_fix_width(unsigned int,	"%u",	     delim, 10, "u", check_uint);
478 	numbers_list_fix_width(int,		"%d",	     delim, 11, "d", check_int);
479 	numbers_list_fix_width(int,		"%d",	     delim, 11, "i", check_int);
480 	numbers_list_fix_width(unsigned int,	"%x",	     delim, 8,  "x", check_uint);
481 	numbers_list_fix_width(unsigned int,	"0x%x",	     delim, 10, "x", check_uint);
482 	numbers_list_fix_width(int,		"0x%x",	     delim, 10, "i", check_int);
483 }
484 
485 static void numbers_list_field_width_h(struct kunit *test, const char *delim)
486 {
487 	numbers_list_fix_width(unsigned short,	"%hu",	     delim, 5, "hu", check_ushort);
488 	numbers_list_fix_width(short,		"%hd",	     delim, 6, "hd", check_short);
489 	numbers_list_fix_width(short,		"%hd",	     delim, 6, "hi", check_short);
490 	numbers_list_fix_width(unsigned short,	"%hx",	     delim, 4, "hx", check_ushort);
491 	numbers_list_fix_width(unsigned short,	"0x%hx",     delim, 6, "hx", check_ushort);
492 	numbers_list_fix_width(short,		"0x%hx",     delim, 6, "hi", check_short);
493 }
494 
495 static void numbers_list_field_width_hh(struct kunit *test, const char *delim)
496 {
497 	numbers_list_fix_width(unsigned char,	"%hhu",	     delim, 3, "hhu", check_uchar);
498 	numbers_list_fix_width(signed char,	"%hhd",	     delim, 4, "hhd", check_char);
499 	numbers_list_fix_width(signed char,	"%hhd",	     delim, 4, "hhi", check_char);
500 	numbers_list_fix_width(unsigned char,	"%hhx",	     delim, 2, "hhx", check_uchar);
501 	numbers_list_fix_width(unsigned char,	"0x%hhx",    delim, 4, "hhx", check_uchar);
502 	numbers_list_fix_width(signed char,	"0x%hhx",    delim, 4, "hhi", check_char);
503 }
504 
505 /*
506  * List of numbers separated by delim. Each field width specifier is the
507  * maximum possible digits for the given type and base.
508  */
509 static void numbers_list_field_width_typemax(struct kunit *test, const char *delim)
510 {
511 	numbers_list_field_width_ll(test, delim);
512 	numbers_list_field_width_l(test, delim);
513 	numbers_list_field_width_d(test, delim);
514 	numbers_list_field_width_h(test, delim);
515 	numbers_list_field_width_hh(test, delim);
516 }
517 
518 static void numbers_list_field_width_val_ll(struct kunit *test, const char *delim)
519 {
520 	numbers_list_val_width(unsigned long long, "%llu",   delim, "llu", check_ull);
521 	numbers_list_val_width(long long,	   "%lld",   delim, "lld", check_ll);
522 	numbers_list_val_width(long long,	   "%lld",   delim, "lli", check_ll);
523 	numbers_list_val_width(unsigned long long, "%llx",   delim, "llx", check_ull);
524 	numbers_list_val_width(unsigned long long, "0x%llx", delim, "llx", check_ull);
525 	numbers_list_val_width(long long,	   "0x%llx", delim, "lli", check_ll);
526 }
527 
528 static void numbers_list_field_width_val_l(struct kunit *test, const char *delim)
529 {
530 	numbers_list_val_width(unsigned long,	"%lu",	     delim, "lu", check_ulong);
531 	numbers_list_val_width(long,		"%ld",	     delim, "ld", check_long);
532 	numbers_list_val_width(long,		"%ld",	     delim, "li", check_long);
533 	numbers_list_val_width(unsigned long,	"%lx",	     delim, "lx", check_ulong);
534 	numbers_list_val_width(unsigned long,	"0x%lx",     delim, "lx", check_ulong);
535 	numbers_list_val_width(long,		"0x%lx",     delim, "li", check_long);
536 }
537 
538 static void numbers_list_field_width_val_d(struct kunit *test, const char *delim)
539 {
540 	numbers_list_val_width(unsigned int,	"%u",	     delim, "u", check_uint);
541 	numbers_list_val_width(int,		"%d",	     delim, "d", check_int);
542 	numbers_list_val_width(int,		"%d",	     delim, "i", check_int);
543 	numbers_list_val_width(unsigned int,	"%x",	     delim, "x", check_uint);
544 	numbers_list_val_width(unsigned int,	"0x%x",	     delim, "x", check_uint);
545 	numbers_list_val_width(int,		"0x%x",	     delim, "i", check_int);
546 }
547 
548 static void numbers_list_field_width_val_h(struct kunit *test, const char *delim)
549 {
550 	numbers_list_val_width(unsigned short,	"%hu",	     delim, "hu", check_ushort);
551 	numbers_list_val_width(short,		"%hd",	     delim, "hd", check_short);
552 	numbers_list_val_width(short,		"%hd",	     delim, "hi", check_short);
553 	numbers_list_val_width(unsigned short,	"%hx",	     delim, "hx", check_ushort);
554 	numbers_list_val_width(unsigned short,	"0x%hx",     delim, "hx", check_ushort);
555 	numbers_list_val_width(short,		"0x%hx",     delim, "hi", check_short);
556 }
557 
558 static void numbers_list_field_width_val_hh(struct kunit *test, const char *delim)
559 {
560 	numbers_list_val_width(unsigned char,	"%hhu",	     delim, "hhu", check_uchar);
561 	numbers_list_val_width(signed char,	"%hhd",	     delim, "hhd", check_char);
562 	numbers_list_val_width(signed char,	"%hhd",	     delim, "hhi", check_char);
563 	numbers_list_val_width(unsigned char,	"%hhx",	     delim, "hhx", check_uchar);
564 	numbers_list_val_width(unsigned char,	"0x%hhx",    delim, "hhx", check_uchar);
565 	numbers_list_val_width(signed char,	"0x%hhx",    delim, "hhi", check_char);
566 }
567 
568 /*
569  * List of numbers separated by delim. Each field width specifier is the
570  * exact length of the corresponding value digits in the string being scanned.
571  */
572 static void numbers_list_field_width_val_width(struct kunit *test, const char *delim)
573 {
574 	numbers_list_field_width_val_ll(test, delim);
575 	numbers_list_field_width_val_l(test, delim);
576 	numbers_list_field_width_val_d(test, delim);
577 	numbers_list_field_width_val_h(test, delim);
578 	numbers_list_field_width_val_hh(test, delim);
579 }
580 
581 /*
582  * Slice a continuous string of digits without field delimiters, containing
583  * numbers of varying length, using the field width to extract each group
584  * of digits. For example the hex values c0,3,bf01,303 would have a
585  * string representation of "c03bf01303" and extracted with "%2x%1x%4x%3x".
586  */
587 static void numbers_slice(struct kunit *test)
588 {
589 	numbers_list_field_width_val_width(test, "");
590 }
591 
592 #define test_number_prefix(T, str, scan_fmt, expect0, expect1, n_args, fn)	\
593 do {										\
594 	const T expect[2] = { expect0, expect1 };				\
595 	T result[2] = { (T)~expect[0], (T)~expect[1] };				\
596 										\
597 	_test(test, __FILE__, __LINE__, fn, &expect, str, scan_fmt, n_args, &result[0], &result[1]);\
598 } while (0)
599 
600 /*
601  * Number prefix is >= field width.
602  * Expected behaviour is derived from testing userland sscanf.
603  */
604 static void numbers_prefix_overflow(struct kunit *test)
605 {
606 	/*
607 	 * Negative decimal with a field of width 1, should quit scanning
608 	 * and return 0.
609 	 */
610 	test_number_prefix(long long,	"-1 1", "%1lld %lld",	0, 0, 0, check_ll);
611 	test_number_prefix(long,	"-1 1", "%1ld %ld",	0, 0, 0, check_long);
612 	test_number_prefix(int,		"-1 1", "%1d %d",	0, 0, 0, check_int);
613 	test_number_prefix(short,	"-1 1", "%1hd %hd",	0, 0, 0, check_short);
614 	test_number_prefix(signed char,	"-1 1", "%1hhd %hhd",	0, 0, 0, check_char);
615 
616 	test_number_prefix(long long,	"-1 1", "%1lli %lli",	0, 0, 0, check_ll);
617 	test_number_prefix(long,	"-1 1", "%1li %li",	0, 0, 0, check_long);
618 	test_number_prefix(int,		"-1 1", "%1i %i",	0, 0, 0, check_int);
619 	test_number_prefix(short,	"-1 1", "%1hi %hi",	0, 0, 0, check_short);
620 	test_number_prefix(signed char,	"-1 1", "%1hhi %hhi",	0, 0, 0, check_char);
621 
622 	/*
623 	 * 0x prefix in a field of width 1: 0 is a valid digit so should
624 	 * convert. Next field scan starts at the 'x' which isn't a digit so
625 	 * scan quits with one field converted.
626 	 */
627 	test_number_prefix(unsigned long long,	"0xA7", "%1llx%llx", 0, 0, 1, check_ull);
628 	test_number_prefix(unsigned long,	"0xA7", "%1lx%lx",   0, 0, 1, check_ulong);
629 	test_number_prefix(unsigned int,	"0xA7", "%1x%x",     0, 0, 1, check_uint);
630 	test_number_prefix(unsigned short,	"0xA7", "%1hx%hx",   0, 0, 1, check_ushort);
631 	test_number_prefix(unsigned char,	"0xA7", "%1hhx%hhx", 0, 0, 1, check_uchar);
632 	test_number_prefix(long long,		"0xA7", "%1lli%llx", 0, 0, 1, check_ll);
633 	test_number_prefix(long,		"0xA7", "%1li%lx",   0, 0, 1, check_long);
634 	test_number_prefix(int,			"0xA7", "%1i%x",     0, 0, 1, check_int);
635 	test_number_prefix(short,		"0xA7", "%1hi%hx",   0, 0, 1, check_short);
636 	test_number_prefix(char,		"0xA7", "%1hhi%hhx", 0, 0, 1, check_char);
637 
638 	/*
639 	 * 0x prefix in a field of width 2 using %x conversion: first field
640 	 * converts to 0. Next field scan starts at the character after "0x".
641 	 * Both fields will convert.
642 	 */
643 	test_number_prefix(unsigned long long,	"0xA7", "%2llx%llx", 0, 0xa7, 2, check_ull);
644 	test_number_prefix(unsigned long,	"0xA7", "%2lx%lx",   0, 0xa7, 2, check_ulong);
645 	test_number_prefix(unsigned int,	"0xA7", "%2x%x",     0, 0xa7, 2, check_uint);
646 	test_number_prefix(unsigned short,	"0xA7", "%2hx%hx",   0, 0xa7, 2, check_ushort);
647 	test_number_prefix(unsigned char,	"0xA7", "%2hhx%hhx", 0, 0xa7, 2, check_uchar);
648 
649 	/*
650 	 * 0x prefix in a field of width 2 using %i conversion: first field
651 	 * converts to 0. Next field scan starts at the character after "0x",
652 	 * which will convert if can be interpreted as decimal but will fail
653 	 * if it contains any hex digits (since no 0x prefix).
654 	 */
655 	test_number_prefix(long long,	"0x67", "%2lli%lli", 0, 67, 2, check_ll);
656 	test_number_prefix(long,	"0x67", "%2li%li",   0, 67, 2, check_long);
657 	test_number_prefix(int,		"0x67", "%2i%i",     0, 67, 2, check_int);
658 	test_number_prefix(short,	"0x67", "%2hi%hi",   0, 67, 2, check_short);
659 	test_number_prefix(char,	"0x67", "%2hhi%hhi", 0, 67, 2, check_char);
660 
661 	test_number_prefix(long long,	"0xA7", "%2lli%lli", 0, 0,  1, check_ll);
662 	test_number_prefix(long,	"0xA7", "%2li%li",   0, 0,  1, check_long);
663 	test_number_prefix(int,		"0xA7", "%2i%i",     0, 0,  1, check_int);
664 	test_number_prefix(short,	"0xA7", "%2hi%hi",   0, 0,  1, check_short);
665 	test_number_prefix(char,	"0xA7", "%2hhi%hhi", 0, 0,  1, check_char);
666 }
667 
668 #define _test_simple_strtoxx(T, fn, gen_fmt, expect, base)			\
669 do {										\
670 	T got;									\
671 	char *endp;								\
672 	int len;								\
673 										\
674 	len = snprintf(test_buffer, BUF_SIZE, gen_fmt, expect);			\
675 	got = (fn)(test_buffer, &endp, base);					\
676 	if (got != (expect)) {							\
677 		KUNIT_FAIL(test, #fn "(\"%s\", %d): got " gen_fmt " expected " gen_fmt, \
678 			   test_buffer, base, got, expect);			\
679 	} else if (endp != test_buffer + len) {					\
680 		KUNIT_FAIL(test, #fn "(\"%s\", %d) startp=0x%px got endp=0x%px expected 0x%px", \
681 			   test_buffer, base, test_buffer,			\
682 			   test_buffer + len, endp);				\
683 	}									\
684 } while (0)
685 
686 #define test_simple_strtoxx(T, fn, gen_fmt, base)				\
687 do {										\
688 	int i;									\
689 										\
690 	for (i = 0; i < ARRAY_SIZE(numbers); i++) {				\
691 		_test_simple_strtoxx(T, fn, gen_fmt, (T)numbers[i], base);	\
692 										\
693 		if (is_signed_type(T))						\
694 			_test_simple_strtoxx(T, fn, gen_fmt,			\
695 					      -(T)numbers[i], base);		\
696 	}									\
697 } while (0)
698 
699 static void test_simple_strtoull(struct kunit *test)
700 {
701 	test_simple_strtoxx(unsigned long long, simple_strtoull, "%llu",   10);
702 	test_simple_strtoxx(unsigned long long, simple_strtoull, "%llu",   0);
703 	test_simple_strtoxx(unsigned long long, simple_strtoull, "%llx",   16);
704 	test_simple_strtoxx(unsigned long long, simple_strtoull, "0x%llx", 16);
705 	test_simple_strtoxx(unsigned long long, simple_strtoull, "0x%llx", 0);
706 }
707 
708 static void test_simple_strtoll(struct kunit *test)
709 {
710 	test_simple_strtoxx(long long, simple_strtoll, "%lld",	 10);
711 	test_simple_strtoxx(long long, simple_strtoll, "%lld",	 0);
712 	test_simple_strtoxx(long long, simple_strtoll, "%llx",	 16);
713 	test_simple_strtoxx(long long, simple_strtoll, "0x%llx", 16);
714 	test_simple_strtoxx(long long, simple_strtoll, "0x%llx", 0);
715 }
716 
717 static void test_simple_strtoul(struct kunit *test)
718 {
719 	test_simple_strtoxx(unsigned long, simple_strtoul, "%lu",   10);
720 	test_simple_strtoxx(unsigned long, simple_strtoul, "%lu",   0);
721 	test_simple_strtoxx(unsigned long, simple_strtoul, "%lx",   16);
722 	test_simple_strtoxx(unsigned long, simple_strtoul, "0x%lx", 16);
723 	test_simple_strtoxx(unsigned long, simple_strtoul, "0x%lx", 0);
724 }
725 
726 static void test_simple_strtol(struct kunit *test)
727 {
728 	test_simple_strtoxx(long, simple_strtol, "%ld",   10);
729 	test_simple_strtoxx(long, simple_strtol, "%ld",   0);
730 	test_simple_strtoxx(long, simple_strtol, "%lx",   16);
731 	test_simple_strtoxx(long, simple_strtol, "0x%lx", 16);
732 	test_simple_strtoxx(long, simple_strtol, "0x%lx", 0);
733 }
734 
735 /* Selection of common delimiters/separators between numbers in a string. */
736 static const char * const number_delimiters[] = {
737 	" ", ":", ",", "-", "/",
738 };
739 
740 static void test_numbers(struct kunit *test)
741 {
742 	int i;
743 
744 	/* String containing only one number. */
745 	numbers_simple(test);
746 
747 	/* String with multiple numbers separated by delimiter. */
748 	for (i = 0; i < ARRAY_SIZE(number_delimiters); i++) {
749 		numbers_list(test, number_delimiters[i]);
750 
751 		/* Field width may be longer than actual field digits. */
752 		numbers_list_field_width_typemax(test, number_delimiters[i]);
753 
754 		/* Each field width exactly length of actual field digits. */
755 		numbers_list_field_width_val_width(test, number_delimiters[i]);
756 	}
757 
758 	/* Slice continuous sequence of digits using field widths. */
759 	numbers_slice(test);
760 
761 	numbers_prefix_overflow(test);
762 }
763 
764 static void scanf_test(struct kunit *test)
765 {
766 	test_buffer = kmalloc(BUF_SIZE, GFP_KERNEL);
767 	if (!test_buffer)
768 		return;
769 
770 	fmt_buffer = kmalloc(BUF_SIZE, GFP_KERNEL);
771 	if (!fmt_buffer) {
772 		kfree(test_buffer);
773 		return;
774 	}
775 
776 	prandom_seed_state(&rnd_state, 3141592653589793238ULL);
777 
778 	test_numbers(test);
779 
780 	test_simple_strtoull(test);
781 	test_simple_strtoll(test);
782 	test_simple_strtoul(test);
783 	test_simple_strtol(test);
784 
785 	kfree(fmt_buffer);
786 	kfree(test_buffer);
787 }
788 
789 static struct kunit_case scanf_test_cases[] = {
790 	KUNIT_CASE(scanf_test),
791 	{}
792 };
793 
794 static struct kunit_suite scanf_test_suite = {
795 	.name = "scanf",
796 	.test_cases = scanf_test_cases,
797 };
798 
799 kunit_test_suite(scanf_test_suite);
800 
801 MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
802 MODULE_DESCRIPTION("Test cases for sscanf facility");
803 MODULE_LICENSE("GPL v2");
804