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