File Index
Files and directories
Sign in
FILE

scanf_kunit.c

File preview with syntax highlighting.

linux-6.19.14/lib/tests/scanf_kunit.c C
  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
 17static char *test_buffer;
 18static char *fmt_buffer;
 19static struct rnd_state rnd_state;
 20
 21typedef 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
 25static 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)		\
 48do {										\
 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
 60static 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
 68static 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
 76static 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
 85static 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
 93static 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
101static 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
109static 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
118static 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
127static 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
136static 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 */
145static 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)			\
180do {									\
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)			\
189do {									\
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
203static 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 */
256static 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
263static 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)							\
284do {										\
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 */
300static int __printf(4, 5)
301append_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 */
322static 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)				\
331do {										\
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)			\
339do {										\
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)	\
359do {										\
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)		\
367do {										\
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
387static 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
397static 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
407static 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
417static 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
427static 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
437static void numbers_list(struct kunit *test)
438{
439	const char * const *param = test->param_value;
440	const char *delim = *param;
441
442	numbers_list_ll(test, delim);
443	numbers_list_l(test, delim);
444	numbers_list_d(test, delim);
445	numbers_list_h(test, delim);
446	numbers_list_hh(test, delim);
447}
448
449static void numbers_list_field_width_ll(struct kunit *test, const char *delim)
450{
451	numbers_list_fix_width(unsigned long long, "%llu",   delim, 20, "llu", check_ull);
452	numbers_list_fix_width(long long,	   "%lld",   delim, 20, "lld", check_ll);
453	numbers_list_fix_width(long long,	   "%lld",   delim, 20, "lli", check_ll);
454	numbers_list_fix_width(unsigned long long, "%llx",   delim, 16, "llx", check_ull);
455	numbers_list_fix_width(unsigned long long, "0x%llx", delim, 18, "llx", check_ull);
456	numbers_list_fix_width(long long,	   "0x%llx", delim, 18, "lli", check_ll);
457}
458
459static void numbers_list_field_width_l(struct kunit *test, const char *delim)
460{
461#if BITS_PER_LONG == 64
462	numbers_list_fix_width(unsigned long,	"%lu",	     delim, 20, "lu", check_ulong);
463	numbers_list_fix_width(long,		"%ld",	     delim, 20, "ld", check_long);
464	numbers_list_fix_width(long,		"%ld",	     delim, 20, "li", check_long);
465	numbers_list_fix_width(unsigned long,	"%lx",	     delim, 16, "lx", check_ulong);
466	numbers_list_fix_width(unsigned long,	"0x%lx",     delim, 18, "lx", check_ulong);
467	numbers_list_fix_width(long,		"0x%lx",     delim, 18, "li", check_long);
468#else
469	numbers_list_fix_width(unsigned long,	"%lu",	     delim, 10, "lu", check_ulong);
470	numbers_list_fix_width(long,		"%ld",	     delim, 11, "ld", check_long);
471	numbers_list_fix_width(long,		"%ld",	     delim, 11, "li", check_long);
472	numbers_list_fix_width(unsigned long,	"%lx",	     delim, 8,  "lx", check_ulong);
473	numbers_list_fix_width(unsigned long,	"0x%lx",     delim, 10, "lx", check_ulong);
474	numbers_list_fix_width(long,		"0x%lx",     delim, 10, "li", check_long);
475#endif
476}
477
478static void numbers_list_field_width_d(struct kunit *test, const char *delim)
479{
480	numbers_list_fix_width(unsigned int,	"%u",	     delim, 10, "u", check_uint);
481	numbers_list_fix_width(int,		"%d",	     delim, 11, "d", check_int);
482	numbers_list_fix_width(int,		"%d",	     delim, 11, "i", check_int);
483	numbers_list_fix_width(unsigned int,	"%x",	     delim, 8,  "x", check_uint);
484	numbers_list_fix_width(unsigned int,	"0x%x",	     delim, 10, "x", check_uint);
485	numbers_list_fix_width(int,		"0x%x",	     delim, 10, "i", check_int);
486}
487
488static void numbers_list_field_width_h(struct kunit *test, const char *delim)
489{
490	numbers_list_fix_width(unsigned short,	"%hu",	     delim, 5, "hu", check_ushort);
491	numbers_list_fix_width(short,		"%hd",	     delim, 6, "hd", check_short);
492	numbers_list_fix_width(short,		"%hd",	     delim, 6, "hi", check_short);
493	numbers_list_fix_width(unsigned short,	"%hx",	     delim, 4, "hx", check_ushort);
494	numbers_list_fix_width(unsigned short,	"0x%hx",     delim, 6, "hx", check_ushort);
495	numbers_list_fix_width(short,		"0x%hx",     delim, 6, "hi", check_short);
496}
497
498static void numbers_list_field_width_hh(struct kunit *test, const char *delim)
499{
500	numbers_list_fix_width(unsigned char,	"%hhu",	     delim, 3, "hhu", check_uchar);
501	numbers_list_fix_width(signed char,	"%hhd",	     delim, 4, "hhd", check_char);
502	numbers_list_fix_width(signed char,	"%hhd",	     delim, 4, "hhi", check_char);
503	numbers_list_fix_width(unsigned char,	"%hhx",	     delim, 2, "hhx", check_uchar);
504	numbers_list_fix_width(unsigned char,	"0x%hhx",    delim, 4, "hhx", check_uchar);
505	numbers_list_fix_width(signed char,	"0x%hhx",    delim, 4, "hhi", check_char);
506}
507
508/*
509 * List of numbers separated by delim. Each field width specifier is the
510 * maximum possible digits for the given type and base.
511 */
512static void numbers_list_field_width_typemax(struct kunit *test)
513{
514	const char * const *param = test->param_value;
515	const char *delim = *param;
516
517	numbers_list_field_width_ll(test, delim);
518	numbers_list_field_width_l(test, delim);
519	numbers_list_field_width_d(test, delim);
520	numbers_list_field_width_h(test, delim);
521	numbers_list_field_width_hh(test, delim);
522}
523
524static void numbers_list_field_width_val_ll(struct kunit *test, const char *delim)
525{
526	numbers_list_val_width(unsigned long long, "%llu",   delim, "llu", check_ull);
527	numbers_list_val_width(long long,	   "%lld",   delim, "lld", check_ll);
528	numbers_list_val_width(long long,	   "%lld",   delim, "lli", check_ll);
529	numbers_list_val_width(unsigned long long, "%llx",   delim, "llx", check_ull);
530	numbers_list_val_width(unsigned long long, "0x%llx", delim, "llx", check_ull);
531	numbers_list_val_width(long long,	   "0x%llx", delim, "lli", check_ll);
532}
533
534static void numbers_list_field_width_val_l(struct kunit *test, const char *delim)
535{
536	numbers_list_val_width(unsigned long,	"%lu",	     delim, "lu", check_ulong);
537	numbers_list_val_width(long,		"%ld",	     delim, "ld", check_long);
538	numbers_list_val_width(long,		"%ld",	     delim, "li", check_long);
539	numbers_list_val_width(unsigned long,	"%lx",	     delim, "lx", check_ulong);
540	numbers_list_val_width(unsigned long,	"0x%lx",     delim, "lx", check_ulong);
541	numbers_list_val_width(long,		"0x%lx",     delim, "li", check_long);
542}
543
544static void numbers_list_field_width_val_d(struct kunit *test, const char *delim)
545{
546	numbers_list_val_width(unsigned int,	"%u",	     delim, "u", check_uint);
547	numbers_list_val_width(int,		"%d",	     delim, "d", check_int);
548	numbers_list_val_width(int,		"%d",	     delim, "i", check_int);
549	numbers_list_val_width(unsigned int,	"%x",	     delim, "x", check_uint);
550	numbers_list_val_width(unsigned int,	"0x%x",	     delim, "x", check_uint);
551	numbers_list_val_width(int,		"0x%x",	     delim, "i", check_int);
552}
553
554static void numbers_list_field_width_val_h(struct kunit *test, const char *delim)
555{
556	numbers_list_val_width(unsigned short,	"%hu",	     delim, "hu", check_ushort);
557	numbers_list_val_width(short,		"%hd",	     delim, "hd", check_short);
558	numbers_list_val_width(short,		"%hd",	     delim, "hi", check_short);
559	numbers_list_val_width(unsigned short,	"%hx",	     delim, "hx", check_ushort);
560	numbers_list_val_width(unsigned short,	"0x%hx",     delim, "hx", check_ushort);
561	numbers_list_val_width(short,		"0x%hx",     delim, "hi", check_short);
562}
563
564static void numbers_list_field_width_val_hh(struct kunit *test, const char *delim)
565{
566	numbers_list_val_width(unsigned char,	"%hhu",	     delim, "hhu", check_uchar);
567	numbers_list_val_width(signed char,	"%hhd",	     delim, "hhd", check_char);
568	numbers_list_val_width(signed char,	"%hhd",	     delim, "hhi", check_char);
569	numbers_list_val_width(unsigned char,	"%hhx",	     delim, "hhx", check_uchar);
570	numbers_list_val_width(unsigned char,	"0x%hhx",    delim, "hhx", check_uchar);
571	numbers_list_val_width(signed char,	"0x%hhx",    delim, "hhi", check_char);
572}
573
574/*
575 * List of numbers separated by delim. Each field width specifier is the
576 * exact length of the corresponding value digits in the string being scanned.
577 */
578static void numbers_list_field_width_val_width(struct kunit *test)
579{
580	const char * const *param = test->param_value;
581	const char *delim = *param;
582
583	numbers_list_field_width_val_ll(test, delim);
584	numbers_list_field_width_val_l(test, delim);
585	numbers_list_field_width_val_d(test, delim);
586	numbers_list_field_width_val_h(test, delim);
587	numbers_list_field_width_val_hh(test, delim);
588}
589
590/*
591 * Slice a continuous string of digits without field delimiters, containing
592 * numbers of varying length, using the field width to extract each group
593 * of digits. For example the hex values c0,3,bf01,303 would have a
594 * string representation of "c03bf01303" and extracted with "%2x%1x%4x%3x".
595 */
596static void numbers_slice(struct kunit *test)
597{
598	const char *delim = "";
599
600	KUNIT_ASSERT_PTR_EQ(test, test->param_value, NULL);
601	test->param_value = &delim;
602
603	numbers_list_field_width_val_width(test);
604}
605
606#define test_number_prefix(T, str, scan_fmt, expect0, expect1, n_args, fn)	\
607do {										\
608	const T expect[2] = { expect0, expect1 };				\
609	T result[2] = { (T)~expect[0], (T)~expect[1] };				\
610										\
611	_test(test, __FILE__, __LINE__, fn, &expect, str, scan_fmt, n_args, &result[0], &result[1]);\
612} while (0)
613
614/*
615 * Number prefix is >= field width.
616 * Expected behaviour is derived from testing userland sscanf.
617 */
618static void numbers_prefix_overflow(struct kunit *test)
619{
620	/*
621	 * Negative decimal with a field of width 1, should quit scanning
622	 * and return 0.
623	 */
624	test_number_prefix(long long,	"-1 1", "%1lld %lld",	0, 0, 0, check_ll);
625	test_number_prefix(long,	"-1 1", "%1ld %ld",	0, 0, 0, check_long);
626	test_number_prefix(int,		"-1 1", "%1d %d",	0, 0, 0, check_int);
627	test_number_prefix(short,	"-1 1", "%1hd %hd",	0, 0, 0, check_short);
628	test_number_prefix(signed char,	"-1 1", "%1hhd %hhd",	0, 0, 0, check_char);
629
630	test_number_prefix(long long,	"-1 1", "%1lli %lli",	0, 0, 0, check_ll);
631	test_number_prefix(long,	"-1 1", "%1li %li",	0, 0, 0, check_long);
632	test_number_prefix(int,		"-1 1", "%1i %i",	0, 0, 0, check_int);
633	test_number_prefix(short,	"-1 1", "%1hi %hi",	0, 0, 0, check_short);
634	test_number_prefix(signed char,	"-1 1", "%1hhi %hhi",	0, 0, 0, check_char);
635
636	/*
637	 * 0x prefix in a field of width 1: 0 is a valid digit so should
638	 * convert. Next field scan starts at the 'x' which isn't a digit so
639	 * scan quits with one field converted.
640	 */
641	test_number_prefix(unsigned long long,	"0xA7", "%1llx%llx", 0, 0, 1, check_ull);
642	test_number_prefix(unsigned long,	"0xA7", "%1lx%lx",   0, 0, 1, check_ulong);
643	test_number_prefix(unsigned int,	"0xA7", "%1x%x",     0, 0, 1, check_uint);
644	test_number_prefix(unsigned short,	"0xA7", "%1hx%hx",   0, 0, 1, check_ushort);
645	test_number_prefix(unsigned char,	"0xA7", "%1hhx%hhx", 0, 0, 1, check_uchar);
646	test_number_prefix(long long,		"0xA7", "%1lli%llx", 0, 0, 1, check_ll);
647	test_number_prefix(long,		"0xA7", "%1li%lx",   0, 0, 1, check_long);
648	test_number_prefix(int,			"0xA7", "%1i%x",     0, 0, 1, check_int);
649	test_number_prefix(short,		"0xA7", "%1hi%hx",   0, 0, 1, check_short);
650	test_number_prefix(char,		"0xA7", "%1hhi%hhx", 0, 0, 1, check_char);
651
652	/*
653	 * 0x prefix in a field of width 2 using %x conversion: first field
654	 * converts to 0. Next field scan starts at the character after "0x".
655	 * Both fields will convert.
656	 */
657	test_number_prefix(unsigned long long,	"0xA7", "%2llx%llx", 0, 0xa7, 2, check_ull);
658	test_number_prefix(unsigned long,	"0xA7", "%2lx%lx",   0, 0xa7, 2, check_ulong);
659	test_number_prefix(unsigned int,	"0xA7", "%2x%x",     0, 0xa7, 2, check_uint);
660	test_number_prefix(unsigned short,	"0xA7", "%2hx%hx",   0, 0xa7, 2, check_ushort);
661	test_number_prefix(unsigned char,	"0xA7", "%2hhx%hhx", 0, 0xa7, 2, check_uchar);
662
663	/*
664	 * 0x prefix in a field of width 2 using %i conversion: first field
665	 * converts to 0. Next field scan starts at the character after "0x",
666	 * which will convert if can be interpreted as decimal but will fail
667	 * if it contains any hex digits (since no 0x prefix).
668	 */
669	test_number_prefix(long long,	"0x67", "%2lli%lli", 0, 67, 2, check_ll);
670	test_number_prefix(long,	"0x67", "%2li%li",   0, 67, 2, check_long);
671	test_number_prefix(int,		"0x67", "%2i%i",     0, 67, 2, check_int);
672	test_number_prefix(short,	"0x67", "%2hi%hi",   0, 67, 2, check_short);
673	test_number_prefix(char,	"0x67", "%2hhi%hhi", 0, 67, 2, check_char);
674
675	test_number_prefix(long long,	"0xA7", "%2lli%lli", 0, 0,  1, check_ll);
676	test_number_prefix(long,	"0xA7", "%2li%li",   0, 0,  1, check_long);
677	test_number_prefix(int,		"0xA7", "%2i%i",     0, 0,  1, check_int);
678	test_number_prefix(short,	"0xA7", "%2hi%hi",   0, 0,  1, check_short);
679	test_number_prefix(char,	"0xA7", "%2hhi%hhi", 0, 0,  1, check_char);
680}
681
682#define _test_simple_strtoxx(T, fn, gen_fmt, expect, base)			\
683do {										\
684	T got;									\
685	char *endp;								\
686	int len;								\
687										\
688	len = snprintf(test_buffer, BUF_SIZE, gen_fmt, expect);			\
689	got = (fn)(test_buffer, &endp, base);					\
690	if (got != (expect)) {							\
691		KUNIT_FAIL(test, #fn "(\"%s\", %d): got " gen_fmt " expected " gen_fmt, \
692			   test_buffer, base, got, expect);			\
693	} else if (endp != test_buffer + len) {					\
694		KUNIT_FAIL(test, #fn "(\"%s\", %d) startp=0x%px got endp=0x%px expected 0x%px", \
695			   test_buffer, base, test_buffer,			\
696			   test_buffer + len, endp);				\
697	}									\
698} while (0)
699
700#define test_simple_strtoxx(T, fn, gen_fmt, base)				\
701do {										\
702	int i;									\
703										\
704	for (i = 0; i < ARRAY_SIZE(numbers); i++) {				\
705		_test_simple_strtoxx(T, fn, gen_fmt, (T)numbers[i], base);	\
706										\
707		if (is_signed_type(T))						\
708			_test_simple_strtoxx(T, fn, gen_fmt,			\
709					      -(T)numbers[i], base);		\
710	}									\
711} while (0)
712
713static void test_simple_strtoull(struct kunit *test)
714{
715	test_simple_strtoxx(unsigned long long, simple_strtoull, "%llu",   10);
716	test_simple_strtoxx(unsigned long long, simple_strtoull, "%llu",   0);
717	test_simple_strtoxx(unsigned long long, simple_strtoull, "%llx",   16);
718	test_simple_strtoxx(unsigned long long, simple_strtoull, "0x%llx", 16);
719	test_simple_strtoxx(unsigned long long, simple_strtoull, "0x%llx", 0);
720}
721
722static void test_simple_strtoll(struct kunit *test)
723{
724	test_simple_strtoxx(long long, simple_strtoll, "%lld",	 10);
725	test_simple_strtoxx(long long, simple_strtoll, "%lld",	 0);
726	test_simple_strtoxx(long long, simple_strtoll, "%llx",	 16);
727	test_simple_strtoxx(long long, simple_strtoll, "0x%llx", 16);
728	test_simple_strtoxx(long long, simple_strtoll, "0x%llx", 0);
729}
730
731static void test_simple_strtoul(struct kunit *test)
732{
733	test_simple_strtoxx(unsigned long, simple_strtoul, "%lu",   10);
734	test_simple_strtoxx(unsigned long, simple_strtoul, "%lu",   0);
735	test_simple_strtoxx(unsigned long, simple_strtoul, "%lx",   16);
736	test_simple_strtoxx(unsigned long, simple_strtoul, "0x%lx", 16);
737	test_simple_strtoxx(unsigned long, simple_strtoul, "0x%lx", 0);
738}
739
740static void test_simple_strtol(struct kunit *test)
741{
742	test_simple_strtoxx(long, simple_strtol, "%ld",   10);
743	test_simple_strtoxx(long, simple_strtol, "%ld",   0);
744	test_simple_strtoxx(long, simple_strtol, "%lx",   16);
745	test_simple_strtoxx(long, simple_strtol, "0x%lx", 16);
746	test_simple_strtoxx(long, simple_strtol, "0x%lx", 0);
747}
748
749/* Selection of common delimiters/separators between numbers in a string. */
750static const char * const number_delimiters[] = {
751	" ", ":", ",", "-", "/",
752};
753
754static void number_delimiter_param_desc(const char * const *param,
755					   char *desc)
756{
757	snprintf(desc, KUNIT_PARAM_DESC_SIZE, "\"%s\"", *param);
758}
759
760KUNIT_ARRAY_PARAM(number_delimiters, number_delimiters, number_delimiter_param_desc);
761
762static struct kunit_case scanf_test_cases[] = {
763	KUNIT_CASE(numbers_simple),
764	/* String with multiple numbers separated by delimiter. */
765	KUNIT_CASE_PARAM(numbers_list, number_delimiters_gen_params),
766	/* Field width may be longer than actual field digits. */
767	KUNIT_CASE_PARAM(numbers_list_field_width_typemax, number_delimiters_gen_params),
768	/* Each field width exactly length of actual field digits. */
769	KUNIT_CASE_PARAM(numbers_list_field_width_val_width, number_delimiters_gen_params),
770	/* Slice continuous sequence of digits using field widths. */
771	KUNIT_CASE(numbers_slice),
772	KUNIT_CASE(numbers_prefix_overflow),
773
774	KUNIT_CASE(test_simple_strtoull),
775	KUNIT_CASE(test_simple_strtoll),
776	KUNIT_CASE(test_simple_strtoul),
777	KUNIT_CASE(test_simple_strtol),
778	{}
779};
780
781static int scanf_suite_init(struct kunit_suite *suite)
782{
783	test_buffer = kmalloc(BUF_SIZE, GFP_KERNEL);
784	if (!test_buffer)
785		return -ENOMEM;
786
787	fmt_buffer = kmalloc(BUF_SIZE, GFP_KERNEL);
788	if (!fmt_buffer) {
789		kfree(test_buffer);
790		return -ENOMEM;
791	}
792
793	prandom_seed_state(&rnd_state, 3141592653589793238ULL);
794
795	return 0;
796}
797
798static void scanf_suite_exit(struct kunit_suite *suite)
799{
800	kfree(fmt_buffer);
801	kfree(test_buffer);
802}
803
804static struct kunit_suite scanf_test_suite = {
805	.name = "scanf",
806	.suite_init = scanf_suite_init,
807	.suite_exit = scanf_suite_exit,
808	.test_cases = scanf_test_cases,
809};
810
811kunit_test_suite(scanf_test_suite);
812
813MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
814MODULE_DESCRIPTION("Test cases for sscanf facility");
815MODULE_LICENSE("GPL v2");
~/ Read-only file preview.