/src/barebox/commands/fuzz.c
Line | Count | Source |
1 | | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | | |
3 | | #define pr_fmt(fmt) "fuzz: " fmt |
4 | | |
5 | | #include <common.h> |
6 | | #include <command.h> |
7 | | #include <getopt.h> |
8 | | #include <fuzz.h> |
9 | | #include <libfile.h> |
10 | | #include <fs.h> |
11 | | |
12 | | struct fuzz_process { |
13 | | bool print; |
14 | | const char *match; |
15 | | unsigned nmatches; |
16 | | const struct fuzz_test *test; |
17 | | }; |
18 | | |
19 | | static int process_fuzz_test(const struct fuzz_test *test, |
20 | | void *_ctx) |
21 | 0 | { |
22 | 0 | struct fuzz_process *ctx = _ctx; |
23 | |
|
24 | 0 | if (ctx->print) { |
25 | 0 | printf("%s\n", test->name); |
26 | 0 | ctx->nmatches++; |
27 | 0 | } |
28 | |
|
29 | 0 | if (ctx->match && !strcmp(test->name, ctx->match)) { |
30 | 0 | ctx->test = test; |
31 | 0 | return true; |
32 | 0 | } |
33 | | |
34 | 0 | return false; |
35 | 0 | } |
36 | | |
37 | | static const struct fuzz_test *get_fuzz_test(const char *match, bool print) |
38 | 0 | { |
39 | 0 | struct fuzz_process ctx = { |
40 | 0 | .match = match, .print = print |
41 | 0 | }; |
42 | |
|
43 | 0 | if (call_for_each_fuzz_test(process_fuzz_test, &ctx)) |
44 | 0 | return ctx.test; |
45 | | |
46 | 0 | if (!ctx.nmatches) { |
47 | 0 | if (match) |
48 | 0 | printf("No fuzz tests matching '%s' found.\n", match); |
49 | 0 | else |
50 | 0 | printf("No fuzz tests registered.\n"); |
51 | 0 | } |
52 | |
|
53 | 0 | return NULL; |
54 | 0 | } |
55 | | |
56 | | static int run_fuzz_test(const char *match, bool list, const u8 *buf, size_t len) |
57 | 0 | { |
58 | 0 | const struct fuzz_test *test; |
59 | |
|
60 | 0 | test = get_fuzz_test(match, list); |
61 | 0 | if (list) |
62 | 0 | return 0; |
63 | 0 | else if (!test) |
64 | 0 | return COMMAND_ERROR; |
65 | | |
66 | 0 | fuzz_test_setup(test); |
67 | |
|
68 | 0 | return fuzz_test_once(test, buf, len); |
69 | 0 | } |
70 | | |
71 | | static int do_fuzz(int argc, char *argv[]) |
72 | 0 | { |
73 | 0 | const char *file = NULL; |
74 | 0 | u64 max_size = FILESIZE_MAX; |
75 | 0 | size_t size = 0; |
76 | 0 | const u8 *buf = NULL; |
77 | 0 | void *contents = NULL; |
78 | 0 | bool list = false; |
79 | 0 | int err = 0, opt; |
80 | |
|
81 | 0 | while((opt = getopt(argc, argv, "ls:f:")) > 0) { |
82 | 0 | switch(opt) { |
83 | 0 | case 'l': |
84 | 0 | list = true; |
85 | 0 | break; |
86 | 0 | case 's': |
87 | 0 | err = kstrtou64(optarg, 0, &max_size); |
88 | 0 | if (err || max_size > SIZE_MAX) { |
89 | 0 | printf("invalid max size\n"); |
90 | 0 | return COMMAND_ERROR; |
91 | 0 | } |
92 | 0 | break; |
93 | 0 | case 'f': |
94 | 0 | file = optarg; |
95 | 0 | break; |
96 | 0 | default: |
97 | 0 | return COMMAND_ERROR_USAGE; |
98 | 0 | } |
99 | 0 | } |
100 | | |
101 | 0 | argv += optind; |
102 | 0 | argc -= optind; |
103 | |
|
104 | 0 | if ((list && argc) || (!list && argc != 1) || (!file && !list)) |
105 | 0 | return COMMAND_ERROR_USAGE; |
106 | | |
107 | 0 | if (file) { |
108 | 0 | err = read_file_2(file, &size, &contents, max_size); |
109 | 0 | if (err && err != -EFBIG) { |
110 | 0 | printf("error reading file: %m\n"); |
111 | 0 | return COMMAND_ERROR; |
112 | 0 | } |
113 | | |
114 | 0 | buf = contents; |
115 | 0 | } |
116 | | |
117 | 0 | err = run_fuzz_test(argv[0], list, buf, size); |
118 | |
|
119 | 0 | free(contents); |
120 | 0 | return err; |
121 | 0 | } |
122 | | |
123 | | BAREBOX_CMD_HELP_START(fuzz) |
124 | | BAREBOX_CMD_HELP_TEXT("Run barebox fuzz test on fixed input") |
125 | | BAREBOX_CMD_HELP_TEXT("") |
126 | | BAREBOX_CMD_HELP_TEXT("Options:") |
127 | | BAREBOX_CMD_HELP_OPT ("-l", "list registered fuzz tests") |
128 | | BAREBOX_CMD_HELP_OPT ("-f FILE", "use FILE as fuzz input") |
129 | | BAREBOX_CMD_HELP_OPT ("-s SIZE", "read only SIZE bytes from file") |
130 | | BAREBOX_CMD_HELP_END |
131 | | |
132 | | BAREBOX_CMD_START(fuzz) |
133 | | .cmd = do_fuzz, |
134 | | BAREBOX_CMD_DESC("Run fuzz test") |
135 | | BAREBOX_CMD_OPTS("[-ls] -f FILE [test]") |
136 | | BAREBOX_CMD_GROUP(CMD_GRP_MISC) |
137 | | BAREBOX_CMD_HELP(cmd_fuzz_help) |
138 | | BAREBOX_CMD_END |