fuzz: link fuzz programs with `make all` on Linux

Since 5e47215080 (fuzz: add basic fuzz testing target., 2018-10-12), we have compiled object files for the fuzz tests as part of the default 'make all' target. This helps prevent bit-rot in lesser-used parts of the codebase, by making sure that incompatible changes are caught at build time. However, since we never linked the fuzzer executables, this did not protect us from link-time errors. As of 8b9a42bf48 (fuzz: fix fuzz test build rules, 2024-01-19), it's now possible to link the fuzzer executables without using a fuzzing engine and a variety of compiler-specific (and compiler-version-specific) flags, at least on Linux. So let's add a platform-specific option in config.mak.uname to link the executables as part of the default `make all` target. Since linking the fuzzer executables without a fuzzing engine does not require a C++ compiler, we can change the FUZZ_PROGRAMS build rule to use $(CC) by default. This avoids compiler mis-match issues when overriding $(CC) but not $(CXX). When we *do* want to actually link with a fuzzing engine, we can set $(FUZZ_CXX). The build instructions in the CI fuzz-smoke-test job and in the Makefile comment have been updated accordingly. While we're at it, we can consolidate some of the fuzzer build instructions into one location in the Makefile. Suggested-by: Junio C Hamano <gitster@pobox.com> Helped-by: Jeff King <peff@peff.net> Signed-off-by: Josh Steadmon <steadmon@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Josh Steadmon committed Apr 24, 2024 at 11:14 UTC 8427b7e72be088a4ebe12d2603c43c73657377bb
3 files changed +32 -22
Makefile
+30 -21
@@ -409,6 +409,9 @@ include shared.mak
409 # to the "<name>" of the corresponding `compat/fsmonitor/fsm-settings-<name>.c`
410 # that implements the `fsm_os_settings__*()` routines.
411 #
412 +# Define LINK_FUZZ_PROGRAMS if you want `make all` to also build the fuzz test
413 +# programs in oss-fuzz/.
414 +#
415 # === Optional library: libintl ===
416 #
417 # Define NO_GETTEXT if you don't want Git output to be translated.
@@ -752,23 +755,6 @@ SCRIPTS = $(SCRIPT_SH_GEN) \
755
756 ETAGS_TARGET = TAGS
757
755 -# If you add a new fuzzer, please also make sure to run it in
756 -# ci/run-build-and-minimal-fuzzers.sh so that we make sure it still links and
757 -# runs in the future.
758 -FUZZ_OBJS += oss-fuzz/dummy-cmd-main.o
759 -FUZZ_OBJS += oss-fuzz/fuzz-commit-graph.o
760 -FUZZ_OBJS += oss-fuzz/fuzz-config.o
761 -FUZZ_OBJS += oss-fuzz/fuzz-date.o
762 -FUZZ_OBJS += oss-fuzz/fuzz-pack-headers.o
763 -FUZZ_OBJS += oss-fuzz/fuzz-pack-idx.o
764 -.PHONY: fuzz-objs
765 -fuzz-objs: $(FUZZ_OBJS)
766 -
767 -# Always build fuzz objects even if not testing, to prevent bit-rot.
768 -all:: $(FUZZ_OBJS)
769 -
770 -FUZZ_PROGRAMS += $(patsubst %.o,%,$(filter-out %dummy-cmd-main.o,$(FUZZ_OBJS)))
771 -
758 # Empty...
759 EXTRA_PROGRAMS =
760
@@ -2372,6 +2358,29 @@ ifndef NO_TCLTK
2358 endif
2359 $(QUIET_SUBDIR0)templates $(QUIET_SUBDIR1) SHELL_PATH='$(SHELL_PATH_SQ)' PERL_PATH='$(PERL_PATH_SQ)'
2360
2361 +# If you add a new fuzzer, please also make sure to run it in
2362 +# ci/run-build-and-minimal-fuzzers.sh so that we make sure it still links and
2363 +# runs in the future.
2364 +FUZZ_OBJS += oss-fuzz/dummy-cmd-main.o
2365 +FUZZ_OBJS += oss-fuzz/fuzz-commit-graph.o
2366 +FUZZ_OBJS += oss-fuzz/fuzz-config.o
2367 +FUZZ_OBJS += oss-fuzz/fuzz-date.o
2368 +FUZZ_OBJS += oss-fuzz/fuzz-pack-headers.o
2369 +FUZZ_OBJS += oss-fuzz/fuzz-pack-idx.o
2370 +.PHONY: fuzz-objs
2371 +fuzz-objs: $(FUZZ_OBJS)
2372 +
2373 +# Always build fuzz objects even if not testing, to prevent bit-rot.
2374 +all:: $(FUZZ_OBJS)
2375 +
2376 +FUZZ_PROGRAMS += $(patsubst %.o,%,$(filter-out %dummy-cmd-main.o,$(FUZZ_OBJS)))
2377 +
2378 +# Build fuzz programs when possible, even without the necessary fuzzing support,
2379 +# to prevent bit-rot.
2380 +ifdef LINK_FUZZ_PROGRAMS
2381 +all:: $(FUZZ_PROGRAMS)
2382 +endif
2383 +
2384 please_set_SHELL_PATH_to_a_more_modern_shell:
2385 @$$(:)
2386
@@ -3857,22 +3866,22 @@ cover_db_html: cover_db
3866 #
3867 # An example command to build against libFuzzer from LLVM 11.0.0:
3868 #
3860 -# make CC=clang CXX=clang++ \
3869 +# make CC=clang FUZZ_CXX=clang++ \
3870 # CFLAGS="-fsanitize=fuzzer-no-link,address" \
3871 # LIB_FUZZING_ENGINE="-fsanitize=fuzzer,address" \
3872 # fuzz-all
3873 #
3874 +FUZZ_CXX ?= $(CC)
3875 FUZZ_CXXFLAGS ?= $(ALL_CFLAGS)
3876
3877 .PHONY: fuzz-all
3878 +fuzz-all: $(FUZZ_PROGRAMS)
3879
3880 $(FUZZ_PROGRAMS): %: %.o oss-fuzz/dummy-cmd-main.o $(GITLIBS) GIT-LDFLAGS
3870 - $(QUIET_LINK)$(CXX) $(FUZZ_CXXFLAGS) -o $@ $(ALL_LDFLAGS) \
3881 + $(QUIET_LINK)$(FUZZ_CXX) $(FUZZ_CXXFLAGS) -o $@ $(ALL_LDFLAGS) \
3882 -Wl,--allow-multiple-definition \
3883 $(filter %.o,$^) $(filter %.a,$^) $(LIBS) $(LIB_FUZZING_ENGINE)
3884
3874 -fuzz-all: $(FUZZ_PROGRAMS)
3875 -
3885 $(UNIT_TEST_PROGS): $(UNIT_TEST_BIN)/%$X: $(UNIT_TEST_DIR)/%.o $(UNIT_TEST_DIR)/test-lib.o $(GITLIBS) GIT-LDFLAGS
3886 $(call mkdir_p_parent_template)
3887 $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) \
ci/run-build-and-minimal-fuzzers.sh
+1 -1
@@ -7,7 +7,7 @@
7
8 group "Build fuzzers" make \
9 CC=clang \
10 - CXX=clang++ \
10 + FUZZ_CXX=clang++ \
11 CFLAGS="-fsanitize=fuzzer-no-link,address" \
12 LIB_FUZZING_ENGINE="-fsanitize=fuzzer,address" \
13 fuzz-all
config.mak.uname
+1
@@ -68,6 +68,7 @@ ifeq ($(uname_S),Linux)
68 ifneq ($(findstring .el7.,$(uname_R)),)
69 BASIC_CFLAGS += -std=c99
70 endif
71 + LINK_FUZZ_PROGRAMS = YesPlease
72 endif
73 ifeq ($(uname_S),GNU/kFreeBSD)
74 HAVE_ALLOCA_H = YesPlease