Skip to content

Commit 74e55c7

Browse files
committed
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: tests/fuzz/fuzz-addr.c called common_setup(), which means we called it twice, to hilarious effect. Assert that we don't do that, and don't do that. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
1 parent d3b0313 commit 74e55c7

6 files changed

Lines changed: 61 additions & 7 deletions

File tree

Makefile

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -383,10 +383,7 @@ include cln-grpc/Makefile
383383
endif
384384
include plugins/Makefile
385385
include tests/plugins/Makefile
386-
387-
ifneq ($(FUZZING),0)
388-
include tests/fuzz/Makefile
389-
endif
386+
include tests/fuzz/Makefile
390387

391388
ifneq ($V,1)
392389
MSGGEN_ARGS := -s
@@ -699,9 +696,12 @@ endif
699696

700697
# We special case the fuzzing target binaries, as they need to link against libfuzzer,
701698
# which brings its own main().
699+
ifneq ($(FUZZING),0)
702700
FUZZ_LDFLAGS = -fsanitize=fuzzer
701+
endif
702+
703703
$(ALL_FUZZ_TARGETS):
704-
@$(call VERBOSE, "ld $@", $(LINK.o) $(filter-out %.a,$^) $(LOADLIBES) $(EXTERNAL_LDLIBS) $(LDLIBS) libccan.a $(FUZZ_LDFLAGS) -o $@)
704+
@$(call VERBOSE, "ld $@", $(LINK.o) $(filter-out %.a,$^) libcommon.a libccan.a $(LOADLIBES) $(EXTERNAL_LDLIBS) $(LDLIBS) $(FUZZ_LDFLAGS) -o $@)
705705
ifeq ($(OS),Darwin)
706706
@$(call VERBOSE, "dsymutil $@", dsymutil $@)
707707
endif

common/peer_failed.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "config.h"
44
#include <ccan/compiler/compiler.h>
55
#include <ccan/short_types/short_types.h>
6+
#include <ccan/take/take.h>
67

78
struct channel_id;
89
struct per_peer_state;

common/utils.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "config.h"
2+
#include <assert.h>
23
#include <bitcoin/chainparams.h>
34
#include <ccan/list/list.h>
45
#include <ccan/mem/mem.h>
@@ -99,6 +100,8 @@ void setup_locale(void)
99100
/* Initial creation of tmpctx. */
100101
void setup_tmpctx(void)
101102
{
103+
/* Don't call me twice! */
104+
assert(!tmpctx);
102105
tmpctx = tal_arr_label(NULL, char, 0, "tmpctx");
103106
}
104107

tests/fuzz/Makefile

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,13 @@ FUZZ_TARGETS_SRC := $(wildcard tests/fuzz/fuzz-*.c)
1313
FUZZ_TARGETS_OBJS := $(FUZZ_TARGETS_SRC:.c=.o)
1414
FUZZ_TARGETS_BIN := $(FUZZ_TARGETS_SRC:.c=)
1515

16-
$(FUZZ_TARGETS_OBJS): $(COMMON_HEADERS) $(WIRE_HEADERS) $(COMMON_SRC)
16+
$(FUZZ_TARGETS_OBJS): $(COMMON_HEADERS) $(WIRE_HEADERS) $(COMMON_SRC) tests/fuzz/libfuzz.h
1717
$(FUZZ_TARGETS_BIN): $(LIBFUZZ_OBJS) libcommon.a
1818

1919
ALL_C_SOURCES += $(FUZZ_TARGETS_SRC) $(LIBFUZZ_SRC)
2020
ALL_FUZZ_TARGETS += $(FUZZ_TARGETS_BIN)
21+
22+
# In non-fuzzing builds, these become normal tests.
23+
ifneq ($(FUZZING),1)
24+
check-units: $(FUZZ_TARGETS_BIN:%=unittest/%)
25+
endif

tests/fuzz/fuzz-addr.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99
void init(int *argc, char ***argv)
1010
{
1111
chainparams = chainparams_for_network("bitcoin");
12-
common_setup("fuzzer");
12+
/* Don't call this if we're in unit-test mode, as libfuzz.c does it */
13+
if (!tmpctx)
14+
common_setup("fuzzer");
1315
}
1416

1517
void run(const uint8_t *data, size_t size)

tests/fuzz/libfuzz.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,18 @@
22

33
#include <assert.h>
44
#include <ccan/isaac/isaac64.h>
5+
#include <ccan/short_types/short_types.h>
6+
#include <ccan/tal/grab_file/grab_file.h>
7+
#include <ccan/tal/path/path.h>
8+
#include <ccan/tal/tal.h>
59
#include <common/pseudorand.h>
10+
#include <common/setup.h>
11+
#include <dirent.h>
612
#include <stdlib.h>
713
#include <string.h>
14+
#include <sys/types.h>
815
#include <tests/fuzz/libfuzz.h>
16+
#include <unistd.h>
917

1018
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
1119
int LLVMFuzzerInitialize(int *argc, char ***argv);
@@ -118,3 +126,38 @@ size_t cross_over(const u8 *in1, size_t in1_size, const u8 *in2,
118126
max_out_size);
119127
return overwrite_part(in1, in1_size, in2, in2_size, out, max_out_size);
120128
}
129+
130+
/* In non-fuzzing builds, these become unit tests which just run the corpora:
131+
* this is also good for attaching a debugger to! */
132+
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
133+
int main(int argc, char *argv[])
134+
{
135+
DIR *d;
136+
struct dirent *di;
137+
138+
common_setup(argv[0]);
139+
assert(chdir("tests/fuzz/corpora") == 0);
140+
assert(chdir(path_basename(tmpctx, argv[0])) == 0);
141+
142+
/* FIXME: Support explicit path args? */
143+
init(&argc, &argv);
144+
d = opendir(".");
145+
while ((di = readdir(d)) != NULL) {
146+
u8 *contents;
147+
if (streq(di->d_name, ".") || streq(di->d_name, ".."))
148+
continue;
149+
contents = grab_file(tmpctx, di->d_name);
150+
assert(contents);
151+
run(contents, tal_bytelen(contents)-1);
152+
}
153+
closedir(d);
154+
common_shutdown();
155+
}
156+
157+
/* We never call any functions which might call these */
158+
size_t LLVMFuzzerMutate(uint8_t *data, size_t size, size_t max_size);
159+
size_t LLVMFuzzerMutate(uint8_t *data, size_t size, size_t max_size)
160+
{
161+
abort();
162+
}
163+
#endif /* !FUZZING */

0 commit comments

Comments
 (0)