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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
|
#include "ndpi_api.h"
#include "../src/lib/third_party/include/ahocorasick.h"
#include "fuzz_common_code.h"
#include <stdint.h>
#include <stdio.h>
#include <assert.h>
#include "fuzzer/FuzzedDataProvider.h"
extern "C" int ac_domain_match_handler(AC_MATCH_t *m, AC_TEXT_t *txt, AC_REP_t *match);
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
FuzzedDataProvider fuzzed_data(data, size);
u_int16_t i, j, num_iteration, is_added = 0;
AC_AUTOMATA_t *a;
void *a2;
MATCH_CALLBACK_f mc;
struct ac_stats stats;
AC_PATTERN_t ac_pattern;
char *value_dup, *value_added;
AC_REP_t match;
AC_TEXT_t ac_input_text;
u_int16_t protocol_id;
ndpi_protocol_category_t category;
ndpi_protocol_breed_t breed;
u_int32_t unused;
/* TODO: real string instead of random bytes */
/* Use both APIs */
/* Just to have some data */
if (fuzzed_data.remaining_bytes() < 1024)
return -1;
/* To allow memory allocation failures */
fuzz_set_alloc_callbacks_and_seed(size);
if (fuzzed_data.ConsumeBool())
mc = ac_domain_match_handler;
else
mc = NULL;
ac_automata_enable_debug(0);
a = ac_automata_init(mc);
if (fuzzed_data.ConsumeBool())
a2 = ndpi_init_automa();
else
a2 = ndpi_init_automa_domain();
if (fuzzed_data.ConsumeBool())
ac_automata_feature(a, AC_FEATURE_DEBUG);
if (fuzzed_data.ConsumeBool())
ac_automata_feature(a, AC_FEATURE_LC);
if (fuzzed_data.ConsumeBool())
ac_automata_feature(a, AC_FEATURE_NO_ROOT_RANGE);
if (fuzzed_data.ConsumeBool())
ac_automata_name(a, (char *)fuzzed_data.ConsumeRandomLengthString(32).c_str(),
fuzzed_data.ConsumeBool());
num_iteration = fuzzed_data.ConsumeIntegral<u_int8_t>();
for (i = 0; i < num_iteration; i++) {
std::string value = fuzzed_data.ConsumeRandomLengthString(64);
/* Adding (sometimes) the same string twice, with different "properties" */
for (j = 0; j < 2; j++) {
if (j == 1 && fuzzed_data.ConsumeBool())
continue;
memset(&ac_pattern, 0, sizeof(ac_pattern));
value_dup = ndpi_strdup(value.c_str());
if (!value_dup)
continue;
ac_pattern.astring = value_dup;
ac_pattern.length = strlen(value_dup);
ac_pattern.rep.number = fuzzed_data.ConsumeIntegral<u_int16_t>();
ac_pattern.rep.category = 0;
ac_pattern.rep.breed = 0;
ac_pattern.rep.level = fuzzed_data.ConsumeIntegralInRange(0, 2);
ac_pattern.rep.from_start = fuzzed_data.ConsumeBool();
ac_pattern.rep.at_end = fuzzed_data.ConsumeBool();
ac_pattern.rep.dot = memchr(value_dup, '.', strlen(value_dup)) != NULL;
if (ac_automata_add(a, &ac_pattern) != ACERR_SUCCESS) {
ndpi_free(value_dup);
} else {
/* Keep one random string really added */
if (is_added == 0 && fuzzed_data.ConsumeBool()) {
value_added = ndpi_strdup(value_dup);
if (value_added)
is_added = 1;
}
}
}
value_dup = ndpi_strdup(value.c_str());
if (!value_dup)
continue;
if (ndpi_add_string_to_automa(a2, value_dup) != 0)
ndpi_free(value_dup);
}
if (fuzzed_data.ConsumeBool()) {
ac_automata_finalize(a);
ndpi_finalize_automa(a2);
}
/* "Random" search */
num_iteration = fuzzed_data.ConsumeIntegral<u_int8_t>();
for (i = 0; i < num_iteration; i++) {
std::string value = fuzzed_data.ConsumeRandomLengthString(64);
value_dup = ndpi_strdup(value.c_str());
if (!value_dup)
continue;
ac_input_text.astring = value_dup;
ac_input_text.length = strlen(value_dup);
ac_input_text.option = 0;
ac_automata_search(a, &ac_input_text, &match);
ndpi_free(value_dup);
ndpi_match_string(a2, fuzzed_data.ConsumeBool() ? NULL : (char *)value.c_str());
ndpi_match_string_value(a2, fuzzed_data.ConsumeBool() ? NULL : (char *)value.c_str(),
strlen(value.c_str()), &unused);
ndpi_match_string_protocol_id(a2, (char *)value.c_str(), strlen(value.c_str()),
&protocol_id, &category, &breed);
}
/* Search of an added node */
if (is_added) {
ac_input_text.astring = value_added;
ac_input_text.length = strlen(value_added);
ac_input_text.option = 0;
ac_automata_search(a, &ac_input_text, &match);
ndpi_match_string(a2, value_added);
ndpi_match_string_value(a2, value_added, strlen(value_added), &unused);
ndpi_match_string_protocol_id(a2, value_added, strlen(value_added),
&protocol_id, &category, &breed);
ndpi_free(value_added);
}
ac_automata_dump(a, stdout);
ac_automata_get_stats(a, &stats);
ac_automata_release(a, 1);
ndpi_free_automa(a2);
return 0;
}
|