-
Notifications
You must be signed in to change notification settings - Fork 14
/
decode_fuzzer.c
129 lines (113 loc) · 3.52 KB
/
decode_fuzzer.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/* darkstat 3
* copyright (c) 2022 Emil Mikulic.
*
* decode_fuzzer.c: fuzzer for the decoders in decode.c
*
* Permission to use, copy, modify, and distribute this file for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* Usage:
* clang -g -O2 -fsanitize=fuzzer,address decode_fuzzer.c -o decode_fuzzer
* ./decode_fuzzer decode_corpus
*
* Try also: -print_coverage=1
*
* The first two bytes of the fuzzer input are treated as the linktype, and
* dispatch is done via getlinkhdr().
*/
#include "addr.c"
#include "decode.c"
#include "linktypes.c"
/* This is fine. It means decode_ether won't call into decode_pppoe,
* but linktype DLT_PPP_ETHER will, so we still get coverage.
*/
int opt_want_pppoe = 0;
/* Only enable verbose if debugging the fuzzer. */
static const int verbose = 0;
void verbosef(const char *format, ...) {
if (!verbose) return;
va_list va;
va_start(va, format);
printf("verbosef: ");
vprintf(format, va);
printf("\n");
va_end(va);
}
static void hexdump(const u_char *buf,
const uint32_t len) {
uint32_t i;
uint32_t col = 0;
printf("packet of %u bytes:\n", len);
for (i=0; i<len; i++) {
if (col == 0) printf(" ");
printf("%02x ", buf[i]);
col += 3;
if (col >= 72) {
printf("\n");
col = 0;
}
}
if (col != 0) printf("\n");
}
static void print_summary(const struct pktsummary* s) {
printf("pktsummary:\n");
printf(" src=%s\n", addr_to_str(&s->src));
printf(" dst=%s\n", addr_to_str(&s->dst));
printf(" len=0x%04x (%d) proto=0x%02x tcp_flags=0x%02x\n",
s->len, s->len, s->proto, s->tcp_flags);
printf(" src_port=0x%04x (%d) dst_port=0x%04x (%d)\n",
s->src_port, s->src_port, s->dst_port, s->dst_port);
printf(" src_mac=%02x:%02x:%02x:%02x:%02x:%02x\n",
s->src_mac[0],
s->src_mac[1],
s->src_mac[2],
s->src_mac[3],
s->src_mac[4],
s->src_mac[5]);
printf(" dst_mac=%02x:%02x:%02x:%02x:%02x:%02x\n",
s->dst_mac[0],
s->dst_mac[1],
s->dst_mac[2],
s->dst_mac[3],
s->dst_mac[4],
s->dst_mac[5]);
}
static void decode(int linktype, const uint8_t* data, size_t size) {
const struct linkhdr *lh = getlinkhdr(linktype);
if (verbose) {
printf(">> linktype=%d (%s)\n", linktype, get_linktype_name(linktype));
hexdump(data, size);
}
if (lh == NULL) {
return; /* No decoder for this linktype. */
}
struct pcap_pkthdr hdr;
hdr.caplen = size;
struct pktsummary sm;
memset(&sm, 0, sizeof(sm));
int ret = lh->decoder(&hdr, data, &sm);
if (verbose) {
printf("ret = %d\n", ret);
if (ret) print_summary(&sm);
}
}
int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
int16_t linktype;
const int SZ = sizeof(linktype);
if (size < SZ) {
return 0; /* Too short. */
}
memcpy(&linktype, data, SZ);
decode(linktype, data + SZ, size - SZ);
return 0;
}
/* vim:set ts=2 sw=2 sts=2 expandtab tw=78: */