~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/lib/test_scanf.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php