Coverage Report

Created: 2025-08-28 06:46

/src/ndpi/fuzz/fuzz_ds_patricia.cpp
Line
Count
Source
1
#include "ndpi_api.h"
2
#include "fuzz_common_code.h"
3
4
#include <stdint.h>
5
#include <stdio.h>
6
#include <assert.h>
7
#include "fuzzer/FuzzedDataProvider.h"
8
9
43.1k
static void process_ptree_data(ndpi_prefix_t *prefix, void *data) {
10
  /* Nothing to do */
11
43.1k
  assert(prefix && data == NULL);
12
43.1k
}
13
43.1k
static void process3_ptree_data(ndpi_patricia_node_t *node, void *data, void *user_data) {
14
  /* Nothing to do */
15
43.1k
  assert(node && data == NULL && user_data == NULL);
16
43.1k
}
17
18
592
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
19
592
  FuzzedDataProvider fuzzed_data(data, size);
20
592
  u_int16_t i, num_iteration, ip_len;
21
592
  ndpi_patricia_tree_t *p, *p_cloned;
22
592
  u_int16_t maxbits;
23
592
  int is_added = 0;
24
592
  ndpi_prefix_t prefix, prefix_added;
25
592
  u_char *ip;
26
592
  ndpi_patricia_node_t *node;
27
592
  int tree_type; /* 0: ipv4, 1: ipv6, 2: mac */
28
29
  /* Just to have some data */
30
592
  if (fuzzed_data.remaining_bytes() < 1024)
31
18
    return -1;
32
33
  /* To allow memory allocation failures */
34
574
  fuzz_set_alloc_callbacks_and_seed(size);
35
36
574
  tree_type = fuzzed_data.ConsumeIntegralInRange(0, 2);
37
574
  if (tree_type == 0)
38
202
    maxbits = 32;
39
372
  else if (tree_type == 1)
40
191
    maxbits = 128;
41
181
  else
42
181
    maxbits = 48;
43
44
574
  p = ndpi_patricia_new(maxbits);
45
46
574
  ndpi_patricia_get_maxbits(p);
47
574
  ndpi_patricia_process(p, process_ptree_data);
48
574
  ndpi_patricia_walk_tree_inorder(p, process3_ptree_data, NULL);
49
50
  /* "Random" add */
51
574
  num_iteration = fuzzed_data.ConsumeIntegral<u_int8_t>();
