Coverage Report

Created: 2025-11-11 06:59

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
40.5k
static void process_ptree_data(ndpi_prefix_t *prefix, void *data) {
10
  /* Nothing to do */
11
40.5k
  assert(prefix && data == NULL);
12
40.5k
}
13
40.5k
static void process3_ptree_data(ndpi_patricia_node_t *node, void *data, void *user_data) {
14
  /* Nothing to do */
15
40.5k
  assert(node && data == NULL && user_data == NULL);
16
40.5k
}
17
18
594
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
19
594
  FuzzedDataProvider fuzzed_data(data, size);
20
594
  u_int16_t i, num_iteration, ip_len;
21
594
  ndpi_patricia_tree_t *p, *p_cloned;
22
594
  u_int16_t maxbits;
23
594
  int is_added = 0;
24
594
  ndpi_prefix_t prefix, prefix_added;
25
594
  u_char *ip;
26
594
  ndpi_patricia_node_t *node;
27
594
  int tree_type; /* 0: ipv4, 1: ipv6, 2: mac */
28
29
  /* Just to have some data */
30
594
  if (fuzzed_data.remaining_bytes() < 1024)
31
18
    return -1;
32
33
  /* To allow memory allocation failures */
34
576
  fuzz_set_alloc_callbacks_and_seed(size);
35
36
576
  tree_type = fuzzed_data.ConsumeIntegralInRange(0, 2);
37
576
  if (tree_type == 0)
38
219
    maxbits = 32;
39
357
  else if (tree_type == 1)
40
184
    maxbits = 128;
41
173
  else
42
173
    maxbits = 48;
43
44
576
  p = ndpi_patricia_new(maxbits);
45
46
576
  ndpi_patricia_get_maxbits(p);
47
576
  ndpi_patricia_process(p, process_ptree_data);
48
576
  ndpi_patricia_walk_tree_inorder(p, process3_ptree_data, NULL);
49
50
  /* "Random" add */
51
576
  num_iteration = fuzzed_data.ConsumeIntegral<u_int8_t>();
52
56.6k
  for (i = 0; i < num_iteration; i++) {
53
56.0k
    if (tree_type == 0) {
54
21.0k
      if(fuzzed_data.remaining_bytes() > 4) {
55
19.9k
        std::vector<u_int8_t>data = fuzzed_data.ConsumeBytes<u_int8_t>(4);
56
19.9k
  ip = data.data();
57
19.9k
        ip_len = fuzzed_data.ConsumeIntegralInRange(0, 33); /* 33 to force error */
58
19.9k
        ndpi_fill_prefix_v4(&prefix, (struct in_addr *)ip, ip_len, 32);
59
19.9k
        node = ndpi_patricia_lookup(p, &prefix);
60
        /* Keep one random node really added */
61
19.9k
  if (node && is_added == 0 && fuzzed_data.ConsumeBool()) {
62
128
          is_added = 1;
63
128
          prefix_added = prefix;
64
    /* Some random operations on this node */
65
128
          ndpi_patricia_get_node_prefix(node);
66
128
          ndpi_patricia_get_node_bits(node);
67
128
          ndpi_patricia_set_node_data(node, NULL);
68
128
          assert(ndpi_patricia_get_node_data(node) == NULL);
69
128
          ndpi_patricia_set_node_u64(node, 0);
70
128
          assert(ndpi_patricia_get_node_u64(node) == 0);
71
128
  }
72
19.9k
      }
73
35.0k
    } else if (tree_type == 1){
74
20.5k
      if(fuzzed_data.remaining_bytes() > 16) {
75
14.2k
        std::vector<u_int8_t>data = fuzzed_data.ConsumeBytes<u_int8_t>(16);
76
14.2k
  ip = data.data();
77
14.2k
        ip_len = fuzzed_data.ConsumeIntegralInRange(0, 129); /* 129 to force error */
78
14.2k
        ndpi_fill_prefix_v6(&prefix, (const struct in6_addr *)ip, ip_len, 128);
79
14.2k
        node = ndpi_patricia_lookup(p, &prefix);
80
        /* Keep one random node really added */
81
14.2k
  if (node && is_added == 0 && fuzzed_data.ConsumeBool()) {
82
135
          is_added = 1;
83
135
          prefix_added = prefix;
84
    /* Some random operations on this node */
85
135
          ndpi_patricia_get_node_prefix(node);
86
135
          ndpi_patricia_get_node_bits(node);
87
135
          ndpi_patricia_set_node_data(node, NULL);
88
135
          assert(ndpi_patricia_get_node_data(node) == NULL);
89
135
          ndpi_patricia_set_node_u64(node, 0);
90
135
          assert(ndpi_patricia_get_node_u64(node) == 0);
91
135
  }
92
14.2k
      }
93
20.5k
    } else {
94
14.4k
      if(fuzzed_data.remaining_bytes() > 6) {
95
12.6k
        std::vector<u_int8_t>data = fuzzed_data.ConsumeBytes<u_int8_t>(6);
96
12.6k
  ip = data.data();
97
12.6k
        ip_len = fuzzed_data.ConsumeIntegralInRange(0, 49); /* 49 to force error */
98
12.6k
        ndpi_fill_prefix_mac(&prefix, ip, ip_len, 48);
99
12.6k
        node = ndpi_patricia_lookup(p, &prefix);
100
        /* Keep one random node really added */
101
12.6k
  if (node && is_added == 0 && fuzzed_data.ConsumeBool()) {
102
89
          is_added = 1;
103
89
          prefix_added = prefix;
104
    /* Some random operations on this node */
105
89
          ndpi_patricia_get_node_prefix(node);
106
89
          ndpi_patricia_get_node_bits(node);
107
89
          ndpi_patricia_set_node_data(node, NULL);
108
89
          assert(ndpi_patricia_get_node_data(node) == NULL);
109
89
          ndpi_patricia_set_node_u64(node, 0);
110
89
          assert(ndpi_patricia_get_node_u64(node) == 0);
111
89
  }
112
12.6k
      }
113
14.4k
    }
114
56.0k
  }
