Coverage Report

Created: 2025-11-20 06:48

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
42.0k
static void process_ptree_data(ndpi_prefix_t *prefix, void *data) {
10
  /* Nothing to do */
11
42.0k
  assert(prefix && data == NULL);
12
42.0k
}
13
42.0k
static void process3_ptree_data(ndpi_patricia_node_t *node, void *data, void *user_data) {
14
  /* Nothing to do */
15
42.0k
  assert(node && data == NULL && user_data == NULL);
16
42.0k
}
17
18
599
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
19
599
  FuzzedDataProvider fuzzed_data(data, size);
20
599
  u_int16_t i, num_iteration, ip_len;
21
599
  ndpi_patricia_tree_t *p, *p_cloned;
22
599
  u_int16_t maxbits;
23
599
  int is_added = 0;
24
599
  ndpi_prefix_t prefix, prefix_added;
25
599
  u_char *ip;
26
599
  ndpi_patricia_node_t *node;
27
599
  int tree_type; /* 0: ipv4, 1: ipv6, 2: mac */
28
29
  /* Just to have some data */
30
599
  if (fuzzed_data.remaining_bytes() < 1024)
31
18
    return -1;
32
33
  /* To allow memory allocation failures */
34
581
  fuzz_set_alloc_callbacks_and_seed(size);
35
36
581
  tree_type = fuzzed_data.ConsumeIntegralInRange(0, 2);
37
581
  if (tree_type == 0)
38
215
    maxbits = 32;
39
366
  else if (tree_type == 1)
40
188
    maxbits = 128;
41
178
  else
42
178
    maxbits = 48;
43
44
581
  p = ndpi_patricia_new(maxbits);
45
46
581
  ndpi_patricia_get_maxbits(p);
47
581
  ndpi_patricia_process(p, process_ptree_data);
48
581
  ndpi_patricia_walk_tree_inorder(p, process3_ptree_data, NULL);
49
50
  /* "Random" add */
51
581
  num_iteration = fuzzed_data.ConsumeIntegral<u_int8_t>();
52
57.8k
  for (i = 0; i < num_iteration; i++) {
53
57.3k
    if (tree_type == 0) {
54
22.2k
      if(fuzzed_data.remaining_bytes() > 4) {
55
21.1k
        std::vector<u_int8_t>data = fuzzed_data.ConsumeBytes<u_int8_t>(4);
56
21.1k
  ip = data.data();
57
21.1k
        ip_len = fuzzed_data.ConsumeIntegralInRange(0, 33); /* 33 to force error */
58
21.1k
        ndpi_fill_prefix_v4(&prefix, (struct in_addr *)ip, ip_len, 32);
59
21.1k
        node = ndpi_patricia_lookup(p, &prefix);
60
        /* Keep one random node really added */
61
21.1k
  if (node && is_added == 0 && fuzzed_data.ConsumeBool()) {
62
132
          is_added = 1;
63
132
          prefix_added = prefix;
64
    /* Some random operations on this node */
65
132
          ndpi_patricia_get_node_prefix(node);
66
132
          ndpi_patricia_get_node_bits(node);
67
132
          ndpi_patricia_set_node_data(node, NULL);
68
132
          assert(ndpi_patricia_get_node_data(node) == NULL);
69
132
          ndpi_patricia_set_node_u64(node, 0);
70
132
          assert(ndpi_patricia_get_node_u64(node) == 0);
71
132
  }
72
21.1k
      }
73
35.0k
    } else if (tree_type == 1){
74
20.3k
      if(fuzzed_data.remaining_bytes() > 16) {
75
14.3k
        std::vector<u_int8_t>data = fuzzed_data.ConsumeBytes<u_int8_t>(16);
76
14.3k
  ip = data.data();
77
14.3k
        ip_len = fuzzed_data.ConsumeIntegralInRange(0, 129); /* 129 to force error */
78
14.3k
        ndpi_fill_prefix_v6(&prefix, (const struct in6_addr *)ip, ip_len, 128);
79
14.3k
        node = ndpi_patricia_lookup(p, &prefix);
80
        /* Keep one random node really added */
81
14.3k
  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
14.3k
      }
93
20.3k
    } else {
94
14.6k
      if(fuzzed_data.remaining_bytes() > 6) {
95
12.8k
        std::vector<u_int8_t>data = fuzzed_data.ConsumeBytes<u_int8_t>(6);
96
12.8k
  ip = data.data();
97
12.8k
        ip_len = fuzzed_data.ConsumeIntegralInRange(0, 49); /* 49 to force error */
98
12.8k
        ndpi_fill_prefix_mac(&prefix, ip, ip_len, 48);
99
12.8k
        node = ndpi_patricia_lookup(p, &prefix);
100
        /* Keep one random node really added */
101
12.8k
  if (node && is_added == 0 && fuzzed_data.ConsumeBool()) {
102
91
          is_added = 1;
103
91
          prefix_added = prefix;
104
    /* Some random operations on this node */
105
91
          ndpi_patricia_get_node_prefix(node);
106
91
          ndpi_patricia_get_node_bits(node);
107
91
          ndpi_patricia_set_node_data(node, NULL);
108
91
          assert(ndpi_patricia_get_node_data(node) == NULL);
109
91
          ndpi_patricia_set_node_u64(node, 0);
110
91
          assert(ndpi_patricia_get_node_u64(node) == 0);
111
91
  }
112
12.8k
      }
113
14.6k
    }
114
57.3k
  }
115
116
581
  ndpi_patricia_process(p, process_ptree_data);
