Coverage Report

Created: 2025-10-12 06:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ndpi/fuzz/fuzz_ndpi_reader_pl7m_simplest.c
Line
Count
Source
1
#include "reader_util.h"
2
#include "ndpi_api.h"
3
#include "fuzz_common_code.h"
4
5
#include <pcap/pcap.h>
6
7
#include <errno.h>
8
#include <stdint.h>
9
#include <stdio.h>
10
11
#ifdef ENABLE_PCAP_L7_MUTATOR
12
#include "pl7m.h"
13
#endif
14
15
struct ndpi_workflow_prefs *prefs = NULL;
16
struct ndpi_workflow *workflow = NULL;
17
struct ndpi_global_context *g_ctx;
18
19
u_int8_t enable_payload_analyzer = 0;
20
u_int8_t enable_flow_stats = 1;
21
u_int8_t human_readeable_string_len = 5;
22
u_int8_t max_num_udp_dissected_pkts = 0, max_num_tcp_dissected_pkts = 0; /* Disable limits at application layer */;
23
int malloc_size_stats = 0;
24
FILE *fingerprint_fp = NULL;
25
char *addr_dump_path = NULL;
26
int monitoring_enabled = 1;
27
u_int8_t enable_doh_dot_detection = 0;
28
29
extern void ndpi_report_payload_stats(FILE *out);
30
31
#ifdef CRYPT_FORCE_NO_AESNI
32
extern int force_no_aesni;
33
#endif
34
35
#ifdef ENABLE_PCAP_L7_MUTATOR
36
size_t LLVMFuzzerCustomMutator(uint8_t *Data, size_t Size,
37
0
                               size_t MaxSize, unsigned int Seed) {
38
0
  return pl7m_mutator(Data, Size, MaxSize, Seed);
39
0
}
40
#endif
41
42
701k
static void node_cleanup_walker(const void *node, ndpi_VISIT which, int depth, void *user_data) {
43
701k
  struct ndpi_flow_info *flow = *(struct ndpi_flow_info **) node;
44
45
701k
  (void)depth;
46
701k
  (void)user_data;
47
48
701k
  if((which == ndpi_preorder) || (which == ndpi_leaf)) { /* Avoid walking the same node multiple times */
49
319k
    if((!flow->detection_completed) && flow->ndpi_flow) {
50
266k
      u_int8_t proto_guessed;
51
52
266k
      flow->detected_protocol = ndpi_detection_giveup(workflow->ndpi_struct,
53
266k
                                                      flow->ndpi_flow, &proto_guessed);
54
266k
    }
55
56
319k
    process_ndpi_collected_info(workflow, flow);
57
319k
  }
58
701k
}
59
60
205k
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
61
205k
  pcap_t * pkts;
62
205k
  const u_char *pkt;
63
205k
  struct pcap_pkthdr *header;
64
205k
  int r;
65
205k
  char errbuf[PCAP_ERRBUF_SIZE];
66
205k
  u_int i;
67
205k
  FILE *fd;
68
69
205k
  if (prefs == NULL) {
70
10
    prefs = calloc(sizeof(struct ndpi_workflow_prefs), 1); /* No failure here */
71
10
    prefs->decode_tunnels = 1;
72
10
    prefs->num_roots = 16;
73
10
    prefs->max_ndpi_flows = 16 * 1024 * 1024;
74
10
    prefs->quiet_mode = 0;
75
76
#ifdef ENABLE_MEM_ALLOC_FAILURES
77
    fuzz_set_alloc_callbacks();
78
#endif
79
80
10
    g_ctx = ndpi_global_init();
81
82
10
    workflow = ndpi_workflow_init(prefs, NULL /* pcap handler will be set later */, 0, ndpi_serialization_format_json, g_ctx);
83
84
10
    ndpi_workflow_set_flow_callback(workflow, NULL, NULL); /* No real callback */
85
86
10
    ndpi_set_config(workflow->ndpi_struct, NULL, "log.level", "3");
87
10
    ndpi_set_config(workflow->ndpi_struct, "all", "log", "1");
88
89
10
    ndpi_load_domain_suffixes(workflow->ndpi_struct, "public_suffix_list.dat");
90
10
    ndpi_load_categories_dir(workflow->ndpi_struct, "./lists/");
91
10
    ndpi_load_protocols_dir(workflow->ndpi_struct, "./lists/protocols/");
92
10
    ndpi_load_protocols_file(workflow->ndpi_struct, "protos.txt");
93
10
    ndpi_load_categories_file(workflow->ndpi_struct, "categories.txt", NULL);
94
10
    ndpi_load_risk_domain_file(workflow->ndpi_struct, "risky_domains.txt");
95
10
    ndpi_load_malicious_ja4_file(workflow->ndpi_struct, "ja4_fingerprints.csv");
96
10
    ndpi_load_tcp_fingerprint_file(workflow->ndpi_struct, "tcp_fingerprints.csv");
97
10
    ndpi_load_malicious_sha1_file(workflow->ndpi_struct, "sha1_fingerprints.csv");
98
99
#ifdef ENABLE_ONLY_SUBCLASSIFICATION
100
    ndpi_set_config(workflow->ndpi_struct, NULL, "filename.config", "only_classification.conf");
101
#else
102
103
10
    ndpi_set_config(workflow->ndpi_struct, NULL, "packets_limit_per_flow", "255");
104
10
    ndpi_set_config(workflow->ndpi_struct, NULL, "flow.track_payload", "1");
105
10
    ndpi_set_config(workflow->ndpi_struct, NULL, "tcp_ack_payload_heuristic", "1");
106
10
    ndpi_set_config(workflow->ndpi_struct, NULL, "fully_encrypted_heuristic", "1");
107
10
    ndpi_set_config(workflow->ndpi_struct, "dns", "subclassification", "1");
108
10
    ndpi_set_config(workflow->ndpi_struct, "tls", "application_blocks_tracking", "1");
109
10
#ifndef ENABLE_CONFIG2
110
10
    ndpi_set_config(workflow->ndpi_struct, "stun", "max_packets_extra_dissection", "40");
111
10
    ndpi_set_config(workflow->ndpi_struct, "zoom", "max_packets_extra_dissection", "255");
112
10
    ndpi_set_config(workflow->ndpi_struct, "rtp", "search_for_stun", "1");
113
10
#endif
114
10
    ndpi_set_config(workflow->ndpi_struct, "openvpn", "dpi.heuristics", "0x01");
115
10
    ndpi_set_config(workflow->ndpi_struct, "openvpn", "dpi.heuristics.num_messages", "20");
116
10
    ndpi_set_config(workflow->ndpi_struct, "tls", "metadata.ja4r_fingerprint", "1");
117
10
    ndpi_set_config(workflow->ndpi_struct, "tls", "dpi.heuristics", "0x07");
118
10
    ndpi_set_config(workflow->ndpi_struct, "tls", "dpi.heuristics.max_packets_extra_dissection", "40");
119
10
    ndpi_set_config(workflow->ndpi_struct, "stun", "monitoring", "1");
120
10
    ndpi_set_config(workflow->ndpi_struct, NULL, "dpi.address_cache_size", "8192");
121
10
    ndpi_set_config(workflow->ndpi_struct, NULL, "hostname_dns_check", "1");
122
123
#ifdef ENABLE_CONFIG2
124
    ndpi_set_config(workflow->ndpi_struct, NULL, "flow_risk.all.info", "0");
125
    ndpi_set_config(workflow->ndpi_struct, NULL, "metadata.tcp_fingerprint_format", "1");
126
    ndpi_set_config(workflow->ndpi_struct, NULL, "metadata.ndpi_fingerprint_format", "1");
127
#endif
128
129
10
#endif /* ENABLE_ONLY_SUBCLASSIFICATION */
130
131
10
    ndpi_finalize_initialization(workflow->ndpi_struct);
132
133
#ifdef ENABLE_FINGERPRINT_FP
134
    fingerprint_fp = stdout;
135
#endif
136
137
#ifdef CRYPT_FORCE_NO_AESNI
138
    force_no_aesni = 1;
139
#endif
140
141
#ifdef ENABLE_PAYLOAD_ANALYZER
142
   enable_payload_analyzer = 1;
143
#endif
144
10
  }
