xref: /linux/lib/test_scanf.c (revision 92382d74)
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 
22 KSTM_MODULE_GLOBALS();
23 static char *test_buffer __initdata;
24 static char *fmt_buffer __initdata;
25 static struct rnd_state rnd_state __initdata;
26 
27 typedef int (*check_fn)(const void *check_data, const char *string,
28 			const char *fmt, int n_args, va_list ap);
29 
30 static void __scanf(4, 6) __init
_test(check_fn fn,const void * check_data,const char * string,const char * fmt,int n_args,...)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 
58 fail:
59 	failed_tests++;
60 	va_end(ap);
61 }
62 
63 #define _check_numbers_template(arg_fmt, expect, str, fmt, n_args, ap)		\
64 do {										\
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 
check_ull(const void * check_data,const char * string,const char * fmt,int n_args,va_list ap)78 static 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 
check_ll(const void * check_data,const char * string,const char * fmt,int n_args,va_list ap)86 static 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 
check_ulong(const void * check_data,const char * string,const char * fmt,int n_args,va_list ap)94 static 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 
check_long(const void * check_data,const char * string,const char * fmt,int n_args,va_list ap)102 static 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 
check_uint(const void * check_data,const char * string,const char * fmt,int n_args,va_list ap)110 static 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 
check_int(const void * check_data,const char * string,const char * fmt,int n_args,va_list ap)118 static 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 
check_ushort(const void * check_data,const char * string,const char * fmt,int n_args,va_list ap)126 static 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 
check_short(const void * check_data,const char * string,const char * fmt,int n_args,va_list ap)134 static 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 
check_uchar(const void * check_data,const char * string,const char * fmt,int n_args,va_list ap)142 static 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 
check_char(const void * check_data,const char * string,const char * fmt,int n_args,va_list ap)150 static 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 */
159 static 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)			\
194 do {									\
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)			\
203 do {									\
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 
numbers_simple(void)217 static 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  */
next_test_random(u32 max_bits)270 static 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 
next_test_random_ull(void)277 static 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)							\
298 do {										\
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  */
314 static int __init __printf(4, 5)
append_fmt(char * buf,int * buf_pos,int buf_len,const char * val_fmt,...)315 append_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  */
append_delim(char * str_buf,int * str_buf_pos,int str_buf_len,char * fmt_buf,int * fmt_buf_pos,int fmt_buf_len,const char * delim_str)336 static 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)				\
345 do {										\
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)			\
353 do {										\
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)	\
373 do {										\
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)		\
381 do {										\
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 
numbers_list_ll(const char * delim)401 static 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 
numbers_list_l(const char * delim)411 static 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 
numbers_list_d(const char * delim)421 static 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 
numbers_list_h(const char * delim)431 static 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 
numbers_list_hh(const char * delim)441 static 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 
numbers_list(const char * delim)451 static 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 
numbers_list_field_width_ll(const char * delim)460 static 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 
numbers_list_field_width_l(const char * delim)470 static 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 
numbers_list_field_width_d(const char * delim)489 static 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 
numbers_list_field_width_h(const char * delim)499 static 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 
numbers_list_field_width_hh(const char * delim)509 static 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  */
numbers_list_field_width_typemax(const char * delim)523 static 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 
numbers_list_field_width_val_ll(const char * delim)532 static 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 
numbers_list_field_width_val_l(const char * delim)542 static 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 
numbers_list_field_width_val_d(const char * delim)552 static 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 
numbers_list_field_width_val_h(const char * delim)562 static 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 
numbers_list_field_width_val_hh(const char * delim)572 static 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  */
numbers_list_field_width_val_width(const char * delim)586 static 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  */
numbers_slice(void)601 static 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)	\
607 do {										\
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  */
numbers_prefix_overflow(void)618 static 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)			\
683 do {										\
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)				\
709 do {										\
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 
test_simple_strtoull(void)721 static 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 
test_simple_strtoll(void)730 static 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 
test_simple_strtoul(void)739 static 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 
test_simple_strtol(void)748 static 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. */
758 static const char * const number_delimiters[] __initconst = {
759 	" ", ":", ",", "-", "/",
760 };
761 
test_numbers(void)762 static 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 
selftest(void)786 static 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 
811 KSTM_MODULE_LOADERS(test_scanf);
812 MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
813 MODULE_LICENSE("GPL v2");
814