Coverage Report

Created: 2026-08-03 07:15

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ndpi/fuzz/fuzz_dns_parse.c
Line
Count
Source
1
/*
2
 * fuzz_dns_parse
3
 *
4
 * What it tests:
5
 *   DNS query / answer RR walking in src/lib/protocols/dns.c. Calls
6
 *   ndpi_search_dns() directly with a synthesised packet_struct so the
7
 *   dissector is reached without depending on ndpi_detection_process_packet()
8
 *   and the full flow state machine. Exercises attacker-controlled uint16
9
 *   counts (num_queries, num_answers, authority_rrs, additional_rrs) and the
10
 *   name-compression pointer loops.
11
 *
12
 * Expected input format:
13
 *   Raw DNS payload (starts with the 12-byte ndpi_dns_packet_header prefix).
14
 *   The last byte is consumed as a selector:
15
 *     bit 0 -> TCP vs UDP framing
16
 *     bit 1 -> MDNS port (5353) vs DNS port (53)
17
 */
18
19
#include "ndpi_api.h"
20
#include "ndpi_private.h"
21
#include "fuzz_common_code.h"
22
23
#include <arpa/inet.h>
24
#include <stdint.h>
25
#include <stdio.h>
26
#include <string.h>
27
28
static struct ndpi_detection_module_struct *ndpi_struct = NULL;
29
static struct ndpi_flow_struct *ndpi_flow = NULL;
30
static struct ndpi_iphdr iph;
31
static struct ndpi_udphdr udph;
32
static struct ndpi_tcphdr tcph;
33
34
static char *path = NULL;
35
36
42
int LLVMFuzzerInitialize(int *argc, char ***argv) {
37
42
  (void)argc;
38
42
  path = dirname(strdup(*argv[0])); /* No errors; no free! */
39
42
  return 0;
40
42
}
41
42
3.34k
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
43
3.34k
  struct ndpi_packet_struct *packet;
44
3.34k
  uint8_t selector;
45
3.34k
  int is_tcp, is_mdns;
46
3.34k
  uint16_t port;
47
48
3.34k
  if (ndpi_struct == NULL) {
49
1
    fuzz_init_detection_module(&ndpi_struct, NULL, path);
50
1
    ndpi_flow = ndpi_calloc(1, sizeof(struct ndpi_flow_struct));
51
52
1
    memset(&iph, 0, sizeof(iph));
53
1
    iph.version = 4;
54
1
    iph.ihl = 5;
55
1
    iph.saddr = htonl(0x0A000001);
56
1
    iph.daddr = htonl(0x0A000002);
57
1
  }
58
59
3.34k
  if (size < 1)
60
0
    return 0;
61
62
3.34k
  fuzz_set_alloc_callbacks_and_seed(size);
63
64
3.34k
  selector = data[size - 1];
65
3.34k
  is_tcp  = selector & 0x01;
66
3.34k
  is_mdns = (selector & 0x02) ? 1 : 0;
67
3.34k
  port    = is_mdns ? 5353 : 53;
68
69
3.34k
  packet = &ndpi_struct->packet;
70
3.34k
  packet->payload = data;
71
3.34k
  packet->payload_packet_len = (u_int16_t)size;
72
3.34k
  packet->iph = &iph;
73
3.34k
  packet->iphv6 = NULL;
74
75
3.34k
  if (is_tcp) {
76
923
    memset(&tcph, 0, sizeof(tcph));
77
923
    tcph.source = htons(port);
78
923
    tcph.dest = htons(port);
79
923
    packet->tcp = &tcph;
80
923
    packet->udp = NULL;
81
923
    iph.protocol = 6;
82
2.42k
  } else {
83
2.42k
    memset(&udph, 0, sizeof(udph));
84
2.42k
    udph.source = htons(port);
85
2.42k
    udph.dest = htons(port);
86
2.42k
    packet->udp = &udph;
87
2.42k
    packet->tcp = NULL;
88
2.42k
    iph.protocol = 17;
89
2.42k
  }
90
91
3.34k
  memset(ndpi_flow, 0, sizeof(struct ndpi_flow_struct));
92
3.34k
  ndpi_flow->l4_proto = is_tcp ? IPPROTO_TCP : IPPROTO_UDP;
93
94
3.34k
  ndpi_search_dns(ndpi_struct, ndpi_flow);
95
3.34k
  ndpi_free_flow_data(ndpi_flow);
96
97
3.34k
  return 0;
98
3.34k
}