115
116
576
  ndpi_patricia_process(p, process_ptree_data);
117
576
  ndpi_patricia_walk_tree_inorder(p, process3_ptree_data, NULL);
118
119
  /* "Random" exact search. Remove if found */
120
576
  num_iteration = fuzzed_data.ConsumeIntegral<u_int8_t>();
121
49.2k
  for (i = 0; i < num_iteration; i++) {
122
48.6k
    if (tree_type == 0) {
123
18.7k
      if(fuzzed_data.remaining_bytes() > 4) {
124
12.2k
        std::vector<u_int8_t>data = fuzzed_data.ConsumeBytes<u_int8_t>(4);
125
12.2k
  ip = data.data();
126
12.2k
        ip_len = fuzzed_data.ConsumeIntegralInRange(0, 32);
127
12.2k
        ndpi_fill_prefix_v4(&prefix, (struct in_addr *)ip, ip_len, 32);
128
12.2k
        node = ndpi_patricia_search_exact(p, &prefix);
129
12.2k
  if (node)
130
842
          ndpi_patricia_remove(p, node);
131
12.2k
      }
132
29.8k
    } else if (tree_type == 1) {
133
16.9k
      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
628
          ndpi_patricia_remove(p, node);
141
10.6k
      }
142
16.9k
    } else {
143
12.9k
      if(fuzzed_data.remaining_bytes() > 6) {
144
9.69k
        std::vector<u_int8_t>data = fuzzed_data.ConsumeBytes<u_int8_t>(6);
145
9.69k
  ip = data.data();
146
9.69k
        ip_len = fuzzed_data.ConsumeIntegralInRange(0, 48);
147
9.69k
        ndpi_fill_prefix_mac(&prefix, ip, ip_len, 48);
148
9.69k
        node = ndpi_patricia_search_exact(p, &prefix);
149
9.69k
  if (node)
150
570
          ndpi_patricia_remove(p, node);
151
9.69k
      }
152
12.9k
    }
153
154
48.6k
  }
155
  /* Exact search of an added node */
156
576
  if (is_added)
157
352
    ndpi_patricia_search_exact(p, &prefix_added);
158
159
  /* "Random" best search. Remove if found */
160
576
  num_iteration = fuzzed_data.ConsumeIntegral<u_int8_t>();
161
51.8k
  for (i = 0; i < num_iteration; i++) {
162
51.2k
    if (tree_type == 0) {
163
18.1k
      if(fuzzed_data.remaining_bytes() > 4) {
164
11.9k
        std::vector<u_int8_t>data = fuzzed_data.ConsumeBytes<u_int8_t>(4);
165
11.9k
  ip = data.data();
166
11.9k
        ip_len = fuzzed_data.ConsumeIntegralInRange(0, 32);
167
11.9k
        ndpi_fill_prefix_v4(&prefix, (struct in_addr *)ip, ip_len, 32);
168
11.9k
        node = ndpi_patricia_search_best(p, &prefix);
169
11.9k
  if (node)
170
1.23k
          ndpi_patricia_remove(p, node);
171
11.9k
      }
172
33.1k
    } else if (tree_type == 1) {
173
17.3k
      if(fuzzed_data.remaining_bytes() > 16) {
174
9.37k
        std::vector<u_int8_t>data = fuzzed_data.ConsumeBytes<u_int8_t>(16);
175
9.37k
  ip = data.data();
176
9.37k
        ip_len = fuzzed_data.ConsumeIntegralInRange(0, 128);
177
9.37k
        ndpi_fill_prefix_v6(&prefix, (const struct in6_addr *)ip, ip_len, 128);
178
9.37k
        node = ndpi_patricia_search_best(p, &prefix);
179
9.37k
  if (node)
180
1.70k
          ndpi_patricia_remove(p, node);
181
9.37k
      }
182
17.3k
    } else {
183
15.7k
      if(fuzzed_data.remaining_bytes() > 6) {
184
10.6k
        std::vector<u_int8_t>data = fuzzed_data.ConsumeBytes<u_int8_t>(6);
185
10.6k
  ip = data.data();
186
10.6k
        ip_len = fuzzed_data.ConsumeIntegralInRange(0, 48);
187
10.6k
        ndpi_fill_prefix_mac(&prefix, ip, ip_len, 48);
188
10.6k
        node = ndpi_patricia_search_best(p, &prefix);
189
10.6k
  if (node)
190
766
          ndpi_patricia_remove(p, node);
191
10.6k
      }
192
15.7k
    }
193
51.2k
  }
194
  /* Best search of an added node */
195
576
  if (is_added)
196
352
    ndpi_patricia_search_best(p, &prefix_added);
197
198
576
  p_cloned = ndpi_patricia_clone(p);
199
  
200
576
  ndpi_patricia_process(p_cloned, process_ptree_data);
201
576
  ndpi_patricia_walk_tree_inorder(p_cloned, process3_ptree_data, NULL);
202
203
204
576
  ndpi_patricia_destroy(p, NULL);
205
576
  ndpi_patricia_destroy(p_cloned, NULL);
206
207
576
  return 0;
208
576
}