Skip to content

Commit 7a972fe

Browse files
committed
fuzz: improve coverage and add fuzzers for anomaly model and isolation forest algs
1 parent 70b7d94 commit 7a972fe

8 files changed

Lines changed: 126 additions & 9 deletions

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@
6868
/fuzz/fuzz_alg_bins
6969
/fuzz/fuzz_alg_hll
7070
/fuzz/fuzz_alg_hw_rsi_outliers_da
71+
/fuzz/fuzz_alg_isolationforest
72+
/fuzz/fuzz_alg_anomalymodel
7173
/fuzz/fuzz_alg_jitter
7274
/fuzz/fuzz_alg_crc32_md5
7375
/fuzz/fuzz_alg_ses_des

fuzz/Makefile.am

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
bin_PROGRAMS = fuzz_process_packet fuzz_ndpi_reader fuzz_ndpi_reader_nalloc fuzz_ndpi_reader_alloc_fail fuzz_ndpi_reader_payload_analyzer fuzz_quic_get_crypto_data fuzz_config fuzz_community_id fuzz_serialization fuzz_tls_certificate fuzz_dga fuzz_is_stun_udp fuzz_is_stun_tcp fuzz_match_custom_category fuzz_tls_client_server_hello fuzz_dns_parse fuzz_http_parse fuzz_ndpi_decode_tls_blocks
22
#Alghoritms
3-
bin_PROGRAMS += fuzz_alg_ranking fuzz_alg_bins fuzz_alg_hll fuzz_alg_hw_rsi_outliers_da fuzz_alg_jitter fuzz_alg_ses_des fuzz_alg_crc32_md5 fuzz_alg_shoco fuzz_alg_memmem fuzz_alg_strnstr fuzz_alg_quick_encryption
3+
bin_PROGRAMS += fuzz_alg_ranking fuzz_alg_bins fuzz_alg_hll fuzz_alg_hw_rsi_outliers_da fuzz_alg_jitter fuzz_alg_ses_des fuzz_alg_crc32_md5 fuzz_alg_shoco fuzz_alg_memmem fuzz_alg_strnstr fuzz_alg_quick_encryption fuzz_alg_isolationforest fuzz_alg_anomalymodel
44
#Data structures
55
bin_PROGRAMS += fuzz_ds_patricia fuzz_ds_ahocorasick fuzz_ds_libcache fuzz_ds_tree fuzz_ds_ptree fuzz_ds_hash fuzz_ds_cmsketch fuzz_ds_bitmap64_fuse fuzz_ds_domain_classify fuzz_ds_kdtree fuzz_ds_btree fuzz_ds_address_cache fuzz_ds_bitmap fuzz_ds_filter
66
#Third party
@@ -86,6 +86,12 @@ fuzz_alg_hll_LINK = $(FUZZ_LINK_COMMAND)
8686
fuzz_alg_hw_rsi_outliers_da_SOURCES = fuzz_alg_hw_rsi_outliers_da.cpp fuzz_common_code.c
8787
fuzz_alg_hw_rsi_outliers_da_LINK = $(FUZZ_LINK_COMMAND)
8888

89+
fuzz_alg_isolationforest_SOURCES = fuzz_alg_isolationforest.cpp
90+
fuzz_alg_isolationforest_LINK = $(FUZZ_LINK_COMMAND)
91+
92+
fuzz_alg_anomalymodel_SOURCES = fuzz_alg_anomalymodel.cpp cpp fuzz_common_code.c
93+
fuzz_alg_anomalymodel_LINK = $(FUZZ_LINK_COMMAND)
94+
8995
fuzz_alg_jitter_SOURCES = fuzz_alg_jitter.cpp fuzz_common_code.c
9096
fuzz_alg_jitter_LINK = $(FUZZ_LINK_COMMAND)
9197

