scanf_kunit.c 30 KB

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