Coverage Report

Created: 2026-09-01 06:24

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openvswitch/tests/oss-fuzz/odp_target.c
Line
Count
Source
1
#include <config.h>
2
#include "fuzzer.h"
3
#undef NDEBUG
4
#include "odp-util.h"
5
#include <stdio.h>
6
#include "openvswitch/dynamic-string.h"
7
#include "flow.h"
8
#include "openvswitch/match.h"
9
#include "openvswitch/ofpbuf.h"
10
#include "util.h"
11
#include "openvswitch/ofp-flow.h"
12
#include "openvswitch/vlog.h"
13
14
static int
15
parse_keys(bool wc_keys, const char *in)
16
35.0k
{
17
35.0k
    int exit_code = 0;
18
19
35.0k
    enum odp_key_fitness fitness;
20
35.0k
    struct ofpbuf odp_key;
21
35.0k
    struct ofpbuf odp_mask;
22
35.0k
    struct flow flow;
23
35.0k
    struct ds out;
24
35.0k
    int error;
25
26
    /* Convert string to OVS DP key. */
27
35.0k
    ofpbuf_init(&odp_key, 0);
28
35.0k
    ofpbuf_init(&odp_mask, 0);
29
35.0k
    error = odp_flow_from_string(in, NULL,
30
35.0k
                                 &odp_key, &odp_mask, NULL);
31
35.0k
    if (error) {
32
24.9k
        printf("odp_flow_from_string: error\n");
33
24.9k
        goto next;
34
24.9k
    }
35
36
10.1k
    if (!wc_keys) {
37
5.08k
        struct odp_flow_key_parms odp_parms = {
38
5.08k
            .flow = &flow,
39
5.08k
            .support = {
40
5.08k
                .recirc = true,
41
5.08k
                .ct_state = true,
42
5.08k
                .ct_zone = true,
43
5.08k
                .ct_mark = true,
44
5.08k
                .ct_label = true,
45
5.08k
                .max_vlan_headers = SIZE_MAX,
46
5.08k
            },
47
5.08k
        };
48
49
        /* Convert odp_key to flow. */
50
5.08k
        fitness = odp_flow_key_to_flow(odp_key.data, odp_key.size,
51
5.08k
                                       &flow, NULL);
52
5.08k
        switch (fitness) {
53
2.30k
            case ODP_FIT_PERFECT:
54
2.30k
                break;
55
56
92
            case ODP_FIT_TOO_LITTLE:
57
92
                printf("ODP_FIT_TOO_LITTLE: ");
58
92
                break;
59
60
390
            case ODP_FIT_TOO_MUCH:
61
390
                printf("ODP_FIT_TOO_MUCH: ");
62
390
                break;
63
64
2.30k
            case ODP_FIT_ERROR:
65
2.30k
                printf("odp_flow_key_to_flow: error\n");
66
2.30k
                goto next;
67
5.08k
        }
68
        /* Convert cls_rule back to odp_key. */
69
2.78k
        ofpbuf_uninit(&odp_key);
70
2.78k
        ofpbuf_init(&odp_key, 0);
71
2.78k
        odp_flow_key_from_flow(&odp_parms, &odp_key);
72
73
2.78k
        if (odp_key.size > ODPUTIL_FLOW_KEY_BYTES) {
74
0
            printf ("too long: %"PRIu32" > %d\n",
75
0
                    odp_key.size, ODPUTIL_FLOW_KEY_BYTES);
76
0
            exit_code = 1;
77
0
        }
78
2.78k
    }
79
80
    /* Convert odp_key to string. */
81
7.87k
    ds_init(&out);
82
7.87k
    if (wc_keys) {
83
5.08k
        odp_flow_format(odp_key.data, odp_key.size,
84
5.08k
                        odp_mask.data, odp_mask.size, NULL, &out, false,
85
5.08k
                        false);
86
5.08k
    } else {
87
2.78k
        odp_flow_key_format(odp_key.data, odp_key.size, &out);
88
2.78k
    }
89
7.87k
    puts(ds_cstr(&out));
90
7.87k
    ds_destroy(&out);
91
92
35.0k
next:
93
35.0k
    ofpbuf_uninit(&odp_key);
94
35.0k
    ofpbuf_uninit(&odp_mask);
95
96
35.0k
    return exit_code;
97
7.87k
}
98
99
static int
100
parse_actions(const char *in)
101
17.5k
{
102
17.5k
    struct ofpbuf odp_actions;
103
17.5k
    struct ds out;
104
17.5k
    int error;
105
106
    /* Convert string to OVS DP actions. */
107
17.5k
    ofpbuf_init(&odp_actions, 0);
108
17.5k
    error = odp_actions_from_string(in, NULL, &odp_actions);
109
17.5k
    if (error) {
110
14.3k
        printf("odp_actions_from_string: error\n");
111
14.3k
        goto next;
112
14.3k
    }
113
114
    /* Convert odp_actions back to string. */
115
3.15k
    ds_init(&out);
116
3.15k
    format_odp_actions(&out, odp_actions.data, odp_actions.size, NULL);
117
3.15k
    puts(ds_cstr(&out));
118
3.15k
    ds_destroy(&out);
119
120
17.5k
next:
121
17.5k
    ofpbuf_uninit(&odp_actions);
122
17.5k
    return 0;
123
3.15k
}
124
125
int
126
LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
127
42.1k
{
128
    /* Bail out if we cannot construct at least a 1 char string. */
129
42.1k
    const char *input = (const char *) data;
130
42.1k
    if (size < 2 || input[size - 1] != '\0' || strchr(input, '\n') ||
131
42.1k
        strlen(input) != size - 1) {
132
52
        return 0;
133
52
    }
134
135
    /* Disable logging to avoid write to disk. */
136
42.0k
    static bool isInit = false;
137
42.0k
    if (!isInit) {
138
2
        vlog_set_verbosity("off");
139
2
        isInit = true;
140
2
    }
141
142
    /* Parse keys and wc keys. */
143
42.0k
    parse_keys(false, input);
144
42.0k
    parse_keys(true, input);
145
146
    /* Parse actions. */
147
42.0k
    parse_actions(input);
148
149
42.0k
    return 0;
150
42.1k
}