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_DESCRIPTION("Test cases for sscanf facility");
814 MODULE_LICENSE("GPL v2");
815