-fsanitize=fuzzer-no-link makes it workable to build a library with fuzzing enabled, and let the fuzzing test program explicitly trigger the fuzzing. This allows fuzzing to trace cmp instructions to guide the fuzzing to improve results.master
| include: | include: | ||||
| - arch: x86-32 | - arch: x86-32 | ||||
| archdeps: "gcc-multilib g++-multilib libpcaudio-dev:i386 libsonic-dev:i386 libc6-dbg:i386" | archdeps: "gcc-multilib g++-multilib libpcaudio-dev:i386 libsonic-dev:i386 libc6-dbg:i386" | ||||
| archconfig: "--host=i686-linux-gnu" | |||||
| archconfigflags: "-m32" | archconfigflags: "-m32" | ||||
| - arch: x86-64 | - arch: x86-64 | ||||
| - name: autoconf | - name: autoconf | ||||
| run: ./autogen.sh ; chmod -x INSTALL m4/*.m4 | run: ./autogen.sh ; chmod -x INSTALL m4/*.m4 | ||||
| - name: configure | - name: configure | ||||
| run: CC=clang CXX=clang++ | |||||
| CFLAGS="${{ matrix.archconfigflags }} -fsanitize=address,undefined -fstack-protector-strong -g -Og -fno-omit-frame-pointer" | |||||
| run: CC="clang ${{ matrix.archconfigflags }}" CXX="clang++ ${{ matrix.archconfigflags }}" | |||||
| CFLAGS="-fsanitize=address,undefined -fstack-protector-strong -g -Og -fno-omit-frame-pointer" | |||||
| CXXFLAGS="${{ matrix.archconfigflags }} -fsanitize=address,undefined -fstack-protector-strong -g -Og -fno-omit-frame-pointer" | CXXFLAGS="${{ matrix.archconfigflags }} -fsanitize=address,undefined -fstack-protector-strong -g -Og -fno-omit-frame-pointer" | ||||
| LDFLAGS="-fsanitize=address,undefined -lubsan" | LDFLAGS="-fsanitize=address,undefined -lubsan" | ||||
| ./configure --with-libfuzzer | |||||
| ./configure ${{ matrix.archconfig }} --with-libfuzzer | |||||
| - name: Store the fuzzer config | - name: Store the fuzzer config | ||||
| if: ${{ failure() }} | if: ${{ failure() }} | ||||
| uses: actions/upload-artifact@v3 | uses: actions/upload-artifact@v3 |
| endif | endif | ||||
| src_speak_ng_LDADD = src/libespeak-ng.la | src_speak_ng_LDADD = src/libespeak-ng.la | ||||
| src_speak_ng_LDFLAGS = -static -lm ${PCAUDIOLIB_LIBS} | |||||
| src_speak_ng_LDFLAGS = -static -lm ${PCAUDIOLIB_LIBS} ${LIBFUZZER_NO_MAIN} | |||||
| src_speak_ng_CFLAGS = -Isrc/libespeak-ng ${AM_CFLAGS} | src_speak_ng_CFLAGS = -Isrc/libespeak-ng ${AM_CFLAGS} | ||||
| bin_PROGRAMS += src/espeak-ng | bin_PROGRAMS += src/espeak-ng | ||||
| man1_MANS += src/espeak-ng.1 | man1_MANS += src/espeak-ng.1 | ||||
| endif | endif | ||||
| src_espeak_ng_LDADD = src/libespeak-ng.la ${PCAUDIOLIB_LIBS} | |||||
| src_espeak_ng_LDADD = src/libespeak-ng.la ${PCAUDIOLIB_LIBS} ${LIBFUZZER_NO_MAIN} | |||||
| src_espeak_ng_SOURCES = src/espeak-ng.c | src_espeak_ng_SOURCES = src/espeak-ng.c | ||||
| if HAVE_LIBFUZZER | if HAVE_LIBFUZZER | ||||
| nodist_EXTRA_src_espeak_ng_SOURCES = force-cxx-linking.cxx | nodist_EXTRA_src_espeak_ng_SOURCES = force-cxx-linking.cxx | ||||
| if HAVE_LIBFUZZER | if HAVE_LIBFUZZER | ||||
| tests_ssml_fuzzer_test_CFLAGS += -fsanitize=fuzzer | |||||
| tests_ssml_fuzzer_test_LDFLAGS = -fsanitize=fuzzer | |||||
| noinst_PROGRAMS = tests/fuzzing/synth_fuzzer.test | noinst_PROGRAMS = tests/fuzzing/synth_fuzzer.test | ||||
| tests_fuzzing_synth_fuzzer_test_SOURCES = tests/fuzzing/synth_fuzzer.c | tests_fuzzing_synth_fuzzer_test_SOURCES = tests/fuzzing/synth_fuzzer.c | ||||
| tests_fuzzing_synth_fuzzer_test_LDADD = src/libespeak-ng.la | tests_fuzzing_synth_fuzzer_test_LDADD = src/libespeak-ng.la | ||||
| tests_fuzzing_synth_fuzzer_test_CFLAGS= ${AM_CFLAGS} -fsanitize=fuzzer -DPATH_ESPEAK_DATA=\"$(abs_top_srcdir)/espeak-ng-data\" -Isrc/libespeak-ng | |||||
| tests_fuzzing_synth_fuzzer_test_LDFLAGS= ${AM_LDFLAGS} -fsanitize=fuzzer -static -lm -Wl,-z,relro ${PCAUDIOLIB_LIBS} | |||||
| tests_fuzzing_synth_fuzzer_test_CFLAGS= ${AM_CFLAGS} -DPATH_ESPEAK_DATA=\"$(abs_top_srcdir)/espeak-ng-data\" -Isrc/libespeak-ng | |||||
| tests_fuzzing_synth_fuzzer_test_LDFLAGS= ${AM_LDFLAGS} -static -lm -Wl,-z,relro ${PCAUDIOLIB_LIBS} ${LIBFUZZER_NO_MAIN} | |||||
| else | else | ||||
| tests_ssml_fuzzer_test_LDADD += tests/libfuzzrunner.la | tests_ssml_fuzzer_test_LDADD += tests/libfuzzrunner.la | ||||
| endif | endif |
| fi | fi | ||||
| AC_LANG_PUSH(C) | |||||
| TEMP_CFLAGS="$CFLAGS" | |||||
| CFLAGS="$CFLAGS -fsanitize=fuzzer" | |||||
| AC_MSG_CHECKING([if $CC supports fuzzer with the -fsanitize=fuzzer flag]) | |||||
| AC_COMPILE_IFELSE( | |||||
| [AC_LANG_PROGRAM( [[]], [[]])], | |||||
| [have_fuzzer_fuzzer=yes], | |||||
| [have_fuzzer_fuzzer=no]) | |||||
| AC_MSG_RESULT($have_fuzzer_fuzzer) | |||||
| CFLAGS="$TEMP_CFLAGS" | |||||
| AC_LANG_POP(C) | |||||
| if test "$with_libfuzzer" = yes ; then | |||||
| AC_LANG_PUSH(C) | |||||
| TEMP_CFLAGS="$CFLAGS" | |||||
| TEMP_LIBS="$LIBS" | |||||
| HOST_CPU="`$CC -print-multiarch | sed -e 's/-.*//'`" | |||||
| LIBFUZZER_NO_MAIN="`$CC -print-runtime-dir`/libclang_rt.fuzzer_no_main-$HOST_CPU.a -lstdc++ -lm" | |||||
| CFLAGS="$CFLAGS -fsanitize=fuzzer-no-link" | |||||
| LIBS="$LIBS $LIBFUZZER_NO_MAIN" | |||||
| AC_MSG_CHECKING([if $CC supports fuzzer with the -fsanitize=fuzzer flag]) | |||||
| AC_COMPILE_IFELSE( | |||||
| [AC_LANG_PROGRAM( [[]], [[]])], | |||||
| [have_fuzzer_fuzzer=yes], | |||||
| [have_fuzzer_fuzzer=no]) | |||||
| AC_MSG_RESULT($have_fuzzer_fuzzer) | |||||
| if test "$have_fuzzer_fuzzer" != yes ; then | |||||
| CFLAGS="$TEMP_CFLAGS" | |||||
| LIBFUZZER_NO_MAIN="" | |||||
| fi | |||||
| AC_SUBST(LIBFUZZER_NO_MAIN) | |||||
| LIBS="$TEMP_LIBS" | |||||
| AC_LANG_POP(C) | |||||
| fi | |||||
| dnl ================================================================ | dnl ================================================================ | ||||
| dnl FreeBSD check. | dnl FreeBSD check. |
| } | } | ||||
| /* See http://llvm.org/docs/LibFuzzer.html */ | /* See http://llvm.org/docs/LibFuzzer.html */ | ||||
| extern int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); | |||||
| extern int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) | |||||
| extern int LLVMFuzzerRunDriver(int *argc, char ***argv, | |||||
| int (*UserCb)(const uint8_t *Data, size_t Size)); | |||||
| int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) | |||||
| { | { | ||||
| int buflength = size+1; | int buflength = size+1; | ||||
| if (!initialized) | if (!initialized) | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| int main(int argc, char *argv[]) { | |||||
| LLVMFuzzerRunDriver(&argc, &argv, LLVMFuzzerTestOneInput); | |||||
| } |