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