117
581
  ndpi_patricia_walk_tree_inorder(p, process3_ptree_data, NULL);
118
119
  /* "Random" exact search. Remove if found */
120
581
  num_iteration = fuzzed_data.ConsumeIntegral<u_int8_t>();
121
48.2k
  for (i = 0; i < num_iteration; i++) {
122
47.6k
    if (tree_type == 0) {
123
17.0k
      if(fuzzed_data.remaining_bytes() > 4) {
124
12.0k
        std::vector<u_int8_t>data = fuzzed_data.ConsumeBytes<u_int8_t>(4);
125
12.0k
  ip = data.data();
126
12.0k
        ip_len = fuzzed_data.ConsumeIntegralInRange(0, 32);
127
12.0k
        ndpi_fill_prefix_v4(&prefix, (struct in_addr *)ip, ip_len, 32);
128
12.0k
        node = ndpi_patricia_search_exact(p, &prefix);
129
12.0k
  if (node)
130
807
          ndpi_patricia_remove(p, node);
131
12.0k
      }
132
30.6k
    } else if (tree_type == 1) {
133
17.1k
      if(fuzzed_data.remaining_bytes() > 16) {
134
10.6k
        std::vector<u_int8_t>data = fuzzed_data.ConsumeBytes<u_int8_t>(16);
135
10.6k
  ip = data.data();
136
10.6k
        ip_len = fuzzed_data.ConsumeIntegralInRange(0, 128);
137
10.6k
        ndpi_fill_prefix_v6(&prefix, (const struct in6_addr *)ip, ip_len, 128);
138
10.6k
        node = ndpi_patricia_search_exact(p, &prefix);
139
10.6k
  if (node)
140
580
          ndpi_patricia_remove(p, node);
141
10.6k
      }
142
17.1k
    } else {
143
13.5k
      if(fuzzed_data.remaining_bytes() > 6) {
144
9.54k
        std::vector<u_int8_t>data = fuzzed_data.ConsumeBytes<u_int8_t>(6);
145
9.54k
  ip = data.data();
146
9.54k
        ip_len = fuzzed_data.ConsumeIntegralInRange(0, 48);
147
9.54k
        ndpi_fill_prefix_mac(&prefix, ip, ip_len, 48);
148
9.54k
        node = ndpi_patricia_search_exact(p, &prefix);
149
9.54k
  if (node)
150
498
          ndpi_patricia_remove(p, node);
151
9.54k
      }
152
13.5k
    }
153
154
47.6k
  }
155
  /* Exact search of an added node */
156
581
  if (is_added)
157
361
    ndpi_patricia_search_exact(p, &prefix_added);
158
159
  /* "Random" best search. Remove if found */
160
581
  num_iteration = fuzzed_data.ConsumeIntegral<u_int8_t>();
161
52.4k
  for (i = 0; i < num_iteration; i++) {
162
51.9k
    if (tree_type == 0) {
163
17.9k
      if(fuzzed_data.remaining_bytes() > 4) {
164
11.8k
        std::vector<u_int8_t>data = fuzzed_data.ConsumeBytes<u_int8_t>(4);
165
11.8k
  ip = data.data();
166
11.8k
        ip_len = fuzzed_data.ConsumeIntegralInRange(0, 32);
167
11.8k
        ndpi_fill_prefix_v4(&prefix, (struct in_addr *)ip, ip_len, 32);
168
11.8k
        node = ndpi_patricia_search_best(p, &prefix);
169
11.8k
  if (node)
170
1.17k
          ndpi_patricia_remove(p, node);
171
11.8k
      }
172
33.9k
    } else if (tree_type == 1) {
173
17.6k
      if(fuzzed_data.remaining_bytes() > 16) {
174
9.15k
        std::vector<u_int8_t>data = fuzzed_data.ConsumeBytes<u_int8_t>(16);
175
9.15k
  ip = data.data();
176
9.15k
        ip_len = fuzzed_data.ConsumeIntegralInRange(0, 128);
177
9.15k
        ndpi_fill_prefix_v6(&prefix, (const struct in6_addr *)ip, ip_len, 128);
178
9.15k
        node = ndpi_patricia_search_best(p, &prefix);
179
9.15k
  if (node)
180
1.57k
          ndpi_patricia_remove(p, node);
181
9.15k
      }
182
17.6k
    } else {
183
16.2k
      if(fuzzed_data.remaining_bytes() > 6) {
184
10.9k
        std::vector<u_int8_t>data = fuzzed_data.ConsumeBytes<u_int8_t>(6);
185
10.9k
  ip = data.data();
186
10.9k
        ip_len = fuzzed_data.ConsumeIntegralInRange(0, 48);
187
10.9k
        ndpi_fill_prefix_mac(&prefix, ip, ip_len, 48);
188
10.9k
        node = ndpi_patricia_search_best(p, &prefix);
189
10.9k
  if (node)
190
816
          ndpi_patricia_remove(p, node);
191
10.9k
      }
192
16.2k
    }
193
51.9k
  }
194
  /* Best search of an added node */
195
581
  if (is_added)
196
361
    ndpi_patricia_search_best(p, &prefix_added);
197
198
581
  p_cloned = ndpi_patricia_clone(p);
199
  
200
581
  ndpi_patricia_process(p_cloned, process_ptree_data);
201
581
  ndpi_patricia_walk_tree_inorder(p_cloned, process3_ptree_data, NULL);
202
203
204
581
  ndpi_patricia_destroy(p, NULL);
205
581
  ndpi_patricia_destroy(p_cloned, NULL);
206
207
581
  return 0;
208
581
}