/src/openvswitch/tests/oss-fuzz/ofctl_parse_target.c
Line | Count | Source |
1 | | #include <config.h> |
2 | | #include "fuzzer.h" |
3 | | #include "openvswitch/ofp-flow.h" |
4 | | #include "ofp-version-opt.h" |
5 | | #include "ofproto/ofproto.h" |
6 | | #include "openflow/openflow.h" |
7 | | #include "openvswitch/ofpbuf.h" |
8 | | #include "openvswitch/vlog.h" |
9 | | #include "util.h" |
10 | | |
11 | | static void |
12 | | ofctl_parse_flows__(struct ofputil_flow_mod *fms, size_t n_fms, |
13 | | enum ofputil_protocol usable_protocols) |
14 | 5.15k | { |
15 | 5.15k | enum ofputil_protocol protocol = 0; |
16 | 5.15k | char *usable_s; |
17 | 5.15k | size_t i; |
18 | | |
19 | 5.15k | usable_s = ofputil_protocols_to_string(usable_protocols); |
20 | 5.15k | printf("usable protocols: %s\n", usable_s); |
21 | 5.15k | free(usable_s); |
22 | | |
23 | 5.15k | if (!(usable_protocols & OFPUTIL_P_ANY)) { |
24 | 66 | printf("no usable protocol\n"); |
25 | 66 | goto free; |
26 | 66 | } |
27 | 11.7k | for (i = 0; i < sizeof(enum ofputil_protocol) * CHAR_BIT; i++) { |
28 | 11.7k | protocol = 1u << i; |
29 | 11.7k | if (protocol & usable_protocols & OFPUTIL_P_ANY) { |
30 | 5.08k | break; |
31 | 5.08k | } |
32 | 11.7k | } |
33 | 5.08k | ovs_assert(is_pow2(protocol)); |
34 | | |
35 | 5.08k | printf("chosen protocol: %s\n", ofputil_protocol_to_string(protocol)); |
36 | | |
37 | 10.1k | for (i = 0; i < n_fms; i++) { |
38 | 5.08k | struct ofputil_flow_mod *fm = &fms[i]; |
39 | 5.08k | struct ofpbuf *msg; |
40 | | |
41 | 5.08k | msg = ofputil_encode_flow_mod(fm, protocol); |
42 | 5.08k | ofpbuf_delete(msg); |
43 | 5.08k | } |
44 | | |
45 | 5.15k | free: |
46 | 10.3k | for (i = 0; i < n_fms; i++) { |
47 | 5.15k | struct ofputil_flow_mod *fm = &fms[i]; |
48 | 5.15k | free(CONST_CAST(struct ofpact *, fm->ofpacts)); |
49 | 5.15k | minimatch_destroy(&fm->match); |
50 | 5.15k | } |
51 | 5.15k | } |
52 | | |
53 | | /* "parse-flow FLOW": parses the argument as a flow (like add-flow) and prints |
54 | | * it back to stdout. */ |
55 | | static void |
56 | | ofctl_parse_flow(const char *input, int command) |
57 | 14.9k | { |
58 | 14.9k | enum ofputil_protocol usable_protocols; |
59 | 14.9k | struct ofputil_flow_mod fm; |
60 | 14.9k | char *error; |
61 | | |
62 | 14.9k | error = parse_ofp_flow_mod_str(&fm, input, NULL, NULL, |
63 | 14.9k | command, &usable_protocols); |
64 | 14.9k | if (error) { |
65 | 9.81k | printf("Error encountered: %s\n", error); |
66 | 9.81k | free(error); |
67 | 9.81k | } else { |
68 | 5.15k | ofctl_parse_flows__(&fm, 1, usable_protocols); |
69 | 5.15k | } |
70 | 14.9k | } |
71 | | |
72 | | int |
73 | | LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) |
74 | 29.6k | { |
75 | | /* Bail out if we cannot construct at least a 1 char string. |
76 | | * Reserve 1 byte to decide flow mod command. |
77 | | * |
78 | | * Here's the structure of data we expect |
79 | | * |--Byte 1--|--Byte 2--|...|--Byte (size-1)--| |
80 | | * |
81 | | * where, |
82 | | * |
83 | | * Byte 1: Used to decide which ofp flow mod command to test |
84 | | * Bytes 2--(size-1): The C string that is actually passed to |
85 | | * ofctl_parse_flow() test API. |
86 | | * |
87 | | * This means that the fuzzed input is actually a C string of |
88 | | * length = (size -2) with the terminal byte being the NUL |
89 | | * character. Moreover, this string is expected to not contain |
90 | | * a new-line character. |
91 | | */ |
92 | 29.6k | const char *stream = (const char *) data; |
93 | 29.6k | if (size < 3 || stream[size - 1] != '\0' || strchr(&stream[1], '\n') || |
94 | 29.6k | strlen(&stream[1]) != size - 2) { |
95 | 44 | return 0; |
96 | 44 | } |
97 | | |
98 | | /* Disable logging to avoid write to disk. */ |
99 | 29.6k | static bool isInit = false; |
100 | 29.6k | if (!isInit) { |
101 | 2 | vlog_set_verbosity("off"); |
102 | 2 | isInit = true; |
103 | 2 | } |
104 | | |
105 | | /* Decide test parameters using first byte of fuzzed input. */ |
106 | 29.6k | int command = (stream[0] % OFPFC_DELETE_STRICT) + 1; |
107 | | |
108 | | /* Fuzz extended match parsing. */ |
109 | 29.6k | const char *input = &stream[1]; |
110 | 29.6k | ofctl_parse_flow(input, command); |
111 | | |
112 | 29.6k | return 0; |
113 | 29.6k | } |