brintos

brintos / linux-shallow public Read only

0
0
Text · 29.0 KiB · 7257b17 Raw
815 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Test cases for sscanf facility.4 */5 6#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt7 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 102421 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) __init31_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 than267 * 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 get293 * 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 string334 * 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 == 64473	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#else480	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#endif487}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 the521 * 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 the584 * 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, containing597 * numbers of varying length, using the field width to extract each group598 * of digits. For example the hex values c0,3,bf01,303 would have a599 * 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] = { (T)~expect[0], (T)~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 scanning622	 * 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 should638	 * convert. Next field scan starts at the 'x' which isn't a digit so639	 * 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 field654	 * 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 field665	 * converts to 0. Next field scan starts at the character after "0x",666	 * which will convert if can be interpreted as decimal but will fail667	 * 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_DESCRIPTION("Test cases for sscanf facility");814MODULE_LICENSE("GPL v2");815