fuzz/fuzz_alg_anomalymodel.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#include "ndpi_api.h"
2+
#include "fuzz_common_code.h"
3+
4+
#include <stdint.h>
5+
#include <stdio.h>
6+
#include "fuzzer/FuzzedDataProvider.h"
7+
8+
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
9+
FuzzedDataProvider fuzzed_data(data, size);
10+
u_int32_t n_normal, n_attacks, n_features, i, j;
11+
ndpi_anomaly_model *m;
12+
13+
/* To allow memory allocation failures */
14+
fuzz_set_alloc_callbacks_and_seed(size);
15+
16+
n_features = fuzzed_data.ConsumeIntegralInRange<u_int32_t>(1, 8);
17+
n_normal = fuzzed_data.ConsumeIntegral<u_int8_t>();
18+
n_attacks = fuzzed_data.ConsumeIntegral<u_int8_t>();
19+
m = ndpi_alloc_anomaly_model(n_features);
20+
21+
double *row = (double *)malloc(sizeof(double) * n_features); /* No failure here */
22+
23+
for(i = 0; i < n_normal; i++) {
24+
for(j = 0; j < n_features; j++)
25+
row[j] = fuzzed_data.ConsumeFloatingPoint<double>();
26+
27+
ndpi_train_anomaly_model(m, row);
28+
}
29+
for(i = 0; i < n_attacks; i++) {
30+
for(j = 0; j < n_features; j++)
31+
row[j] = fuzzed_data.ConsumeFloatingPoint<double>();
32+
33+
ndpi_compute_anomaly_score(m, row);
34+
}
35+
36+
ndpi_free_anomaly_model(m);
37+
free(row);
38+
39+
return 0;
40+
}

fuzz/fuzz_alg_hw_rsi_outliers_da.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
9393
ndpi_data_min(a);
9494
ndpi_data_max(a);
9595
ndpi_data_jitter(a);
96+
ndpi_data_burstiness(a);
9697
ndpi_data_last(a);
9798
ndpi_data_window_average(a);
9899
ndpi_data_window_variance(a);

fuzz/fuzz_alg_isolationforest.cpp

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#include "ndpi_api.h"
2+
3+
#include <stdint.h>
4+
#include <stdio.h>
5+
#include "fuzzer/FuzzedDataProvider.h"
6+
7+
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
8+
FuzzedDataProvider fuzzed_data(data, size);
9+
u_int32_t n_normal, n_attacks, n_features, i, j;
10+
double **d;
11+
void *f;
12+
13+
/* isolationforest code doesn't handle allocation failures */
14+
15+
/* Data set */
16+
n_features = fuzzed_data.ConsumeIntegralInRange<u_int32_t>(0, 8);
17+
n_normal = fuzzed_data.ConsumeIntegral<u_int8_t>();
18+
n_attacks = fuzzed_data.ConsumeIntegral<u_int8_t>();
19+
20+
d = (double **)ndpi_malloc(sizeof(double *) * (n_normal + n_attacks));
21+
22+
for(i = 0; i < n_normal; i++) {
23+
u_int32_t l = sizeof(double) * n_features;
24+
double *row = (double *)ndpi_malloc(l);
25+
26+
d[i] = row;
27+
for(j = 0; j < n_features; j++)
28+
row[j] = fuzzed_data.ConsumeFloatingPoint<double>();
29+
}
30+
for(i = 0; i < n_attacks; i++) {
31+
u_int32_t l = sizeof(double) * n_features;
32+
double *row = (double *)ndpi_malloc(l);
33+
34+
d[n_normal + i] = row;
35+
for(j = 0; j < n_features; j++)
36+
row[j] = fuzzed_data.ConsumeFloatingPoint<double>();
37+
}
38+
39+
f = ndpi_alloc_iforest(d, n_normal, n_features);
40+
for(i = 0; i < n_normal + n_attacks; i++) {
41+
ndpi_iforest_score(f, d[i]);
42+
}
43+
44+
ndpi_free_iforest(f);
45+
46+
for(i = 0; i < n_normal + n_attacks; i++)
47+
ndpi_free(d[i]);
48+
ndpi_free(d);
49+
50+
return 0;
51+
}

fuzz/fuzz_alg_ranking.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
99
FuzzedDataProvider fuzzed_data(data, size);
1010
u_int16_t i, j;
11-
ndpi_ranking rank;
11+
ndpi_ranking rank, rank2;
1212
u_int16_t max_num_entries, num_epochs;
1313
u_int32_t now, prev_epoch;
1414
ndpi_ranking_epoch_entry *entries;
@@ -45,9 +45,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
4545
ndpi_print_ranking(&rank);
4646

