summaryrefslogtreecommitdiff
path: root/tests/oss-fuzz
diff options
context:
space:
mode:
authorBhargava Shastry <bshastry@sect.tu-berlin.de>2018-10-03 01:15:58 +0200
committerBen Pfaff <blp@ovn.org>2018-10-03 14:48:14 -0700
commitea43b024a8a03f6648d0e06589137a4fbfea9f5a (patch)
tree6ca874852de847bcfce707a21f082623bc709cb2 /tests/oss-fuzz
parent7837818b27c5d55dd1ef4309e3ca83089980459a (diff)
downloadopenvswitch-ea43b024a8a03f6648d0e06589137a4fbfea9f5a.tar.gz
ossfuzz: Additions for new ODP parser target
This patch adds a new oss-fuzz target for the ODP parser. The target harness has been adapted from test-odp.c. Prominently, it leaves out "parse_filter" due to an unresolvable bug in that code at the time of writing. It also includes the following: - a fuzzing dictionary - fuzzing config - some automake additions for the new target Signed-off-by: Bhargava Shastry <bshastry@sect.tu-berlin.de> Signed-off-by: Ben Pfaff <blp@ovn.org>
Diffstat (limited to 'tests/oss-fuzz')
-rw-r--r--tests/oss-fuzz/automake.mk13
-rw-r--r--tests/oss-fuzz/config/odp.dict170
-rw-r--r--tests/oss-fuzz/config/odp_target.options3
-rw-r--r--tests/oss-fuzz/odp_target.c147
4 files changed, 331 insertions, 2 deletions
diff --git a/tests/oss-fuzz/automake.mk b/tests/oss-fuzz/automake.mk
index 3e3ac2f9c..4fbdb4c2b 100644
--- a/tests/oss-fuzz/automake.mk
+++ b/tests/oss-fuzz/automake.mk
@@ -2,7 +2,8 @@ OSS_FUZZ_TARGETS = \
tests/oss-fuzz/flow_extract_target \
tests/oss-fuzz/json_parser_target \
tests/oss-fuzz/ofp_print_target \
- tests/oss-fuzz/expr_parse_target
+ tests/oss-fuzz/expr_parse_target \
+ tests/oss-fuzz/odp_target
EXTRA_PROGRAMS += $(OSS_FUZZ_TARGETS)
oss-fuzz-targets: $(OSS_FUZZ_TARGETS)
@@ -31,10 +32,18 @@ tests_oss_fuzz_expr_parse_target_LDADD = lib/libopenvswitch.la \
ovn/lib/libovn.la
tests_oss_fuzz_expr_parse_target_LDFLAGS = $(LIB_FUZZING_ENGINE) -lc++
+tests_oss_fuzz_odp_target_SOURCES = \
+ tests/oss-fuzz/odp_target.c \
+ tests/oss-fuzz/fuzzer.h
+tests_oss_fuzz_odp_target_LDADD = lib/libopenvswitch.la
+tests_oss_fuzz_odp_target_LDFLAGS = $(LIB_FUZZING_ENGINE) -lc++
+
EXTRA_DIST += \
tests/oss-fuzz/config/flow_extract_target.options \
tests/oss-fuzz/config/json_parser_target.options \
tests/oss-fuzz/config/ofp_print_target.options \
tests/oss-fuzz/config/expr_parse_target.options \
+ tests/oss-fuzz/config/odp_target.options \
tests/oss-fuzz/config/ovs.dict \
- tests/oss-fuzz/config/expr.dict
+ tests/oss-fuzz/config/expr.dict \
+ tests/oss-fuzz/config/odp.dict
diff --git a/tests/oss-fuzz/config/odp.dict b/tests/oss-fuzz/config/odp.dict
new file mode 100644
index 000000000..a9bdd3e99
--- /dev/null
+++ b/tests/oss-fuzz/config/odp.dict
@@ -0,0 +1,170 @@
+"("
+")"
+","
+"/0x"
+"0x"
+": "
+"="
+"=r"
+"action"
+"arp"
+"bfd"
+"bos"
+"c1"
+"c2"
+"c3"
+"c4"
+"cc"
+"cfi"
+"cfm"
+"class"
+"clone"
+"code"
+"commit,"
+"crit,"
+"csum"
+"ct"
+"ct(error)"
+"ct_clear"
+"ct_label"
+"ct_mark"
+"ct_state"
+"ct_tuple4"
+"ct_tuple6"
+"ct_zone"
+"dir"
+"dl_type"
+"dnat"
+"dp_hash"
+"drop"
+"dst"
+"dst_port"
+"egress"
+"encap"
+"error"
+"erspan"
+"erspan(ver=1,sid=0x,dir=,idx=0x)"
+"est"
+"eth"
+"eth_type"
+"eth_type(0/)"
+"first"
+"flags"
+"force_commit,"
+"frag"
+"gbp("
+"geneve"
+"gre((flags=0x,proto=0x)"
+"hash,"
+"helper"
+"hlimit"
+"hwid"
+"icmp"
+"icmpv6"
+"id"
+"idx="
+"in_port"
+"ingress"
+"inv"
+"ip6erspan"
+"ipfix(output_port="
+"ipv4"
+"ipv6"
+"ipv6_dst"
+"ipv6_src"
+"l4()"
+"label"
+"lacp"
+"later"
+"len"
+"lldp"
+"mark=/,"
+"match"
+"md2"
+"mdtype"
+"meter()"
+"mpls"
+"nat"
+"nd"
+"new"
+"no"
+"np"
+"ns"
+"nsh"
+"oam,"
+"op"
+"options("
+"out_port("
+"packet_type"
+"pcp="
+"persistent,"
+"pop_eth"
+"pop_mpls(eth_type=0x)"
+"pop_nsh()"
+"pop_vlan"
+"proto"
+"push_eth(src=:::::,dst=:::::,type=)"
+"push_mpls("
+"push_nsh("
+"push_vlan("
+"push_vlan(tpid=,vid=,pcp=,cfi=)"
+"random,"
+"recirc()"
+"recirc_id"
+"rel"
+"rpl"
+"sFlow(vid=,pcp=,output=)"
+"sample"
+"sctp"
+"seq=0x"
+"set("
+"set(nsh("
+"sha"
+"si"
+"sip"
+"skb_mark"
+"skb_priority"
+"sll"
+"slow_path"
+"snat"
+"spi"
+"src"
+"src_port"
+"stp"
+"sym_l4()"
+"target"
+"tc="
+"tclass"
+"tcp"
+"tcp_flags"
+"tha"
+"tip"
+"tll"
+"tnl_pop("
+"tnl_push(tnl_port("
+"too_little"
+"too_much"
+"tos"
+"tp_dst"
+"tp_src"
+"tpid=0x"
+"trk"
+"trunc()"
+"ttl"
+"tun_id"
+"tunnel"
+"tunnel_out_port"
+"type"
+"udp"
+"unspec"
+"userdata"
+"userspace("
+"userspace(error)"
+"userspace(pid"
+"ver"
+"vid"
+"vlan"
+"vxlan"
+"vxlan(flags=0x,vni=0x)"
+"vxlan(gbp("
+"zone"
diff --git a/tests/oss-fuzz/config/odp_target.options b/tests/oss-fuzz/config/odp_target.options
new file mode 100644
index 000000000..41821b8c1
--- /dev/null
+++ b/tests/oss-fuzz/config/odp_target.options
@@ -0,0 +1,3 @@
+[libfuzzer]
+close_fd_mask = 3
+dict = odp.dict
diff --git a/tests/oss-fuzz/odp_target.c b/tests/oss-fuzz/odp_target.c
new file mode 100644
index 000000000..93231bde3
--- /dev/null
+++ b/tests/oss-fuzz/odp_target.c
@@ -0,0 +1,147 @@
+#include <config.h>
+#include "fuzzer.h"
+#undef NDEBUG
+#include "odp-util.h"
+#include <stdio.h>
+#include "openvswitch/dynamic-string.h"
+#include "flow.h"
+#include "openvswitch/match.h"
+#include "openvswitch/ofpbuf.h"
+#include "util.h"
+#include "openvswitch/ofp-flow.h"
+#include "openvswitch/vlog.h"
+
+static int
+parse_keys(bool wc_keys, const char *in)
+{
+ int exit_code = 0;
+
+ enum odp_key_fitness fitness;
+ struct ofpbuf odp_key;
+ struct ofpbuf odp_mask;
+ struct flow flow;
+ struct ds out;
+ int error;
+
+ /* Convert string to OVS DP key. */
+ ofpbuf_init(&odp_key, 0);
+ ofpbuf_init(&odp_mask, 0);
+ error = odp_flow_from_string(in, NULL,
+ &odp_key, &odp_mask);
+ if (error) {
+ printf("odp_flow_from_string: error\n");
+ goto next;
+ }
+
+ if (!wc_keys) {
+ struct odp_flow_key_parms odp_parms = {
+ .flow = &flow,
+ .support = {
+ .recirc = true,
+ .ct_state = true,
+ .ct_zone = true,
+ .ct_mark = true,
+ .ct_label = true,
+ .max_vlan_headers = SIZE_MAX,
+ },
+ };
+
+ /* Convert odp_key to flow. */
+ fitness = odp_flow_key_to_flow(odp_key.data, odp_key.size, &flow);
+ switch (fitness) {
+ case ODP_FIT_PERFECT:
+ break;
+
+ case ODP_FIT_TOO_LITTLE:
+ printf("ODP_FIT_TOO_LITTLE: ");
+ break;
+
+ case ODP_FIT_TOO_MUCH:
+ printf("ODP_FIT_TOO_MUCH: ");
+ break;
+
+ case ODP_FIT_ERROR:
+ printf("odp_flow_key_to_flow: error\n");
+ goto next;
+ }
+ /* Convert cls_rule back to odp_key. */
+ ofpbuf_uninit(&odp_key);
+ ofpbuf_init(&odp_key, 0);
+ odp_flow_key_from_flow(&odp_parms, &odp_key);
+
+ if (odp_key.size > ODPUTIL_FLOW_KEY_BYTES) {
+ printf ("too long: %"PRIu32" > %d\n",
+ odp_key.size, ODPUTIL_FLOW_KEY_BYTES);
+ exit_code = 1;
+ }
+ }
+
+ /* Convert odp_key to string. */
+ ds_init(&out);
+ if (wc_keys) {
+ odp_flow_format(odp_key.data, odp_key.size,
+ odp_mask.data, odp_mask.size, NULL, &out, false);
+ } else {
+ odp_flow_key_format(odp_key.data, odp_key.size, &out);
+ }
+ puts(ds_cstr(&out));
+ ds_destroy(&out);
+
+next:
+ ofpbuf_uninit(&odp_key);
+ ofpbuf_uninit(&odp_mask);
+
+ return exit_code;
+}
+
+static int
+parse_actions(const char *in)
+{
+ struct ofpbuf odp_actions;
+ struct ds out;
+ int error;
+
+ /* Convert string to OVS DP actions. */
+ ofpbuf_init(&odp_actions, 0);
+ error = odp_actions_from_string(in, NULL, &odp_actions);
+ if (error) {
+ printf("odp_actions_from_string: error\n");
+ goto next;
+ }
+
+ /* Convert odp_actions back to string. */
+ ds_init(&out);
+ format_odp_actions(&out, odp_actions.data, odp_actions.size, NULL);
+ puts(ds_cstr(&out));
+ ds_destroy(&out);
+
+next:
+ ofpbuf_uninit(&odp_actions);
+ return 0;
+}
+
+int
+LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ /* Bail out if we cannot construct at least a 1 char string. */
+ const char *input = (const char *) data;
+ if (size < 2 || input[size - 1] != '\0' || strchr(input, '\n')) {
+ return 0;
+ }
+
+ /* Disable logging to avoid write to disk. */
+ static bool isInit = false;
+ if (!isInit) {
+ vlog_set_verbosity("off");
+ isInit = true;
+ }
+
+ /* Parse keys and wc keys. */
+ parse_keys(false, input);
+ parse_keys(true, input);
+
+ /* Parse actions. */
+ parse_actions(input);
+
+ return 0;
+}