52
58.3k
  for (i = 0; i < num_iteration; i++) {
53
57.7k
    if (tree_type == 0) {
54
22.4k
      if(fuzzed_data.remaining_bytes() > 4) {
55
21.3k
        std::vector<u_int8_t>data = fuzzed_data.ConsumeBytes<u_int8_t>(4);
56
21.3k
  ip = data.data();
57
21.3k
        ip_len = fuzzed_data.ConsumeIntegralInRange(0, 33); /* 33 to force error */
58
21.3k
        ndpi_fill_prefix_v4(&prefix, (struct in_addr *)ip, ip_len, 32);
59
21.3k
        node = ndpi_patricia_lookup(p, &prefix);
60
        /* Keep one random node really added */
61
21.3k
  if (node && is_added == 0 && fuzzed_data.ConsumeBool()) {
62
131
          is_added = 1;
63
131
          prefix_added = prefix;
64
    /* Some random operations on this node */
65
131
          ndpi_patricia_get_node_prefix(node);
66
131
          ndpi_patricia_get_node_bits(node);
67
131
          ndpi_patricia_set_node_data(node, NULL);
68
131
          assert(ndpi_patricia_get_node_data(node) == NULL);
69
131
          ndpi_patricia_set_node_u64(node, 0);
70
131
          assert(ndpi_patricia_get_node_u64(node) == 0);
71
131
  }
72
21.3k
      }
73
35.3k
    } else if (tree_type == 1){
74
21.5k
      if(fuzzed_data.remaining_bytes() > 16) {
75
15.4k
        std::vector<u_int8_t>data = fuzzed_data.ConsumeBytes<u_int8_t>(16);
76
15.4k
  ip = data.data();
77
15.4k
        ip_len = fuzzed_data.ConsumeIntegralInRange(0, 129); /* 129 to force error */
78
15.4k
        ndpi_fill_prefix_v6(&prefix, (const struct in6_addr *)ip, ip_len, 128);
79
15.4k
        node = ndpi_patricia_lookup(p, &prefix);
80
        /* Keep one random node really added */
81
15.4k
  if (node && is_added == 0 && fuzzed_data.ConsumeBool()) {
82
138
          is_added = 1;
83
138
          prefix_added = prefix;
84
    /* Some random operations on this node */
85
138
          ndpi_patricia_get_node_prefix(node);
86
138
          ndpi_patricia_get_node_bits(node);
87
138
          ndpi_patricia_set_node_data(node, NULL);
88
138
          assert(ndpi_patricia_get_node_data(node) == NULL);
89
138
          ndpi_patricia_set_node_u64(node, 0);
90
138
          assert(ndpi_patricia_get_node_u64(node) == 0);
91
138
  }
92
15.4k
      }
93
21.5k
    } else {
94
13.7k
      if(fuzzed_data.remaining_bytes() > 6) {
95
12.5k
        std::vector<u_int8_t>data = fuzzed_data.ConsumeBytes<u_int8_t>(6);
96
12.5k
  ip = data.data();
97
12.5k
        ip_len = fuzzed_data.ConsumeIntegralInRange(0, 49); /* 49 to force error */
98
12.5k
        ndpi_fill_prefix_mac(&prefix, ip, ip_len, 48);
99
12.5k
        node = ndpi_patricia_lookup(p, &prefix);
100
        /* Keep one random node really added */
101
12.5k
  if (node && is_added == 0 && fuzzed_data.ConsumeBool()) {
102
93
          is_added = 1;
103
93
          prefix_added = prefix;
104
    /* Some random operations on this node */
105
93
          ndpi_patricia_get_node_prefix(node);
106
93
          ndpi_patricia_get_node_bits(node);
107
93
          ndpi_patricia_set_node_data(node, NULL);
108
93
          assert(ndpi_patricia_get_node_data(node) == NULL);
109
93
          ndpi_patricia_set_node_u64(node, 0);
110
93
          assert(ndpi_patricia_get_node_u64(node) == 0);
111
93
  }
112
12.5k
      }
113
13.7k
    }
114
57.7k
  }
115
116
574
  ndpi_patricia_process(p, process_ptree_data);
117
574
  ndpi_patricia_walk_tree_inorder(p, process3_ptree_data, NULL);
118
119
  /* "Random" exact search. Remove if found */
120
574
  num_iteration = fuzzed_data.ConsumeIntegral<u_int8_t>();
121
44.2k
  for (i = 0; i < num_iteration; i++) {
122
43.6k
    if (tree_type == 0) {
123
13.9k
      if(fuzzed_data.remaining_bytes() > 4) {
124
9.09k
        std::vector<u_int8_t>data = fuzzed_data.ConsumeBytes<u_int8_t>(4);
125
9.09k
  ip = data.data();
126
9.09k
        ip_len = fuzzed_data.ConsumeIntegralInRange(0, 32);
127
9.09k
        ndpi_fill_prefix_v4(&prefix, (struct in_addr *)ip, ip_len, 32);
128
9.09k
        node = ndpi_patricia_search_exact(p, &prefix);
129
9.09k
  if (node)
130
720
          ndpi_patricia_remove(p, node);
131
9.09k
      }
132
29.7k
    } else if (tree_type == 1) {
133
15.7k
      if(fuzzed_data.remaining_bytes() > 16) {
134
8.63k
        std::vector<u_int8_t>data = fuzzed_data.ConsumeBytes<u_int8_t>(16);
135
8.63k
  ip = data.data();
136
8.63k
        ip_len = fuzzed_data.ConsumeIntegralInRange(0, 128);
137
8.63k
        ndpi_fill_prefix_v6(&prefix, (const struct in6_addr *)ip, ip_len, 128);
138
8.63k
        node = ndpi_patricia_search_exact(p, &prefix);
139
8.63k
  if (node)
140
502
          ndpi_patricia_remove(p, node);
141
8.63k
      }
142
15.7k
    } else {
143
13.9k
      if(fuzzed_data.remaining_bytes() > 6) {
144
10.4k
        std::vector<u_int8_t>data = fuzzed_data.ConsumeBytes<u_int8_t>(6);
145
10.4k
  ip = data.data();
146
10.4k
        ip_len = fuzzed_data.ConsumeIntegralInRange(0, 48);
147
10.4k
        ndpi_fill_prefix_mac(&prefix, ip, ip_len, 48);
148
10.4k
        node = ndpi_patricia_search_exact(p, &prefix);
149
10.4k
  if (node)
150
536
          ndpi_patricia_remove(p, node);
151
10.4k
      }
152
13.9k
    }
153
154
43.6k
  }
