Makefile: run fuzzing corpora as normal unit tests in non-fuzzing mode.
This means we can make sure the compile and run in normal builds. Side note: various tests call common_setup(), which means we called it twice in unit testing mode, so we conditionalize those. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
13
Makefile
13
Makefile
@@ -392,10 +392,7 @@ include cln-grpc/Makefile
|
||||
endif
|
||||
include plugins/Makefile
|
||||
include tests/plugins/Makefile
|
||||
|
||||
ifneq ($(FUZZING),0)
|
||||
include tests/fuzz/Makefile
|
||||
endif
|
||||
include tests/fuzz/Makefile
|
||||
|
||||
ifneq ($V,1)
|
||||
MSGGEN_ARGS := -s
|
||||
@@ -709,6 +706,7 @@ endif
|
||||
# We special case the fuzzing target binaries, as they need to link against libfuzzer,
|
||||
# which brings its own main().
|
||||
# FUZZER_LIB and LLVM_LDFLAGS are set by configure script on macOS
|
||||
ifneq ($(FUZZING),0)
|
||||
ifeq ($(OS),Darwin)
|
||||
ifneq ($(FUZZER_LIB),)
|
||||
FUZZ_LDFLAGS = $(FUZZER_LIB) $(LLVM_LDFLAGS)
|
||||
@@ -718,9 +716,10 @@ endif
|
||||
else
|
||||
FUZZ_LDFLAGS = -fsanitize=fuzzer
|
||||
endif
|
||||
endif
|
||||
|
||||
$(ALL_FUZZ_TARGETS):
|
||||
@$(call VERBOSE, "ld $@", $(LINK.o) $(filter-out %.a,$^) $(LOADLIBES) $(EXTERNAL_LDLIBS) $(LDLIBS) libccan.a $(FUZZ_LDFLAGS) -o $@)
|
||||
@$(call VERBOSE, "ld $@", $(LINK.o) $(filter-out %.a,$^) libcommon.a libccan.a $(LOADLIBES) $(EXTERNAL_LDLIBS) $(LDLIBS) $(FUZZ_LDFLAGS) -o $@)
|
||||
ifeq ($(OS),Darwin)
|
||||
@$(call VERBOSE, "dsymutil $@", dsymutil $@)
|
||||
endif
|
||||
@@ -841,6 +840,10 @@ update-mocks/%: % $(ALL_GEN_HEADERS) $(ALL_GEN_SOURCES)
|
||||
unittest/%: % bolt-precheck
|
||||
BOLTDIR=$(LOCAL_BOLTDIR) $(VG) $(VG_TEST_ARGS) $* > /dev/null
|
||||
|
||||
# FIXME: we don't do leak detection on fuzz tests, since they don't have a cleanup function.
|
||||
fuzzunittest/%: % bolt-precheck
|
||||
BOLTDIR=$(LOCAL_BOLTDIR) $(VG) $* > /dev/null
|
||||
|
||||
# Commands
|
||||
MKDIR_P = mkdir -p
|
||||
INSTALL = install
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "config.h"
|
||||
#include <ccan/compiler/compiler.h>
|
||||
#include <ccan/short_types/short_types.h>
|
||||
#include <ccan/take/take.h>
|
||||
|
||||
struct channel_id;
|
||||
struct per_peer_state;
|
||||
|
||||
@@ -13,8 +13,13 @@ FUZZ_TARGETS_SRC := $(wildcard tests/fuzz/fuzz-*.c)
|
||||
FUZZ_TARGETS_OBJS := $(FUZZ_TARGETS_SRC:.c=.o)
|
||||
FUZZ_TARGETS_BIN := $(FUZZ_TARGETS_SRC:.c=)
|
||||
|
||||
$(FUZZ_TARGETS_OBJS): $(COMMON_HEADERS) $(WIRE_HEADERS) $(COMMON_SRC)
|
||||
$(FUZZ_TARGETS_OBJS): $(COMMON_HEADERS) $(WIRE_HEADERS) $(COMMON_SRC) tests/fuzz/libfuzz.h
|
||||
$(FUZZ_TARGETS_BIN): $(LIBFUZZ_OBJS) libcommon.a
|
||||
|
||||
ALL_C_SOURCES += $(FUZZ_TARGETS_SRC) $(LIBFUZZ_SRC)
|
||||
ALL_FUZZ_TARGETS += $(FUZZ_TARGETS_BIN)
|
||||
|
||||
# In non-fuzzing builds, these become normal tests.
|
||||
ifneq ($(FUZZING),1)
|
||||
check-units: $(FUZZ_TARGETS_BIN:%=fuzzunittest/%)
|
||||
endif
|
||||
|
||||
@@ -144,6 +144,11 @@ size_t LLVMFuzzerCustomCrossOver(const u8 *data1, size_t size1, const u8 *data2,
|
||||
return encoded_size;
|
||||
}
|
||||
|
||||
void init(int *argc, char ***argv) { common_setup("fuzzer"); }
|
||||
void init(int *argc, char ***argv)
|
||||
{
|
||||
/* Don't call this if we're in unit-test mode, as libfuzz.c does it */
|
||||
if (!tmpctx)
|
||||
common_setup("fuzzer");
|
||||
}
|
||||
|
||||
#endif /* LIGHTNING_TESTS_FUZZ_BOLT12_H */
|
||||
|
||||
@@ -74,7 +74,9 @@ void init(int *argc, char ***argv)
|
||||
assert(devnull >= 0);
|
||||
status_setup_sync(devnull);
|
||||
|
||||
common_setup("fuzzer");
|
||||
/* Don't call this if we're in unit-test mode, as libfuzz.c does it */
|
||||
if (!tmpctx)
|
||||
common_setup("fuzzer");
|
||||
|
||||
/* These keys are copied from BOLT 8 test vectors, though we use them in
|
||||
* a different setting.
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
void init(int *argc, char ***argv)
|
||||
{
|
||||
chainparams = chainparams_for_network("bitcoin");
|
||||
common_setup("fuzzer");
|
||||
/* Don't call this if we're in unit-test mode, as libfuzz.c does it */
|
||||
if (!tmpctx)
|
||||
common_setup("fuzzer");
|
||||
}
|
||||
|
||||
void run(const uint8_t *data, size_t size)
|
||||
|
||||
@@ -18,7 +18,12 @@ size_t LLVMFuzzerCustomCrossOver(const u8 *in1, size_t in1_size, const u8 *in2,
|
||||
size_t in2_size, u8 *out, size_t max_out_size,
|
||||
unsigned seed);
|
||||
|
||||
void init(int *argc, char ***argv) { common_setup("fuzzer"); }
|
||||
void init(int *argc, char ***argv)
|
||||
{
|
||||
/* Don't call this if we're in unit-test mode, as libfuzz.c does it */
|
||||
if (!tmpctx)
|
||||
common_setup("fuzzer");
|
||||
}
|
||||
|
||||
// Encodes a dummy bolt11 invoice into `fuzz_data` and returns the size of the
|
||||
// encoded string.
|
||||
|
||||
@@ -8,7 +8,12 @@
|
||||
/* Include bolt12.c directly, to gain access to string_to_data(). */
|
||||
#include "../../common/bolt12.c"
|
||||
|
||||
void init(int *argc, char ***argv) { common_setup("fuzzer"); }
|
||||
void init(int *argc, char ***argv)
|
||||
{
|
||||
/* Don't call this if we're in unit-test mode, as libfuzz.c does it */
|
||||
if (!tmpctx)
|
||||
common_setup("fuzzer");
|
||||
}
|
||||
|
||||
void run(const u8 *data, size_t size)
|
||||
{
|
||||
|
||||
@@ -10,7 +10,9 @@
|
||||
|
||||
void init(int *argc, char ***argv)
|
||||
{
|
||||
common_setup("fuzzer");
|
||||
/* Don't call this if we're in unit-test mode, as libfuzz.c does it */
|
||||
if (!tmpctx)
|
||||
common_setup("fuzzer");
|
||||
}
|
||||
|
||||
void run(const uint8_t *data, size_t size)
|
||||
|
||||
@@ -12,7 +12,9 @@
|
||||
|
||||
void init(int *argc, char ***argv)
|
||||
{
|
||||
common_setup("fuzzer");
|
||||
/* Don't call this if we're in unit-test mode, as libfuzz.c does it */
|
||||
if (!tmpctx)
|
||||
common_setup("fuzzer");
|
||||
chainparams = chainparams_for_network("bitcoin");
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,9 @@ static struct codex32 *codex32_dup(const tal_t *ctx, const struct codex32 *src)
|
||||
|
||||
void init(int *argc, char ***argv)
|
||||
{
|
||||
common_setup("fuzzer");
|
||||
/* Don't call this if we're in unit-test mode, as libfuzz.c does it */
|
||||
if (!tmpctx)
|
||||
common_setup("fuzzer");
|
||||
}
|
||||
|
||||
/* Custom mutator with structure-aware and byte-level mutations */
|
||||
|
||||
@@ -54,7 +54,9 @@ void init(int *argc, char ***argv)
|
||||
init_cs_in.s_ck = ck;
|
||||
init_cs_in.r_ck = ck;
|
||||
|
||||
common_setup("fuzzer");
|
||||
/* Don't call this if we're in unit-test mode, as libfuzz.c does it */
|
||||
if (!tmpctx)
|
||||
common_setup("fuzzer");
|
||||
}
|
||||
|
||||
/* Test that encrypting and decrypting the message does not alter it. */
|
||||
|
||||
@@ -23,7 +23,9 @@
|
||||
|
||||
void init(int *argc, char ***argv)
|
||||
{
|
||||
common_setup("fuzzer");
|
||||
/* Don't call this if we're in unit-test mode, as libfuzz.c does it */
|
||||
if (!tmpctx)
|
||||
common_setup("fuzzer");
|
||||
int devnull = open("/dev/null", O_WRONLY);
|
||||
status_setup_sync(devnull);
|
||||
chainparams = chainparams_for_network("bitcoin");
|
||||
|
||||
@@ -2,10 +2,18 @@
|
||||
|
||||
#include <assert.h>
|
||||
#include <ccan/isaac/isaac64.h>
|
||||
#include <ccan/short_types/short_types.h>
|
||||
#include <ccan/tal/grab_file/grab_file.h>
|
||||
#include <ccan/tal/path/path.h>
|
||||
#include <ccan/tal/tal.h>
|
||||
#include <common/pseudorand.h>
|
||||
#include <common/setup.h>
|
||||
#include <dirent.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <tests/fuzz/libfuzz.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
|
||||
int LLVMFuzzerInitialize(int *argc, char ***argv);
|
||||
@@ -118,3 +126,38 @@ size_t cross_over(const u8 *in1, size_t in1_size, const u8 *in2,
|
||||
max_out_size);
|
||||
return overwrite_part(in1, in1_size, in2, in2_size, out, max_out_size);
|
||||
}
|
||||
|
||||
/* In non-fuzzing builds, these become unit tests which just run the corpora:
|
||||
* this is also good for attaching a debugger to! */
|
||||
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
DIR *d;
|
||||
struct dirent *di;
|
||||
|
||||
common_setup(argv[0]);
|
||||
assert(chdir("tests/fuzz/corpora") == 0);
|
||||
assert(chdir(path_basename(tmpctx, argv[0])) == 0);
|
||||
|
||||
/* FIXME: Support explicit path args? */
|
||||
init(&argc, &argv);
|
||||
d = opendir(".");
|
||||
while ((di = readdir(d)) != NULL) {
|
||||
u8 *contents;
|
||||
if (streq(di->d_name, ".") || streq(di->d_name, ".."))
|
||||
continue;
|
||||
contents = grab_file(tmpctx, di->d_name);
|
||||
assert(contents);
|
||||
run(contents, tal_bytelen(contents)-1);
|
||||
}
|
||||
closedir(d);
|
||||
common_shutdown();
|
||||
}
|
||||
|
||||
/* We never call any functions which might call these */
|
||||
size_t LLVMFuzzerMutate(uint8_t *data, size_t size, size_t max_size);
|
||||
size_t LLVMFuzzerMutate(uint8_t *data, size_t size, size_t max_size)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
#endif /* !FUZZING */
|
||||
|
||||
@@ -21,7 +21,13 @@ static u8 *prefix_arr(const u8 *data, size_t size, u16 prefix)
|
||||
}
|
||||
|
||||
/* The init function used by all fuzz-wire-* targets. */
|
||||
void init(int *argc, char ***argv) { common_setup("fuzzer"); dev_towire_allow_invalid_node_id = true; }
|
||||
void init(int *argc, char ***argv)
|
||||
{
|
||||
/* Don't call this if we're in unit-test mode, as libfuzz.c does it */
|
||||
if (!tmpctx)
|
||||
common_setup("fuzzer");
|
||||
dev_towire_allow_invalid_node_id = true;
|
||||
}
|
||||
|
||||
/* Test that decoding arbitrary data does not crash. Then, if the data was
|
||||
* successfully decoded, test that encoding and decoding the message does not
|
||||
|
||||
Reference in New Issue
Block a user