Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Test cases for sscanf facility.
0004  */
0005 
0006 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0007 
0008 #include <linux/bitops.h>
0009 #include <linux/init.h>
0010 #include <linux/kernel.h>
0011 #include <linux/module.h>
0012 #include <linux/overflow.h>
0013 #include <linux/printk.h>
0014 #include <linux/random.h>
0015 #include <linux/slab.h>
0016 #include <linux/string.h>
0017 
0018 #include "../tools/testing/selftests/kselftest_module.h"
0019 
0020 #define BUF_SIZE 1024
0021 
0022 KSTM_MODULE_GLOBALS();
0023 static char *test_buffer __initdata;
0024 static char *fmt_buffer __initdata;
0025 static struct rnd_state rnd_state __initdata;
0026 
0027 typedef int (*check_fn)(const void *check_data, const char *string,
0028             const char *fmt, int n_args, va_list ap);
0029 
0030 static void __scanf(4, 6) __init
0031 _test(check_fn fn, const void *check_data, const char *string, const char *fmt,
0032     int n_args, ...)
0033 {
0034     va_list ap, ap_copy;
0035     int ret;
0036 
0037     total_tests++;
0038 
0039     va_start(ap, n_args);
0040     va_copy(ap_copy, ap);
0041     ret = vsscanf(string, fmt, ap_copy);
0042     va_end(ap_copy);
0043 
0044     if (ret != n_args) {
0045         pr_warn("vsscanf(\"%s\", \"%s\", ...) returned %d expected %d\n",
0046             string, fmt, ret, n_args);
0047         goto fail;
0048     }
0049 
0050     ret = (*fn)(check_data, string, fmt, n_args, ap);
0051     if (ret)
0052         goto fail;
0053 
0054     va_end(ap);
0055 
0056     return;
0057 
0058 fail:
0059     failed_tests++;
0060     va_end(ap);
0061 }
0062 
0063 #define _check_numbers_template(arg_fmt, expect, str, fmt, n_args, ap)      \
0064 do {                                        \
0065     pr_debug("\"%s\", \"%s\" ->\n", str, fmt);              \
0066     for (; n_args > 0; n_args--, expect++) {                \
0067         typeof(*expect) got = *va_arg(ap, typeof(expect));      \
0068         pr_debug("\t" arg_fmt "\n", got);               \
0069         if (got != *expect) {                       \
0070             pr_warn("vsscanf(\"%s\", \"%s\", ...) expected " arg_fmt " got " arg_fmt "\n", \
0071                 str, fmt, *expect, got);            \
0072             return 1;                       \
0073         }                               \
0074     }                                   \
0075     return 0;                               \
0076 } while (0)
0077 
0078 static int __init check_ull(const void *check_data, const char *string,
0079                 const char *fmt, int n_args, va_list ap)
0080 {
0081     const unsigned long long *pval = check_data;
0082 
0083     _check_numbers_template("%llu", pval, string, fmt, n_args, ap);
0084 }
0085 
0086 static int __init check_ll(const void *check_data, const char *string,
0087                const char *fmt, int n_args, va_list ap)
0088 {
0089     const long long *pval = check_data;
0090 
0091     _check_numbers_template("%lld", pval, string, fmt, n_args, ap);
0092 }
0093 
0094 static int __init check_ulong(const void *check_data, const char *string,
0095                const char *fmt, int n_args, va_list ap)
0096 {
0097     const unsigned long *pval = check_data;
0098 
0099     _check_numbers_template("%lu", pval, string, fmt, n_args, ap);
0100 }
0101 
0102 static int __init check_long(const void *check_data, const char *string,
0103               const char *fmt, int n_args, va_list ap)
0104 {
0105     const long *pval = check_data;
0106 
0107     _check_numbers_template("%ld", pval, string, fmt, n_args, ap);
0108 }
0109 
0110 static int __init check_uint(const void *check_data, const char *string,
0111                  const char *fmt, int n_args, va_list ap)
0112 {
0113     const unsigned int *pval = check_data;
0114 
0115     _check_numbers_template("%u", pval, string, fmt, n_args, ap);
0116 }
0117 
0118 static int __init check_int(const void *check_data, const char *string,
0119                 const char *fmt, int n_args, va_list ap)
0120 {
0121     const int *pval = check_data;
0122 
0123     _check_numbers_template("%d", pval, string, fmt, n_args, ap);
0124 }
0125 
0126 static int __init check_ushort(const void *check_data, const char *string,
0127                    const char *fmt, int n_args, va_list ap)
0128 {
0129     const unsigned short *pval = check_data;
0130 
0131     _check_numbers_template("%hu", pval, string, fmt, n_args, ap);
0132 }
0133 
0134 static int __init check_short(const void *check_data, const char *string,
0135                    const char *fmt, int n_args, va_list ap)
0136 {
0137     const short *pval = check_data;
0138 
0139     _check_numbers_template("%hd", pval, string, fmt, n_args, ap);
0140 }
0141 
0142 static int __init check_uchar(const void *check_data, const char *string,
0143                    const char *fmt, int n_args, va_list ap)
0144 {
0145     const unsigned char *pval = check_data;
0146 
0147     _check_numbers_template("%hhu", pval, string, fmt, n_args, ap);
0148 }
0149 
0150 static int __init check_char(const void *check_data, const char *string,
0151                    const char *fmt, int n_args, va_list ap)
0152 {
0153     const signed char *pval = check_data;
0154 
0155     _check_numbers_template("%hhd", pval, string, fmt, n_args, ap);
0156 }
0157 
0158 /* Selection of interesting numbers to test, copied from test-kstrtox.c */
0159 static const unsigned long long numbers[] __initconst = {
0160     0x0ULL,
0161     0x1ULL,
0162     0x7fULL,
0163     0x80ULL,
0164     0x81ULL,
0165     0xffULL,
0166     0x100ULL,
0167     0x101ULL,
0168     0x7fffULL,
0169     0x8000ULL,
0170     0x8001ULL,
0171     0xffffULL,
0172     0x10000ULL,
0173     0x10001ULL,
0174     0x7fffffffULL,
0175     0x80000000ULL,
0176     0x80000001ULL,
0177     0xffffffffULL,
0178     0x100000000ULL,
0179     0x100000001ULL,
0180     0x7fffffffffffffffULL,
0181     0x8000000000000000ULL,
0182     0x8000000000000001ULL,
0183     0xfffffffffffffffeULL,
0184     0xffffffffffffffffULL,
0185 };
0186 
0187 #define value_representable_in_type(T, val)                  \
0188 (is_signed_type(T)                               \
0189     ? ((long long)(val) >= type_min(T)) && ((long long)(val) <= type_max(T)) \
0190     : ((unsigned long long)(val) <= type_max(T)))
0191 
0192 
0193 #define test_one_number(T, gen_fmt, scan_fmt, val, fn)          \
0194 do {                                    \
0195     const T expect_val = (T)(val);                  \
0196     T result = ~expect_val; /* should be overwritten */     \
0197                                     \
0198     snprintf(test_buffer, BUF_SIZE, gen_fmt, expect_val);       \
0199     _test(fn, &expect_val, test_buffer, "%" scan_fmt, 1, &result);  \
0200 } while (0)
0201 
0202 #define simple_numbers_loop(T, gen_fmt, scan_fmt, fn)           \
0203 do {                                    \
0204     int i;                              \
0205                                     \
0206     for (i = 0; i < ARRAY_SIZE(numbers); i++) {         \
0207         if (value_representable_in_type(T, numbers[i]))     \
0208             test_one_number(T, gen_fmt, scan_fmt,       \
0209                     numbers[i], fn);        \
0210                                     \
0211         if (value_representable_in_type(T, -numbers[i]))    \
0212             test_one_number(T, gen_fmt, scan_fmt,       \
0213                     -numbers[i], fn);       \
0214     }                               \
0215 } while (0)
0216 
0217 static void __init numbers_simple(void)
0218 {
0219     simple_numbers_loop(unsigned long long, "%llu",   "llu", check_ull);
0220     simple_numbers_loop(long long,      "%lld",   "lld", check_ll);
0221     simple_numbers_loop(long long,      "%lld",   "lli", check_ll);
0222     simple_numbers_loop(unsigned long long, "%llx",   "llx", check_ull);
0223     simple_numbers_loop(long long,      "%llx",   "llx", check_ll);
0224     simple_numbers_loop(long long,      "0x%llx", "lli", check_ll);
0225     simple_numbers_loop(unsigned long long, "0x%llx", "llx", check_ull);
0226     simple_numbers_loop(long long,      "0x%llx", "llx", check_ll);
0227 
0228     simple_numbers_loop(unsigned long,  "%lu",    "lu", check_ulong);
0229     simple_numbers_loop(long,       "%ld",    "ld", check_long);
0230     simple_numbers_loop(long,       "%ld",    "li", check_long);
0231     simple_numbers_loop(unsigned long,  "%lx",    "lx", check_ulong);
0232     simple_numbers_loop(long,       "%lx",    "lx", check_long);
0233     simple_numbers_loop(long,       "0x%lx",  "li", check_long);
0234     simple_numbers_loop(unsigned long,  "0x%lx",  "lx", check_ulong);
0235     simple_numbers_loop(long,       "0x%lx",  "lx", check_long);
0236 
0237     simple_numbers_loop(unsigned int,   "%u",     "u", check_uint);
0238     simple_numbers_loop(int,        "%d",     "d", check_int);
0239     simple_numbers_loop(int,        "%d",     "i", check_int);
0240     simple_numbers_loop(unsigned int,   "%x",     "x", check_uint);
0241     simple_numbers_loop(int,        "%x",     "x", check_int);
0242     simple_numbers_loop(int,        "0x%x",   "i", check_int);
0243     simple_numbers_loop(unsigned int,   "0x%x",   "x", check_uint);
0244     simple_numbers_loop(int,        "0x%x",   "x", check_int);
0245 
0246     simple_numbers_loop(unsigned short, "%hu",    "hu", check_ushort);
0247     simple_numbers_loop(short,      "%hd",    "hd", check_short);
0248     simple_numbers_loop(short,      "%hd",    "hi", check_short);
0249     simple_numbers_loop(unsigned short, "%hx",    "hx", check_ushort);
0250     simple_numbers_loop(short,      "%hx",    "hx", check_short);
0251     simple_numbers_loop(short,      "0x%hx",  "hi", check_short);
0252     simple_numbers_loop(unsigned short, "0x%hx",  "hx", check_ushort);
0253     simple_numbers_loop(short,      "0x%hx",  "hx", check_short);
0254 
0255     simple_numbers_loop(unsigned char,  "%hhu",   "hhu", check_uchar);
0256     simple_numbers_loop(signed char,    "%hhd",   "hhd", check_char);
0257     simple_numbers_loop(signed char,    "%hhd",   "hhi", check_char);
0258     simple_numbers_loop(unsigned char,  "%hhx",   "hhx", check_uchar);
0259     simple_numbers_loop(signed char,    "%hhx",   "hhx", check_char);
0260     simple_numbers_loop(signed char,    "0x%hhx", "hhi", check_char);
0261     simple_numbers_loop(unsigned char,  "0x%hhx", "hhx", check_uchar);
0262     simple_numbers_loop(signed char,    "0x%hhx", "hhx", check_char);
0263 }
0264 
0265 /*
0266  * This gives a better variety of number "lengths" in a small sample than
0267  * the raw prandom*() functions (Not mathematically rigorous!!).
0268  * Variabilty of length and value is more important than perfect randomness.
0269  */
0270 static u32 __init next_test_random(u32 max_bits)
0271 {
0272     u32 n_bits = hweight32(prandom_u32_state(&rnd_state)) % (max_bits + 1);
0273 
0274     return prandom_u32_state(&rnd_state) & GENMASK(n_bits, 0);
0275 }
0276 
0277 static unsigned long long __init next_test_random_ull(void)
0278 {
0279     u32 rand1 = prandom_u32_state(&rnd_state);
0280     u32 n_bits = (hweight32(rand1) * 3) % 64;
0281     u64 val = (u64)prandom_u32_state(&rnd_state) * rand1;
0282 
0283     return val & GENMASK_ULL(n_bits, 0);
0284 }
0285 
0286 #define random_for_type(T)              \
0287     ((T)(sizeof(T) <= sizeof(u32)           \
0288         ? next_test_random(BITS_PER_TYPE(T))    \
0289         : next_test_random_ull()))
0290 
0291 /*
0292  * Define a pattern of negative and positive numbers to ensure we get
0293  * some of both within the small number of samples in a test string.
0294  */
0295 #define NEGATIVES_PATTERN 0x3246    /* 00110010 01000110 */
0296 
0297 #define fill_random_array(arr)                          \
0298 do {                                        \
0299     unsigned int neg_pattern = NEGATIVES_PATTERN;               \
0300     int i;                                  \
0301                                         \
0302     for (i = 0; i < ARRAY_SIZE(arr); i++, neg_pattern >>= 1) {      \
0303         (arr)[i] = random_for_type(typeof((arr)[0]));           \
0304         if (is_signed_type(typeof((arr)[0])) && (neg_pattern & 1))  \
0305             (arr)[i] = -(arr)[i];                   \
0306     }                                   \
0307 } while (0)
0308 
0309 /*
0310  * Convenience wrapper around snprintf() to append at buf_pos in buf,
0311  * updating buf_pos and returning the number of characters appended.
0312  * On error buf_pos is not changed and return value is 0.
0313  */
0314 static int __init __printf(4, 5)
0315 append_fmt(char *buf, int *buf_pos, int buf_len, const char *val_fmt, ...)
0316 {
0317     va_list ap;
0318     int field_len;
0319 
0320     va_start(ap, val_fmt);
0321     field_len = vsnprintf(buf + *buf_pos, buf_len - *buf_pos, val_fmt, ap);
0322     va_end(ap);
0323 
0324     if (field_len < 0)
0325         field_len = 0;
0326 
0327     *buf_pos += field_len;
0328 
0329     return field_len;
0330 }
0331 
0332 /*
0333  * Convenience function to append the field delimiter string
0334  * to both the value string and format string buffers.
0335  */
0336 static void __init append_delim(char *str_buf, int *str_buf_pos, int str_buf_len,
0337                 char *fmt_buf, int *fmt_buf_pos, int fmt_buf_len,
0338                 const char *delim_str)
0339 {
0340     append_fmt(str_buf, str_buf_pos, str_buf_len, delim_str);
0341     append_fmt(fmt_buf, fmt_buf_pos, fmt_buf_len, delim_str);
0342 }
0343 
0344 #define test_array_8(fn, check_data, string, fmt, arr)              \
0345 do {                                        \
0346     BUILD_BUG_ON(ARRAY_SIZE(arr) != 8);                 \
0347     _test(fn, check_data, string, fmt, 8,                   \
0348         &(arr)[0], &(arr)[1], &(arr)[2], &(arr)[3],         \
0349         &(arr)[4], &(arr)[5], &(arr)[6], &(arr)[7]);            \
0350 } while (0)
0351 
0352 #define numbers_list_8(T, gen_fmt, field_sep, scan_fmt, fn)         \
0353 do {                                        \
0354     int i, pos = 0, fmt_pos = 0;                        \
0355     T expect[8], result[8];                         \
0356                                         \
0357     fill_random_array(expect);                      \
0358                                         \
0359     for (i = 0; i < ARRAY_SIZE(expect); i++) {              \
0360         if (i != 0)                         \
0361             append_delim(test_buffer, &pos, BUF_SIZE,       \
0362                      fmt_buffer, &fmt_pos, BUF_SIZE,        \
0363                      field_sep);                \
0364                                         \
0365         append_fmt(test_buffer, &pos, BUF_SIZE, gen_fmt, expect[i]);    \
0366         append_fmt(fmt_buffer, &fmt_pos, BUF_SIZE, "%%%s", scan_fmt);   \
0367     }                                   \
0368                                         \
0369     test_array_8(fn, expect, test_buffer, fmt_buffer, result);      \
0370 } while (0)
0371 
0372 #define numbers_list_fix_width(T, gen_fmt, field_sep, width, scan_fmt, fn)  \
0373 do {                                        \
0374     char full_fmt[16];                          \
0375                                         \
0376     snprintf(full_fmt, sizeof(full_fmt), "%u%s", width, scan_fmt);      \
0377     numbers_list_8(T, gen_fmt, field_sep, full_fmt, fn);            \
0378 } while (0)
0379 
0380 #define numbers_list_val_width(T, gen_fmt, field_sep, scan_fmt, fn)     \
0381 do {                                        \
0382     int i, val_len, pos = 0, fmt_pos = 0;                   \
0383     T expect[8], result[8];                         \
0384                                         \
0385     fill_random_array(expect);                      \
0386                                         \
0387     for (i = 0; i < ARRAY_SIZE(expect); i++) {              \
0388         if (i != 0)                         \
0389             append_delim(test_buffer, &pos, BUF_SIZE,       \
0390                      fmt_buffer, &fmt_pos, BUF_SIZE, field_sep);\
0391                                         \
0392         val_len = append_fmt(test_buffer, &pos, BUF_SIZE, gen_fmt,  \
0393                      expect[i]);                \
0394         append_fmt(fmt_buffer, &fmt_pos, BUF_SIZE,          \
0395                "%%%u%s", val_len, scan_fmt);            \
0396     }                                   \
0397                                         \
0398     test_array_8(fn, expect, test_buffer, fmt_buffer, result);      \
0399 } while (0)
0400 
0401 static void __init numbers_list_ll(const char *delim)
0402 {
0403     numbers_list_8(unsigned long long, "%llu",   delim, "llu", check_ull);
0404     numbers_list_8(long long,      "%lld",   delim, "lld", check_ll);
0405     numbers_list_8(long long,      "%lld",   delim, "lli", check_ll);
0406     numbers_list_8(unsigned long long, "%llx",   delim, "llx", check_ull);
0407     numbers_list_8(unsigned long long, "0x%llx", delim, "llx", check_ull);
0408     numbers_list_8(long long,      "0x%llx", delim, "lli", check_ll);
0409 }
0410 
0411 static void __init numbers_list_l(const char *delim)
0412 {
0413     numbers_list_8(unsigned long,      "%lu",    delim, "lu", check_ulong);
0414     numbers_list_8(long,           "%ld",    delim, "ld", check_long);
0415     numbers_list_8(long,           "%ld",    delim, "li", check_long);
0416     numbers_list_8(unsigned long,      "%lx",    delim, "lx", check_ulong);
0417     numbers_list_8(unsigned long,      "0x%lx",  delim, "lx", check_ulong);
0418     numbers_list_8(long,           "0x%lx",  delim, "li", check_long);
0419 }
0420 
0421 static void __init numbers_list_d(const char *delim)
0422 {
0423     numbers_list_8(unsigned int,       "%u",     delim, "u", check_uint);
0424     numbers_list_8(int,        "%d",     delim, "d", check_int);
0425     numbers_list_8(int,        "%d",     delim, "i", check_int);
0426     numbers_list_8(unsigned int,       "%x",     delim, "x", check_uint);
0427     numbers_list_8(unsigned int,       "0x%x",   delim, "x", check_uint);
0428     numbers_list_8(int,        "0x%x",   delim, "i", check_int);
0429 }
0430 
0431 static void __init numbers_list_h(const char *delim)
0432 {
0433     numbers_list_8(unsigned short,     "%hu",    delim, "hu", check_ushort);
0434     numbers_list_8(short,          "%hd",    delim, "hd", check_short);
0435     numbers_list_8(short,          "%hd",    delim, "hi", check_short);
0436     numbers_list_8(unsigned short,     "%hx",    delim, "hx", check_ushort);
0437     numbers_list_8(unsigned short,     "0x%hx",  delim, "hx", check_ushort);
0438     numbers_list_8(short,          "0x%hx",  delim, "hi", check_short);
0439 }
0440 
0441 static void __init numbers_list_hh(const char *delim)
0442 {
0443     numbers_list_8(unsigned char,      "%hhu",   delim, "hhu", check_uchar);
0444     numbers_list_8(signed char,    "%hhd",   delim, "hhd", check_char);
0445     numbers_list_8(signed char,    "%hhd",   delim, "hhi", check_char);
0446     numbers_list_8(unsigned char,      "%hhx",   delim, "hhx", check_uchar);
0447     numbers_list_8(unsigned char,      "0x%hhx", delim, "hhx", check_uchar);
0448     numbers_list_8(signed char,    "0x%hhx", delim, "hhi", check_char);
0449 }
0450 
0451 static void __init numbers_list(const char *delim)
0452 {
0453     numbers_list_ll(delim);
0454     numbers_list_l(delim);
0455     numbers_list_d(delim);
0456     numbers_list_h(delim);
0457     numbers_list_hh(delim);
0458 }
0459 
0460 static void __init numbers_list_field_width_ll(const char *delim)
0461 {
0462     numbers_list_fix_width(unsigned long long, "%llu",   delim, 20, "llu", check_ull);
0463     numbers_list_fix_width(long long,      "%lld",   delim, 20, "lld", check_ll);
0464     numbers_list_fix_width(long long,      "%lld",   delim, 20, "lli", check_ll);
0465     numbers_list_fix_width(unsigned long long, "%llx",   delim, 16, "llx", check_ull);
0466     numbers_list_fix_width(unsigned long long, "0x%llx", delim, 18, "llx", check_ull);
0467     numbers_list_fix_width(long long,      "0x%llx", delim, 18, "lli", check_ll);
0468 }
0469 
0470 static void __init numbers_list_field_width_l(const char *delim)
0471 {
0472 #if BITS_PER_LONG == 64
0473     numbers_list_fix_width(unsigned long,   "%lu",       delim, 20, "lu", check_ulong);
0474     numbers_list_fix_width(long,        "%ld",       delim, 20, "ld", check_long);
0475     numbers_list_fix_width(long,        "%ld",       delim, 20, "li", check_long);
0476     numbers_list_fix_width(unsigned long,   "%lx",       delim, 16, "lx", check_ulong);
0477     numbers_list_fix_width(unsigned long,   "0x%lx",     delim, 18, "lx", check_ulong);
0478     numbers_list_fix_width(long,        "0x%lx",     delim, 18, "li", check_long);
0479 #else
0480     numbers_list_fix_width(unsigned long,   "%lu",       delim, 10, "lu", check_ulong);
0481     numbers_list_fix_width(long,        "%ld",       delim, 11, "ld", check_long);
0482     numbers_list_fix_width(long,        "%ld",       delim, 11, "li", check_long);
0483     numbers_list_fix_width(unsigned long,   "%lx",       delim, 8,  "lx", check_ulong);
0484     numbers_list_fix_width(unsigned long,   "0x%lx",     delim, 10, "lx", check_ulong);
0485     numbers_list_fix_width(long,        "0x%lx",     delim, 10, "li", check_long);
0486 #endif
0487 }
0488 
0489 static void __init numbers_list_field_width_d(const char *delim)
0490 {
0491     numbers_list_fix_width(unsigned int,    "%u",        delim, 10, "u", check_uint);
0492     numbers_list_fix_width(int,     "%d",        delim, 11, "d", check_int);
0493     numbers_list_fix_width(int,     "%d",        delim, 11, "i", check_int);
0494     numbers_list_fix_width(unsigned int,    "%x",        delim, 8,  "x", check_uint);
0495     numbers_list_fix_width(unsigned int,    "0x%x",      delim, 10, "x", check_uint);
0496     numbers_list_fix_width(int,     "0x%x",      delim, 10, "i", check_int);
0497 }
0498 
0499 static void __init numbers_list_field_width_h(const char *delim)
0500 {
0501     numbers_list_fix_width(unsigned short,  "%hu",       delim, 5, "hu", check_ushort);
0502     numbers_list_fix_width(short,       "%hd",       delim, 6, "hd", check_short);
0503     numbers_list_fix_width(short,       "%hd",       delim, 6, "hi", check_short);
0504     numbers_list_fix_width(unsigned short,  "%hx",       delim, 4, "hx", check_ushort);
0505     numbers_list_fix_width(unsigned short,  "0x%hx",     delim, 6, "hx", check_ushort);
0506     numbers_list_fix_width(short,       "0x%hx",     delim, 6, "hi", check_short);
0507 }
0508 
0509 static void __init numbers_list_field_width_hh(const char *delim)
0510 {
0511     numbers_list_fix_width(unsigned char,   "%hhu",      delim, 3, "hhu", check_uchar);
0512     numbers_list_fix_width(signed char, "%hhd",      delim, 4, "hhd", check_char);
0513     numbers_list_fix_width(signed char, "%hhd",      delim, 4, "hhi", check_char);
0514     numbers_list_fix_width(unsigned char,   "%hhx",      delim, 2, "hhx", check_uchar);
0515     numbers_list_fix_width(unsigned char,   "0x%hhx",    delim, 4, "hhx", check_uchar);
0516     numbers_list_fix_width(signed char, "0x%hhx",    delim, 4, "hhi", check_char);
0517 }
0518 
0519 /*
0520  * List of numbers separated by delim. Each field width specifier is the
0521  * maximum possible digits for the given type and base.
0522  */
0523 static void __init numbers_list_field_width_typemax(const char *delim)
0524 {
0525     numbers_list_field_width_ll(delim);
0526     numbers_list_field_width_l(delim);
0527     numbers_list_field_width_d(delim);
0528     numbers_list_field_width_h(delim);
0529     numbers_list_field_width_hh(delim);
0530 }
0531 
0532 static void __init numbers_list_field_width_val_ll(const char *delim)
0533 {
0534     numbers_list_val_width(unsigned long long, "%llu",   delim, "llu", check_ull);
0535     numbers_list_val_width(long long,      "%lld",   delim, "lld", check_ll);
0536     numbers_list_val_width(long long,      "%lld",   delim, "lli", check_ll);
0537     numbers_list_val_width(unsigned long long, "%llx",   delim, "llx", check_ull);
0538     numbers_list_val_width(unsigned long long, "0x%llx", delim, "llx", check_ull);
0539     numbers_list_val_width(long long,      "0x%llx", delim, "lli", check_ll);
0540 }
0541 
0542 static void __init numbers_list_field_width_val_l(const char *delim)
0543 {
0544     numbers_list_val_width(unsigned long,   "%lu",       delim, "lu", check_ulong);
0545     numbers_list_val_width(long,        "%ld",       delim, "ld", check_long);
0546     numbers_list_val_width(long,        "%ld",       delim, "li", check_long);
0547     numbers_list_val_width(unsigned long,   "%lx",       delim, "lx", check_ulong);
0548     numbers_list_val_width(unsigned long,   "0x%lx",     delim, "lx", check_ulong);
0549     numbers_list_val_width(long,        "0x%lx",     delim, "li", check_long);
0550 }
0551 
0552 static void __init numbers_list_field_width_val_d(const char *delim)
0553 {
0554     numbers_list_val_width(unsigned int,    "%u",        delim, "u", check_uint);
0555     numbers_list_val_width(int,     "%d",        delim, "d", check_int);
0556     numbers_list_val_width(int,     "%d",        delim, "i", check_int);
0557     numbers_list_val_width(unsigned int,    "%x",        delim, "x", check_uint);
0558     numbers_list_val_width(unsigned int,    "0x%x",      delim, "x", check_uint);
0559     numbers_list_val_width(int,     "0x%x",      delim, "i", check_int);
0560 }
0561 
0562 static void __init numbers_list_field_width_val_h(const char *delim)
0563 {
0564     numbers_list_val_width(unsigned short,  "%hu",       delim, "hu", check_ushort);
0565     numbers_list_val_width(short,       "%hd",       delim, "hd", check_short);
0566     numbers_list_val_width(short,       "%hd",       delim, "hi", check_short);
0567     numbers_list_val_width(unsigned short,  "%hx",       delim, "hx", check_ushort);
0568     numbers_list_val_width(unsigned short,  "0x%hx",     delim, "hx", check_ushort);
0569     numbers_list_val_width(short,       "0x%hx",     delim, "hi", check_short);
0570 }
0571 
0572 static void __init numbers_list_field_width_val_hh(const char *delim)
0573 {
0574     numbers_list_val_width(unsigned char,   "%hhu",      delim, "hhu", check_uchar);
0575     numbers_list_val_width(signed char, "%hhd",      delim, "hhd", check_char);
0576     numbers_list_val_width(signed char, "%hhd",      delim, "hhi", check_char);
0577     numbers_list_val_width(unsigned char,   "%hhx",      delim, "hhx", check_uchar);
0578     numbers_list_val_width(unsigned char,   "0x%hhx",    delim, "hhx", check_uchar);
0579     numbers_list_val_width(signed char, "0x%hhx",    delim, "hhi", check_char);
0580 }
0581 
0582 /*
0583  * List of numbers separated by delim. Each field width specifier is the
0584  * exact length of the corresponding value digits in the string being scanned.
0585  */
0586 static void __init numbers_list_field_width_val_width(const char *delim)
0587 {
0588     numbers_list_field_width_val_ll(delim);
0589     numbers_list_field_width_val_l(delim);
0590     numbers_list_field_width_val_d(delim);
0591     numbers_list_field_width_val_h(delim);
0592     numbers_list_field_width_val_hh(delim);
0593 }
0594 
0595 /*
0596  * Slice a continuous string of digits without field delimiters, containing
0597  * numbers of varying length, using the field width to extract each group
0598  * of digits. For example the hex values c0,3,bf01,303 would have a
0599  * string representation of "c03bf01303" and extracted with "%2x%1x%4x%3x".
0600  */
0601 static void __init numbers_slice(void)
0602 {
0603     numbers_list_field_width_val_width("");
0604 }
0605 
0606 #define test_number_prefix(T, str, scan_fmt, expect0, expect1, n_args, fn)  \
0607 do {                                        \
0608     const T expect[2] = { expect0, expect1 };               \
0609     T result[2] = {~expect[0], ~expect[1]};                 \
0610                                         \
0611     _test(fn, &expect, str, scan_fmt, n_args, &result[0], &result[1]);  \
0612 } while (0)
0613 
0614 /*
0615  * Number prefix is >= field width.
0616  * Expected behaviour is derived from testing userland sscanf.
0617  */
0618 static void __init numbers_prefix_overflow(void)
0619 {
0620     /*
0621      * Negative decimal with a field of width 1, should quit scanning
0622      * and return 0.
0623      */
0624     test_number_prefix(long long,   "-1 1", "%1lld %lld",   0, 0, 0, check_ll);
0625     test_number_prefix(long,    "-1 1", "%1ld %ld", 0, 0, 0, check_long);
0626     test_number_prefix(int,     "-1 1", "%1d %d",   0, 0, 0, check_int);
0627     test_number_prefix(short,   "-1 1", "%1hd %hd", 0, 0, 0, check_short);
0628     test_number_prefix(signed char, "-1 1", "%1hhd %hhd",   0, 0, 0, check_char);
0629 
0630     test_number_prefix(long long,   "-1 1", "%1lli %lli",   0, 0, 0, check_ll);
0631     test_number_prefix(long,    "-1 1", "%1li %li", 0, 0, 0, check_long);
0632     test_number_prefix(int,     "-1 1", "%1i %i",   0, 0, 0, check_int);
0633     test_number_prefix(short,   "-1 1", "%1hi %hi", 0, 0, 0, check_short);
0634     test_number_prefix(signed char, "-1 1", "%1hhi %hhi",   0, 0, 0, check_char);
0635 
0636     /*
0637      * 0x prefix in a field of width 1: 0 is a valid digit so should
0638      * convert. Next field scan starts at the 'x' which isn't a digit so
0639      * scan quits with one field converted.
0640      */
0641     test_number_prefix(unsigned long long,  "0xA7", "%1llx%llx", 0, 0, 1, check_ull);
0642     test_number_prefix(unsigned long,   "0xA7", "%1lx%lx",   0, 0, 1, check_ulong);
0643     test_number_prefix(unsigned int,    "0xA7", "%1x%x",     0, 0, 1, check_uint);
0644     test_number_prefix(unsigned short,  "0xA7", "%1hx%hx",   0, 0, 1, check_ushort);
0645     test_number_prefix(unsigned char,   "0xA7", "%1hhx%hhx", 0, 0, 1, check_uchar);
0646     test_number_prefix(long long,       "0xA7", "%1lli%llx", 0, 0, 1, check_ll);
0647     test_number_prefix(long,        "0xA7", "%1li%lx",   0, 0, 1, check_long);
0648     test_number_prefix(int,         "0xA7", "%1i%x",     0, 0, 1, check_int);
0649     test_number_prefix(short,       "0xA7", "%1hi%hx",   0, 0, 1, check_short);
0650     test_number_prefix(char,        "0xA7", "%1hhi%hhx", 0, 0, 1, check_char);
0651 
0652     /*
0653      * 0x prefix in a field of width 2 using %x conversion: first field
0654      * converts to 0. Next field scan starts at the character after "0x".
0655      * Both fields will convert.
0656      */
0657     test_number_prefix(unsigned long long,  "0xA7", "%2llx%llx", 0, 0xa7, 2, check_ull);
0658     test_number_prefix(unsigned long,   "0xA7", "%2lx%lx",   0, 0xa7, 2, check_ulong);
0659     test_number_prefix(unsigned int,    "0xA7", "%2x%x",     0, 0xa7, 2, check_uint);
0660     test_number_prefix(unsigned short,  "0xA7", "%2hx%hx",   0, 0xa7, 2, check_ushort);
0661     test_number_prefix(unsigned char,   "0xA7", "%2hhx%hhx", 0, 0xa7, 2, check_uchar);
0662 
0663     /*
0664      * 0x prefix in a field of width 2 using %i conversion: first field
0665      * converts to 0. Next field scan starts at the character after "0x",
0666      * which will convert if can be interpreted as decimal but will fail
0667      * if it contains any hex digits (since no 0x prefix).
0668      */
0669     test_number_prefix(long long,   "0x67", "%2lli%lli", 0, 67, 2, check_ll);
0670     test_number_prefix(long,    "0x67", "%2li%li",   0, 67, 2, check_long);
0671     test_number_prefix(int,     "0x67", "%2i%i",     0, 67, 2, check_int);
0672     test_number_prefix(short,   "0x67", "%2hi%hi",   0, 67, 2, check_short);
0673     test_number_prefix(char,    "0x67", "%2hhi%hhi", 0, 67, 2, check_char);
0674 
0675     test_number_prefix(long long,   "0xA7", "%2lli%lli", 0, 0,  1, check_ll);
0676     test_number_prefix(long,    "0xA7", "%2li%li",   0, 0,  1, check_long);
0677     test_number_prefix(int,     "0xA7", "%2i%i",     0, 0,  1, check_int);
0678     test_number_prefix(short,   "0xA7", "%2hi%hi",   0, 0,  1, check_short);
0679     test_number_prefix(char,    "0xA7", "%2hhi%hhi", 0, 0,  1, check_char);
0680 }
0681 
0682 #define _test_simple_strtoxx(T, fn, gen_fmt, expect, base)          \
0683 do {                                        \
0684     T got;                                  \
0685     char *endp;                             \
0686     int len;                                \
0687     bool fail = false;                          \
0688                                         \
0689     total_tests++;                              \
0690     len = snprintf(test_buffer, BUF_SIZE, gen_fmt, expect);         \
0691     got = (fn)(test_buffer, &endp, base);                   \
0692     pr_debug(#fn "(\"%s\", %d) -> " gen_fmt "\n", test_buffer, base, got);  \
0693     if (got != (expect)) {                          \
0694         fail = true;                            \
0695         pr_warn(#fn "(\"%s\", %d): got " gen_fmt " expected " gen_fmt "\n", \
0696             test_buffer, base, got, expect);            \
0697     } else if (endp != test_buffer + len) {                 \
0698         fail = true;                            \
0699         pr_warn(#fn "(\"%s\", %d) startp=0x%px got endp=0x%px expected 0x%px\n", \
0700             test_buffer, base, test_buffer,             \
0701             test_buffer + len, endp);               \
0702     }                                   \
0703                                         \
0704     if (fail)                               \
0705         failed_tests++;                         \
0706 } while (0)
0707 
0708 #define test_simple_strtoxx(T, fn, gen_fmt, base)               \
0709 do {                                        \
0710     int i;                                  \
0711                                         \
0712     for (i = 0; i < ARRAY_SIZE(numbers); i++) {             \
0713         _test_simple_strtoxx(T, fn, gen_fmt, (T)numbers[i], base);  \
0714                                         \
0715         if (is_signed_type(T))                      \
0716             _test_simple_strtoxx(T, fn, gen_fmt,            \
0717                           -(T)numbers[i], base);        \
0718     }                                   \
0719 } while (0)
0720 
0721 static void __init test_simple_strtoull(void)
0722 {
0723     test_simple_strtoxx(unsigned long long, simple_strtoull, "%llu",   10);
0724     test_simple_strtoxx(unsigned long long, simple_strtoull, "%llu",   0);
0725     test_simple_strtoxx(unsigned long long, simple_strtoull, "%llx",   16);
0726     test_simple_strtoxx(unsigned long long, simple_strtoull, "0x%llx", 16);
0727     test_simple_strtoxx(unsigned long long, simple_strtoull, "0x%llx", 0);
0728 }
0729 
0730 static void __init test_simple_strtoll(void)
0731 {
0732     test_simple_strtoxx(long long, simple_strtoll, "%lld",   10);
0733     test_simple_strtoxx(long long, simple_strtoll, "%lld",   0);
0734     test_simple_strtoxx(long long, simple_strtoll, "%llx",   16);
0735     test_simple_strtoxx(long long, simple_strtoll, "0x%llx", 16);
0736     test_simple_strtoxx(long long, simple_strtoll, "0x%llx", 0);
0737 }
0738 
0739 static void __init test_simple_strtoul(void)
0740 {
0741     test_simple_strtoxx(unsigned long, simple_strtoul, "%lu",   10);
0742     test_simple_strtoxx(unsigned long, simple_strtoul, "%lu",   0);
0743     test_simple_strtoxx(unsigned long, simple_strtoul, "%lx",   16);
0744     test_simple_strtoxx(unsigned long, simple_strtoul, "0x%lx", 16);
0745     test_simple_strtoxx(unsigned long, simple_strtoul, "0x%lx", 0);
0746 }
0747 
0748 static void __init test_simple_strtol(void)
0749 {
0750     test_simple_strtoxx(long, simple_strtol, "%ld",   10);
0751     test_simple_strtoxx(long, simple_strtol, "%ld",   0);
0752     test_simple_strtoxx(long, simple_strtol, "%lx",   16);
0753     test_simple_strtoxx(long, simple_strtol, "0x%lx", 16);
0754     test_simple_strtoxx(long, simple_strtol, "0x%lx", 0);
0755 }
0756 
0757 /* Selection of common delimiters/separators between numbers in a string. */
0758 static const char * const number_delimiters[] __initconst = {
0759     " ", ":", ",", "-", "/",
0760 };
0761 
0762 static void __init test_numbers(void)
0763 {
0764     int i;
0765 
0766     /* String containing only one number. */
0767     numbers_simple();
0768 
0769     /* String with multiple numbers separated by delimiter. */
0770     for (i = 0; i < ARRAY_SIZE(number_delimiters); i++) {
0771         numbers_list(number_delimiters[i]);
0772 
0773         /* Field width may be longer than actual field digits. */
0774         numbers_list_field_width_typemax(number_delimiters[i]);
0775 
0776         /* Each field width exactly length of actual field digits. */
0777         numbers_list_field_width_val_width(number_delimiters[i]);
0778     }
0779 
0780     /* Slice continuous sequence of digits using field widths. */
0781     numbers_slice();
0782 
0783     numbers_prefix_overflow();
0784 }
0785 
0786 static void __init selftest(void)
0787 {
0788     test_buffer = kmalloc(BUF_SIZE, GFP_KERNEL);
0789     if (!test_buffer)
0790         return;
0791 
0792     fmt_buffer = kmalloc(BUF_SIZE, GFP_KERNEL);
0793     if (!fmt_buffer) {
0794         kfree(test_buffer);
0795         return;
0796     }
0797 
0798     prandom_seed_state(&rnd_state, 3141592653589793238ULL);
0799 
0800     test_numbers();
0801 
0802     test_simple_strtoull();
0803     test_simple_strtoll();
0804     test_simple_strtoul();
0805     test_simple_strtol();
0806 
0807     kfree(fmt_buffer);
0808     kfree(test_buffer);
0809 }
0810 
0811 KSTM_MODULE_LOADERS(test_scanf);
0812 MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
0813 MODULE_LICENSE("GPL v2");