155
  /* Exact search of an added node */
156
574
  if (is_added)
157
362
    ndpi_patricia_search_exact(p, &prefix_added);
158
159
  /* "Random" best search. Remove if found */
160
574
  num_iteration = fuzzed_data.ConsumeIntegral<u_int8_t>();
161
52.6k
  for (i = 0; i < num_iteration; i++) {
162
52.0k
    if (tree_type == 0) {
163
16.4k
      if(fuzzed_data.remaining_bytes() > 4) {
164
10.7k
        std::vector<u_int8_t>data = fuzzed_data.ConsumeBytes<u_int8_t>(4);
165
10.7k
  ip = data.data();
166
10.7k
        ip_len = fuzzed_data.ConsumeIntegralInRange(0, 32);
167
10.7k
        ndpi_fill_prefix_v4(&prefix, (struct in_addr *)ip, ip_len, 32);
168
10.7k
        node = ndpi_patricia_search_best(p, &prefix);
169
10.7k
  if (node)
170
1.40k
          ndpi_patricia_remove(p, node);
171
10.7k
      }
172
35.5k
    } else if (tree_type == 1) {
173
19.2k
      if(fuzzed_data.remaining_bytes() > 16) {
174
11.1k
        std::vector<u_int8_t>data = fuzzed_data.ConsumeBytes<u_int8_t>(16);
175
11.1k
  ip = data.data();
176
11.1k
        ip_len = fuzzed_data.ConsumeIntegralInRange(0, 128);
177
11.1k
        ndpi_fill_prefix_v6(&prefix, (const struct in6_addr *)ip, ip_len, 128);
178
11.1k
        node = ndpi_patricia_search_best(p, &prefix);
179
11.1k
  if (node)
180
2.08k
          ndpi_patricia_remove(p, node);
181
11.1k
      }
182
19.2k
    } else {
183
16.3k
      if(fuzzed_data.remaining_bytes() > 6) {
184
11.8k
        std::vector<u_int8_t>data = fuzzed_data.ConsumeBytes<u_int8_t>(6);
185
11.8k
  ip = data.data();
186
11.8k
        ip_len = fuzzed_data.ConsumeIntegralInRange(0, 48);
187
11.8k
        ndpi_fill_prefix_mac(&prefix, ip, ip_len, 48);
188
11.8k
        node = ndpi_patricia_search_best(p, &prefix);
189
11.8k
  if (node)
190
709
          ndpi_patricia_remove(p, node);
191
11.8k
      }
192
16.3k
    }
193
52.0k
  }
194
  /* Best search of an added node */
195
574
  if (is_added)
196
362
    ndpi_patricia_search_best(p, &prefix_added);
197
198
574
  p_cloned = ndpi_patricia_clone(p);
199
  
200
574
  ndpi_patricia_process(p_cloned, process_ptree_data);
201
574
  ndpi_patricia_walk_tree_inorder(p_cloned, process3_ptree_data, NULL);
202
203
204
574
  ndpi_patricia_destroy(p, NULL);
205
574
  ndpi_patricia_destroy(p_cloned, NULL);
206
207
574
  return 0;
208
574
}