145
146
#ifdef ENABLE_MEM_ALLOC_FAILURES
147
  /* Don't fail memory allocations until init phase is done */
148
  fuzz_set_alloc_callbacks_and_seed(Size);
149
#endif
150
151
205k
  fd = buffer_to_file(Data, Size);
152
205k
  if (fd == NULL)
153
0
    return 0;
154
155
205k
  pkts = pcap_fopen_offline(fd, errbuf);
156
205k
  if (pkts == NULL) {
157
19
    fclose(fd);
158
19
    return 0;
159
19
  }
160
205k
  if (ndpi_is_datalink_supported(pcap_datalink(pkts)) == 0)
161
317
  {
162
    /* Do not fail if the datalink type is not supported (may happen often during fuzzing). */
163
317
    pcap_close(pkts);
164
317
    return 0;
165
317
  }
166
167
205k
  workflow->pcap_handle = pkts;
168
  /* Init flow tree */
169
205k
  workflow->ndpi_flows_root = ndpi_calloc(workflow->prefs.num_roots, sizeof(void *));
170
205k
  if(!workflow->ndpi_flows_root) {
171
2
    pcap_close(pkts);
172
2
    return 0;
173
2
  }
174
175
205k
  header = NULL;
176
205k
  r = pcap_next_ex(pkts, &header, &pkt);
177
12.7M
  while (r > 0) {
178
    /* allocate an exact size buffer to check overflows */
179
12.5M
    uint8_t *packet_checked = malloc(header->caplen);
180
181
12.5M
    if(packet_checked) {
182
12.5M
      ndpi_risk flow_risk;
183
12.5M
      struct ndpi_flow_info *flow = NULL; /* unused */
184
185
12.5M
      memcpy(packet_checked, pkt, header->caplen);
186
12.5M
      ndpi_workflow_process_packet(workflow, header, packet_checked, &flow_risk, &flow);
187
12.5M
      free(packet_checked);
188
12.5M
    }
189
190
12.5M
    r = pcap_next_ex(pkts, &header, &pkt);
191
12.5M
  }
192
205k
  pcap_close(pkts);
193
194
  /* Free flow trees */
195
3.49M
  for(i = 0; i < workflow->prefs.num_roots; i++) {
196
3.28M
    ndpi_twalk(workflow->ndpi_flows_root[i], node_cleanup_walker, NULL);
197
3.28M
    ndpi_tdestroy(workflow->ndpi_flows_root[i], ndpi_flow_info_freer);
198
3.28M
  }
199
205k
  ndpi_free(workflow->ndpi_flows_root);
200
  /* Free payload analyzer data */
201
205k
  if(enable_payload_analyzer)
202
17.3k
    ndpi_report_payload_stats(stdout);
203
204
#ifdef ENABLE_PAYLOAD_ANALYZER
205
  ndpi_update_params(SPLT_PARAM_TYPE, "splt_param.txt");
206
  ndpi_update_params(BD_PARAM_TYPE, "bd_param.txt");
207
  ndpi_update_params(2, ""); /* invalid */
208
#endif
209
210
205k
  return 0;
211
205k
}