cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

test_scanf.c (29596B)


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