4747
snprintf(path, sizeof(path), "/tmp/ranking.%u.test", (unsigned int)getpid());
48-
if(ndpi_serialize_ranking(&rank, path)) {
49-
ndpi_term_ranking(&rank);
50-
ndpi_deserialize_ranking(&rank, path);
48+
if(ndpi_serialize_ranking(&rank, fuzzed_data.ConsumeBool() ? path : NULL)) {
49+
if(ndpi_deserialize_ranking(&rank2, fuzzed_data.ConsumeBool() ? path : NULL))
50+
ndpi_term_ranking(&rank2);
5151
unlink(path);
5252
}
5353

fuzz/fuzz_config.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,14 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
330330
ndpi_rtp_payload_type2str(fuzzed_data.ConsumeIntegral<u_int8_t>(), fuzzed_data.ConsumeIntegral<u_int32_t>());
331331
ndpi_rtp_payload_type2str(127, fuzzed_data.ConsumeIntegral<u_int32_t>());
332332

333+
ndpi_ikev2_dh_name(fuzzed_data.ConsumeIntegral<u_int8_t>());
334+
ndpi_ikev2_integ_name(fuzzed_data.ConsumeIntegral<u_int8_t>());
335+
ndpi_ikev2_prf_name(fuzzed_data.ConsumeIntegral<u_int8_t>());
336+
ndpi_ikev2_encr_name(fuzzed_data.ConsumeIntegral<u_int8_t>());
337+
338+
char unknown_curve[8];
339+
ndpi_tls_elliptic_curve2str(fuzzed_data.ConsumeIntegral<u_int16_t>(), unknown_curve);
340+
333341
char buf2[16];
334342
ndpi_entropy2str(fuzzed_data.ConsumeFloatingPoint<float>(), fuzzed_data.ConsumeBool() ? buf2 : NULL, sizeof(buf2));
335343

src/lib/ndpi_analyze.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2276,8 +2276,10 @@ bool ndpi_deserialize_ranking(ndpi_ranking *rank, const char *path) {
22762276
if(rank->epochs) {
22772277
n_read = fread(rank->epochs, rank->header.epochs_memory_len, 1, fd);
22782278

2279-
if(n_read != 1)
2279+
if(n_read != 1) {
2280+
ndpi_free(rank->epochs);
22802281
ret = false;
2282+
}
22812283
} else
22822284
ret = false;
22832285
}
@@ -2464,8 +2466,10 @@ ndpi_anomaly_model* ndpi_alloc_anomaly_model(u_int16_t n_features) {
24642466
/* *********************** */
24652467

24662468
void ndpi_free_anomaly_model(ndpi_anomaly_model *m) {
2467-
if(m->training_data) ndpi_free(m->training_data);
2468-
ndpi_free(m);
2469+
if(m) {
2470+
if(m->training_data) ndpi_free(m->training_data);
2471+
ndpi_free(m);
2472+
}
24692473
}
24702474

24712475
/* *********************** */
@@ -2506,6 +2510,8 @@ static void ndpi_normalize_vector_L2(double *training_data, u_int32_t num) {
25062510
/* *********************** */
25072511

25082512
bool ndpi_train_anomaly_model(ndpi_anomaly_model *m, double *training_data) {
2513+
if(!m || !training_data)
2514+
return(false);
25092515
u_int32_t len = sizeof(double) * m->n_features;
25102516

25112517
ndpi_normalize_vector_L1(training_data, m->n_features);
@@ -2571,7 +2577,10 @@ bool ndpi_compute_anomaly_score(ndpi_anomaly_model *m,
25712577
double *testing_data) {
25722578
u_int32_t i;
25732579
double max_distance = 0;
2574-
2580+
2581+
if(!m || !testing_data)
2582+
return(false);
2583+
25752584
ndpi_normalize_vector_L1(testing_data, m->n_features);
25762585

25772586
for(i=0; i<m->n_samples; i++) {

0 commit comments

Comments
 (0)