diff options
author | Ivan Nardi <12729895+IvanNardi@users.noreply.github.com> | 2022-12-06 17:41:58 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-12-06 17:41:58 +0100 |
commit | ada4fe4aa8f88300cfc0dbe6ee965975274b1c40 (patch) | |
tree | 08010d2055d0159330ded8e5c15113deb0c41c3b /fuzz | |
parent | 946c3dba0f6c393c2e41b98103cec3e7308fbf2c (diff) |
fuzz: add a new fuzzer testing memory allocation failures (#1818)
Try to fuzz error paths triggered by allocation errors.
Fix some errors already found by this new fuzzer.
Basic idea taken from: https://github.com/harfbuzz/harfbuzz/pull/2566/files
`FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION` is a standard define used to
(not)compile specific code in fuzzing builds.
See: https://llvm.org/docs/LibFuzzer.html
Diffstat (limited to 'fuzz')
-rw-r--r-- | fuzz/Makefile.am | 22 | ||||
-rw-r--r-- | fuzz/fuzz_ndpi_reader.c | 33 |
2 files changed, 53 insertions, 2 deletions
diff --git a/fuzz/Makefile.am b/fuzz/Makefile.am index d739fb00a..7f4f2de99 100644 --- a/fuzz/Makefile.am +++ b/fuzz/Makefile.am @@ -1,4 +1,4 @@ -bin_PROGRAMS = fuzz_process_packet fuzz_ndpi_reader fuzz_quic_get_crypto_data +bin_PROGRAMS = fuzz_process_packet fuzz_ndpi_reader fuzz_ndpi_reader_alloc_fail fuzz_quic_get_crypto_data fuzz_process_packet_SOURCES = fuzz_process_packet.c fuzz_process_packet_CFLAGS = @NDPI_CFLAGS@ $(CXXFLAGS) @@ -26,6 +26,19 @@ fuzz_ndpi_reader_LINK=$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXX) @NDPI_CFLAGS@ $(AM_CXXFLAGS) $(CXXFLAGS) \ $(fuzz_ndpi_reader_LDFLAGS) @NDPI_LDFLAGS@ $(LDFLAGS) -o $@ +fuzz_ndpi_reader_alloc_fail_SOURCES = fuzz_ndpi_reader.c ../example/reader_util.c +fuzz_ndpi_reader_alloc_fail_CFLAGS = -I../example/ @NDPI_CFLAGS@ $(CXXFLAGS) -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -DENABLE_MEM_ALLOC_FAILURES +fuzz_ndpi_reader_alloc_fail_LDADD = ../src/lib/libndpi.a +fuzz_ndpi_reader_alloc_fail_LDFLAGS = $(PCAP_LIB) $(ADDITIONAL_LIBS) $(LIBS) +if HAS_FUZZLDFLAGS +fuzz_ndpi_reader_alloc_fail_CFLAGS += $(LIB_FUZZING_ENGINE) +fuzz_ndpi_reader_alloc_fail_LDFLAGS += $(LIB_FUZZING_ENGINE) +endif +# force usage of CXX for linker +fuzz_ndpi_reader_alloc_fail_LINK=$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXX) @NDPI_CFLAGS@ $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(fuzz_ndpi_reader_alloc_fail_LDFLAGS) @NDPI_LDFLAGS@ $(LDFLAGS) -o $@ + fuzz_quic_get_crypto_data_SOURCES = fuzz_quic_get_crypto_data.c fuzz_quic_get_crypto_data_CFLAGS = @NDPI_CFLAGS@ $(CXXFLAGS) fuzz_quic_get_crypto_data_LDADD = ../src/lib/libndpi.a @@ -46,15 +59,20 @@ testpcaps := $(wildcard ../tests/pcap/*.pcap*) fuzz_ndpi_reader_seed_corpus.zip: $(testpcaps) zip -r fuzz_ndpi_reader_seed_corpus.zip $(testpcaps) +fuzz_ndpi_reader_alloc_fail_seed_corpus.zip: $(testpcaps) + zip -r fuzz_ndpi_reader_alloc_fail_seed_corpus.zip $(testpcaps) + files_corpus_fuzz_quic_get_crypto_data := $(wildcard corpus/fuzz_quic_get_crypto_data/*) fuzz_quic_get_crypto_data_seed_corpus.zip: $(files_corpus_fuzz_quic_get_crypto_data) zip -r fuzz_quic_get_crypto_data_seed_corpus.zip $(files_corpus_fuzz_quic_get_crypto_data) -corpus: fuzz_quic_get_crypto_data_seed_corpus.zip +corpus: fuzz_ndpi_reader_seed_corpus.zip fuzz_ndpi_reader_alloc_fail_seed_corpus.zip fuzz_quic_get_crypto_data_seed_corpus.zip distdir: find . -type d | xargs -I'{}' mkdir -p '$(distdir)/{}' find . -type f -name '*.c' \ -o -name '*.am' \ -o -name '*.bin' | xargs -I'{}' cp '{}' '$(distdir)/{}' + +all: corpus diff --git a/fuzz/fuzz_ndpi_reader.c b/fuzz/fuzz_ndpi_reader.c index 1adba5939..76f2d7263 100644 --- a/fuzz/fuzz_ndpi_reader.c +++ b/fuzz/fuzz_ndpi_reader.c @@ -23,6 +23,26 @@ int malloc_size_stats = 0; int max_malloc_bins = 0; struct ndpi_bin malloc_bins; /* unused */ +#ifdef ENABLE_MEM_ALLOC_FAILURES + +static int mem_alloc_state = 0; + +static int fastrand () +{ + if(!mem_alloc_state) return 1; /* No failures */ + mem_alloc_state = (214013 * mem_alloc_state + 2531011); + return (mem_alloc_state >> 16) & 0x7FFF; +} + +static void *malloc_wrapper(size_t size) { + return (fastrand () % 16) ? malloc (size) : NULL; +} +static void free_wrapper(void *freeable) { + free(freeable); +} + +#endif + FILE *bufferToFile(const uint8_t *Data, size_t Size) { FILE *fd; fd = tmpfile(); @@ -71,8 +91,17 @@ int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { memset(workflow->stats.protocol_flows, 0, sizeof(workflow->stats.protocol_flows)); ndpi_finalize_initialization(workflow->ndpi_struct); +#ifdef ENABLE_MEM_ALLOC_FAILURES + set_ndpi_malloc(malloc_wrapper); + set_ndpi_free(free_wrapper); + /* Don't fail memory allocations until init phase is done */ +#endif } +#ifdef ENABLE_MEM_ALLOC_FAILURES + mem_alloc_state = Size; +#endif + fd = bufferToFile(Data, Size); if (fd == NULL) return 0; @@ -92,6 +121,10 @@ int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { workflow->pcap_handle = pkts; /* Init flow tree */ workflow->ndpi_flows_root = ndpi_calloc(workflow->prefs.num_roots, sizeof(void *)); + if(!workflow->ndpi_flows_root) { + pcap_close(pkts); + return 0; + } header = NULL; r = pcap_next_ex(pkts, &header, &pkt); |