2
0
mirror of https://github.com/openvswitch/ovs synced 2025-08-22 01:51:26 +00:00
ovs/tests/oss-fuzz/odp_target.c
Eelco Chaudron fa731c1129 oss-fuzz: Fix odp_flow_format() API in the fuzz tests.
When the commit below introduced an API change, the oss-fuzz component
was not updated accordingly, leading to failures in the upstream
oss-fuzz tests.

For more information on the failure, see:
  https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=71524

Fixes: 252ee0f18211 ("dpif: Fix flow put debug message match content.")
Acked-by: Ilya Maximets <i.maximets@ovn.org>
Signed-off-by: Eelco Chaudron <echaudro@redhat.com>
2024-09-12 17:29:42 +02:00

151 lines
3.7 KiB
C

#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, NULL);
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, NULL);
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,
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') ||
strlen(input) != size - 1) {
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;
}