Merge #15043: test: Build fuzz targets into seperate executables

2ca632e5b4 test: Build fuzz targets into seperate executables (MarcoFalke)
fab4bed68a [test] fuzz: make test_one_input return void (MarcoFalke)

Pull request description:

  Currently our fuzzer is a single binary that decides on the first few bits of the buffer what target to pick. This is ineffective as the fuzzer needs to "learn" how the fuzz targets are organized and could get easily confused. Not to mention that the (seed) corpus can not be categorized by target, since targets might "leak" into each other. Also the corpus would potentially become invalid if we ever wanted to remove a target...

  Solve that by building each fuzz target into their own executable.

Tree-SHA512: a874febc85a3c5e6729199542b65cad10640553fba6f663600c827fe144543744dd0f844fb62b4c95c6a04c670bfce32cdff3d5f26de2dfc25f10b258eda18ab
This commit is contained in:
Wladimir J. van der Laan 2019-01-30 21:09:39 +01:00
commit 9553102c38
No known key found for this signature in database
GPG key ID: 1E4AED62986CD25D
7 changed files with 528 additions and 240 deletions

View file

@ -97,7 +97,7 @@ jobs:
PACKAGES="python3-zmq qtbase5-dev qttools5-dev-tools protobuf-compiler libdbus-1-dev libharfbuzz-dev libprotobuf-dev"
DEP_OPTS="NO_QT=1 NO_UPNP=1 DEBUG=1 ALLOW_HOST_PACKAGES=1"
GOAL="install"
BITCOIN_CONFIG="--enable-zmq --with-gui=qt5 --enable-glibc-back-compat --enable-reduce-exports --enable-debug CXXFLAGS=\"-g0 -O2\""
BITCOIN_CONFIG="--enable-zmq --with-gui=qt5 --enable-fuzz --enable-glibc-back-compat --enable-reduce-exports --enable-debug CXXFLAGS=\"-g0 -O2\""
- stage: test
name: 'x86_64 Linux [GOAL: install] [xenial] [no depends, only system libs, sanitizers: thread (TSan), no wallet]'

View file

@ -102,7 +102,6 @@ AM_CONDITIONAL([HAVE_DOXYGEN], [test -n "$DOXYGEN"])
AC_ARG_VAR(PYTHONPATH, Augments the default search path for python module files)
# Enable wallet
AC_ARG_ENABLE([wallet],
[AS_HELP_STRING([--disable-wallet],
[disable wallet (enabled by default)])],
@ -147,6 +146,11 @@ AC_ARG_ENABLE([extended-functional-tests],
[use_extended_functional_tests=$enableval],
[use_extended_functional_tests=no])
AC_ARG_ENABLE([fuzz],
AS_HELP_STRING([--enable-fuzz],[enable building of fuzz targets (default no)]),
[enable_fuzz=$enableval],
[enable_fuzz=no])
AC_ARG_WITH([qrencode],
[AS_HELP_STRING([--with-qrencode],
[enable QR code support (default is yes if qt is enabled and libqrencode is found)])],
@ -1394,6 +1398,7 @@ AM_CONDITIONAL([BUILD_DARWIN], [test x$BUILD_OS = xdarwin])
AM_CONDITIONAL([TARGET_WINDOWS], [test x$TARGET_OS = xwindows])
AM_CONDITIONAL([ENABLE_WALLET],[test x$enable_wallet = xyes])
AM_CONDITIONAL([ENABLE_TESTS],[test x$BUILD_TEST = xyes])
AM_CONDITIONAL([ENABLE_FUZZ],[test x$enable_fuzz = xyes])
AM_CONDITIONAL([ENABLE_QT],[test x$bitcoin_enable_qt = xyes])
AM_CONDITIONAL([ENABLE_QT_TESTS],[test x$BUILD_TEST_QT = xyes])
AM_CONDITIONAL([ENABLE_BIP70],[test x$enable_bip70 = xyes])
@ -1536,6 +1541,9 @@ if test x$bitcoin_enable_qt != xno; then
fi
echo " with zmq = $use_zmq"
echo " with test = $use_tests"
if test x$use_tests != xno; then
echo " with fuzz = $enable_fuzz"
fi
echo " with bench = $use_bench"
echo " with upnp = $use_upnp"
echo " use asm = $use_asm"

View file

@ -1,9 +1,9 @@
Fuzz-testing Bitcoin Core
==========================
A special test harness `test_bitcoin_fuzzy` is provided to provide an easy
entry point for fuzzers and the like. In this document we'll describe how to
use it with AFL and libFuzzer.
A special test harness in `src/test/fuzz/` is provided for each fuzz target to
provide an easy entry point for fuzzers and the like. In this document we'll
describe how to use it with AFL and libFuzzer.
## AFL
@ -23,10 +23,10 @@ export AFLPATH=$PWD
To build Bitcoin Core using AFL instrumentation (this assumes that the
`AFLPATH` was set as above):
```
./configure --disable-ccache --disable-shared --enable-tests CC=${AFLPATH}/afl-gcc CXX=${AFLPATH}/afl-g++
./configure --disable-ccache --disable-shared --enable-tests --enable-fuzz CC=${AFLPATH}/afl-gcc CXX=${AFLPATH}/afl-g++
export AFL_HARDEN=1
cd src/
make test/test_bitcoin_fuzzy
make
```
We disable ccache because we don't want to pollute the ccache with instrumented
objects, and similarly don't want to use non-instrumented cached objects linked
@ -35,7 +35,7 @@ in.
The fuzzing can be sped up significantly (~200x) by using `afl-clang-fast` and
`afl-clang-fast++` in place of `afl-gcc` and `afl-g++` when compiling. When
compiling using `afl-clang-fast`/`afl-clang-fast++` the resulting
`test_bitcoin_fuzzy` binary will be instrumented in such a way that the AFL
binary will be instrumented in such a way that the AFL
features "persistent mode" and "deferred forkserver" can be used. See
https://github.com/mcarpenter/afl/tree/master/llvm_mode for details.
@ -63,7 +63,7 @@ Extract these (or other starting inputs) into the `inputs` directory before star
To start the actual fuzzing use:
```
$AFLPATH/afl-fuzz -i ${AFLIN} -o ${AFLOUT} -m52 -- test/test_bitcoin_fuzzy
$AFLPATH/afl-fuzz -i ${AFLIN} -o ${AFLOUT} -m52 -- test/fuzz/fuzz_target_foo
```
You may have to change a few kernel parameters to test optimally - `afl-fuzz`
@ -77,7 +77,7 @@ found in the `compiler-rt` runtime libraries package).
To build the `test/test_bitcoin_fuzzy` executable run
```
./configure --disable-ccache --with-sanitizers=fuzzer,address CC=clang CXX=clang++
./configure --disable-ccache --enable-fuzz --with-sanitizers=fuzzer,address CC=clang CXX=clang++
make
```

View file

@ -3,7 +3,33 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
bin_PROGRAMS += test/test_bitcoin
noinst_PROGRAMS += test/test_bitcoin_fuzzy
FUZZ_TARGETS = \
test/fuzz/address_deserialize \
test/fuzz/addrman_deserialize \
test/fuzz/banentry_deserialize \
test/fuzz/block_deserialize \
test/fuzz/blockheader_deserialize \
test/fuzz/blocklocator_deserialize \
test/fuzz/blockmerkleroot \
test/fuzz/blocktransactions_deserialize \
test/fuzz/blocktransactionsrequest_deserialize \
test/fuzz/blockundo_deserialize \
test/fuzz/bloomfilter_deserialize \
test/fuzz/coins_deserialize \
test/fuzz/diskblockindex_deserialize \
test/fuzz/inv_deserialize \
test/fuzz/messageheader_deserialize \
test/fuzz/netaddr_deserialize \
test/fuzz/service_deserialize \
test/fuzz/transaction_deserialize \
test/fuzz/txoutcompressor_deserialize \
test/fuzz/txundo_deserialize
if ENABLE_FUZZ
noinst_PROGRAMS += $(FUZZ_TARGETS:=)
endif
TEST_SRCDIR = test
TEST_BINARY=test/test_bitcoin$(EXEEXT)
@ -27,6 +53,10 @@ BITCOIN_TEST_SUITE = \
test/test_bitcoin.h \
test/test_bitcoin.cpp
FUZZ_SUITE = \
test/fuzz/fuzz.cpp \
test/fuzz/fuzz.h
# test_bitcoin binary #
BITCOIN_TESTS =\
test/arith_uint256_tests.cpp \
@ -138,28 +168,348 @@ test_test_bitcoin_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -s
if ENABLE_ZMQ
test_test_bitcoin_LDADD += $(ZMQ_LIBS)
endif
#
# test_bitcoin_fuzzy binary #
test_test_bitcoin_fuzzy_SOURCES = test/test_bitcoin_fuzzy.cpp
test_test_bitcoin_fuzzy_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_test_bitcoin_fuzzy_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_test_bitcoin_fuzzy_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
if ENABLE_FUZZ
test_fuzz_block_deserialize_SOURCES = $(FUZZ_SUITE) test/test_bitcoin_fuzzy.cpp
test_fuzz_block_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCK_DESERIALIZE=1
test_fuzz_block_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_block_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_fuzz_block_deserialize_LDADD = \
$(LIBUNIVALUE) \
$(LIBBITCOIN_SERVER) \
$(LIBBITCOIN_COMMON) \
$(LIBBITCOIN_UTIL) \
$(LIBBITCOIN_CONSENSUS) \
$(LIBBITCOIN_CRYPTO) \
$(LIBBITCOIN_CRYPTO_SSE41) \
$(LIBBITCOIN_CRYPTO_AVX2) \
$(LIBBITCOIN_CRYPTO_SHANI) \
$(LIBSECP256K1)
test_fuzz_block_deserialize_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS)
test_test_bitcoin_fuzzy_LDADD = \
$(LIBUNIVALUE) \
$(LIBBITCOIN_SERVER) \
$(LIBBITCOIN_COMMON) \
$(LIBBITCOIN_UTIL) \
$(LIBBITCOIN_CONSENSUS) \
$(LIBBITCOIN_CRYPTO) \
$(LIBBITCOIN_CRYPTO_SSE41) \
$(LIBBITCOIN_CRYPTO_AVX2) \
$(LIBBITCOIN_CRYPTO_SHANI) \
$(LIBSECP256K1)
test_fuzz_transaction_deserialize_SOURCES = $(FUZZ_SUITE) test/test_bitcoin_fuzzy.cpp
test_fuzz_transaction_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DTRANSACTION_DESERIALIZE=1
test_fuzz_transaction_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_transaction_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_fuzz_transaction_deserialize_LDADD = \
$(LIBUNIVALUE) \
$(LIBBITCOIN_SERVER) \
$(LIBBITCOIN_COMMON) \
$(LIBBITCOIN_UTIL) \
$(LIBBITCOIN_CONSENSUS) \
$(LIBBITCOIN_CRYPTO) \
$(LIBBITCOIN_CRYPTO_SSE41) \
$(LIBBITCOIN_CRYPTO_AVX2) \
$(LIBBITCOIN_CRYPTO_SHANI) \
$(LIBSECP256K1)
test_fuzz_transaction_deserialize_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS)
test_test_bitcoin_fuzzy_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS)
#
test_fuzz_blocklocator_deserialize_SOURCES = $(FUZZ_SUITE) test/test_bitcoin_fuzzy.cpp
test_fuzz_blocklocator_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCKLOCATOR_DESERIALIZE=1
test_fuzz_blocklocator_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_blocklocator_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_fuzz_blocklocator_deserialize_LDADD = \
$(LIBUNIVALUE) \
$(LIBBITCOIN_SERVER) \
$(LIBBITCOIN_COMMON) \
$(LIBBITCOIN_UTIL) \
$(LIBBITCOIN_CONSENSUS) \
$(LIBBITCOIN_CRYPTO) \
$(LIBBITCOIN_CRYPTO_SSE41) \
$(LIBBITCOIN_CRYPTO_AVX2) \
$(LIBBITCOIN_CRYPTO_SHANI) \
$(LIBSECP256K1)
test_fuzz_blocklocator_deserialize_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS)
test_fuzz_blockmerkleroot_SOURCES = $(FUZZ_SUITE) test/test_bitcoin_fuzzy.cpp
test_fuzz_blockmerkleroot_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCKMERKLEROOT=1
test_fuzz_blockmerkleroot_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_blockmerkleroot_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_fuzz_blockmerkleroot_LDADD = \
$(LIBUNIVALUE) \
$(LIBBITCOIN_SERVER) \
$(LIBBITCOIN_COMMON) \
$(LIBBITCOIN_UTIL) \
$(LIBBITCOIN_CONSENSUS) \
$(LIBBITCOIN_CRYPTO) \
$(LIBBITCOIN_CRYPTO_SSE41) \
$(LIBBITCOIN_CRYPTO_AVX2) \
$(LIBBITCOIN_CRYPTO_SHANI) \
$(LIBSECP256K1)
test_fuzz_blockmerkleroot_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS)
test_fuzz_addrman_deserialize_SOURCES = $(FUZZ_SUITE) test/test_bitcoin_fuzzy.cpp
test_fuzz_addrman_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DADDRMAN_DESERIALIZE=1
test_fuzz_addrman_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_addrman_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_fuzz_addrman_deserialize_LDADD = \
$(LIBUNIVALUE) \
$(LIBBITCOIN_SERVER) \
$(LIBBITCOIN_COMMON) \
$(LIBBITCOIN_UTIL) \
$(LIBBITCOIN_CONSENSUS) \
$(LIBBITCOIN_CRYPTO) \
$(LIBBITCOIN_CRYPTO_SSE41) \
$(LIBBITCOIN_CRYPTO_AVX2) \
$(LIBBITCOIN_CRYPTO_SHANI) \
$(LIBSECP256K1)
test_fuzz_addrman_deserialize_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS)
test_fuzz_blockheader_deserialize_SOURCES = $(FUZZ_SUITE) test/test_bitcoin_fuzzy.cpp
test_fuzz_blockheader_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCKHEADER_DESERIALIZE=1
test_fuzz_blockheader_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_blockheader_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_fuzz_blockheader_deserialize_LDADD = \
$(LIBUNIVALUE) \
$(LIBBITCOIN_SERVER) \
$(LIBBITCOIN_COMMON) \
$(LIBBITCOIN_UTIL) \
$(LIBBITCOIN_CONSENSUS) \
$(LIBBITCOIN_CRYPTO) \
$(LIBBITCOIN_CRYPTO_SSE41) \
$(LIBBITCOIN_CRYPTO_AVX2) \
$(LIBBITCOIN_CRYPTO_SHANI) \
$(LIBSECP256K1)
test_fuzz_blockheader_deserialize_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS)
test_fuzz_banentry_deserialize_SOURCES = $(FUZZ_SUITE) test/test_bitcoin_fuzzy.cpp
test_fuzz_banentry_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBANENTRY_DESERIALIZE=1
test_fuzz_banentry_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_banentry_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_fuzz_banentry_deserialize_LDADD = \
$(LIBUNIVALUE) \
$(LIBBITCOIN_SERVER) \
$(LIBBITCOIN_COMMON) \
$(LIBBITCOIN_UTIL) \
$(LIBBITCOIN_CONSENSUS) \
$(LIBBITCOIN_CRYPTO) \
$(LIBBITCOIN_CRYPTO_SSE41) \
$(LIBBITCOIN_CRYPTO_AVX2) \
$(LIBBITCOIN_CRYPTO_SHANI) \
$(LIBSECP256K1)
test_fuzz_banentry_deserialize_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS)
test_fuzz_txundo_deserialize_SOURCES = $(FUZZ_SUITE) test/test_bitcoin_fuzzy.cpp
test_fuzz_txundo_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DTXUNDO_DESERIALIZE=1
test_fuzz_txundo_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_txundo_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_fuzz_txundo_deserialize_LDADD = \
$(LIBUNIVALUE) \
$(LIBBITCOIN_SERVER) \
$(LIBBITCOIN_COMMON) \
$(LIBBITCOIN_UTIL) \
$(LIBBITCOIN_CONSENSUS) \
$(LIBBITCOIN_CRYPTO) \
$(LIBBITCOIN_CRYPTO_SSE41) \
$(LIBBITCOIN_CRYPTO_AVX2) \
$(LIBBITCOIN_CRYPTO_SHANI) \
$(LIBSECP256K1)
test_fuzz_txundo_deserialize_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS)
test_fuzz_blockundo_deserialize_SOURCES = $(FUZZ_SUITE) test/test_bitcoin_fuzzy.cpp
test_fuzz_blockundo_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCKUNDO_DESERIALIZE=1
test_fuzz_blockundo_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_blockundo_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_fuzz_blockundo_deserialize_LDADD = \
$(LIBUNIVALUE) \
$(LIBBITCOIN_SERVER) \
$(LIBBITCOIN_COMMON) \
$(LIBBITCOIN_UTIL) \
$(LIBBITCOIN_CONSENSUS) \
$(LIBBITCOIN_CRYPTO) \
$(LIBBITCOIN_CRYPTO_SSE41) \
$(LIBBITCOIN_CRYPTO_AVX2) \
$(LIBBITCOIN_CRYPTO_SHANI) \
$(LIBSECP256K1)
test_fuzz_blockundo_deserialize_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS)
test_fuzz_coins_deserialize_SOURCES = $(FUZZ_SUITE) test/test_bitcoin_fuzzy.cpp
test_fuzz_coins_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DCOINS_DESERIALIZE=1
test_fuzz_coins_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_coins_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_fuzz_coins_deserialize_LDADD = \
$(LIBUNIVALUE) \
$(LIBBITCOIN_SERVER) \
$(LIBBITCOIN_COMMON) \
$(LIBBITCOIN_UTIL) \
$(LIBBITCOIN_CONSENSUS) \
$(LIBBITCOIN_CRYPTO) \
$(LIBBITCOIN_CRYPTO_SSE41) \
$(LIBBITCOIN_CRYPTO_AVX2) \
$(LIBBITCOIN_CRYPTO_SHANI) \
$(LIBSECP256K1)
test_fuzz_coins_deserialize_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS)
test_fuzz_netaddr_deserialize_SOURCES = $(FUZZ_SUITE) test/test_bitcoin_fuzzy.cpp
test_fuzz_netaddr_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DNETADDR_DESERIALIZE=1
test_fuzz_netaddr_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_netaddr_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_fuzz_netaddr_deserialize_LDADD = \
$(LIBUNIVALUE) \
$(LIBBITCOIN_SERVER) \
$(LIBBITCOIN_COMMON) \
$(LIBBITCOIN_UTIL) \
$(LIBBITCOIN_CONSENSUS) \
$(LIBBITCOIN_CRYPTO) \
$(LIBBITCOIN_CRYPTO_SSE41) \
$(LIBBITCOIN_CRYPTO_AVX2) \
$(LIBBITCOIN_CRYPTO_SHANI) \
$(LIBSECP256K1)
test_fuzz_netaddr_deserialize_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS)
test_fuzz_service_deserialize_SOURCES = $(FUZZ_SUITE) test/test_bitcoin_fuzzy.cpp
test_fuzz_service_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DSERVICE_DESERIALIZE=1
test_fuzz_service_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_service_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_fuzz_service_deserialize_LDADD = \
$(LIBUNIVALUE) \
$(LIBBITCOIN_SERVER) \
$(LIBBITCOIN_COMMON) \
$(LIBBITCOIN_UTIL) \
$(LIBBITCOIN_CONSENSUS) \
$(LIBBITCOIN_CRYPTO) \
$(LIBBITCOIN_CRYPTO_SSE41) \
$(LIBBITCOIN_CRYPTO_AVX2) \
$(LIBBITCOIN_CRYPTO_SHANI) \
$(LIBSECP256K1)
test_fuzz_service_deserialize_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS)
test_fuzz_messageheader_deserialize_SOURCES = $(FUZZ_SUITE) test/test_bitcoin_fuzzy.cpp
test_fuzz_messageheader_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGEHEADER_DESERIALIZE=1
test_fuzz_messageheader_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_messageheader_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_fuzz_messageheader_deserialize_LDADD = \
$(LIBUNIVALUE) \
$(LIBBITCOIN_SERVER) \
$(LIBBITCOIN_COMMON) \
$(LIBBITCOIN_UTIL) \
$(LIBBITCOIN_CONSENSUS) \
$(LIBBITCOIN_CRYPTO) \
$(LIBBITCOIN_CRYPTO_SSE41) \
$(LIBBITCOIN_CRYPTO_AVX2) \
$(LIBBITCOIN_CRYPTO_SHANI) \
$(LIBSECP256K1)
test_fuzz_messageheader_deserialize_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS)
test_fuzz_address_deserialize_SOURCES = $(FUZZ_SUITE) test/test_bitcoin_fuzzy.cpp
test_fuzz_address_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DADDRESS_DESERIALIZE=1
test_fuzz_address_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_address_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_fuzz_address_deserialize_LDADD = \
$(LIBUNIVALUE) \
$(LIBBITCOIN_SERVER) \
$(LIBBITCOIN_COMMON) \
$(LIBBITCOIN_UTIL) \
$(LIBBITCOIN_CONSENSUS) \
$(LIBBITCOIN_CRYPTO) \
$(LIBBITCOIN_CRYPTO_SSE41) \
$(LIBBITCOIN_CRYPTO_AVX2) \
$(LIBBITCOIN_CRYPTO_SHANI) \
$(LIBSECP256K1)
test_fuzz_address_deserialize_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS)
test_fuzz_inv_deserialize_SOURCES = $(FUZZ_SUITE) test/test_bitcoin_fuzzy.cpp
test_fuzz_inv_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DINV_DESERIALIZE=1
test_fuzz_inv_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_inv_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_fuzz_inv_deserialize_LDADD = \
$(LIBUNIVALUE) \
$(LIBBITCOIN_SERVER) \
$(LIBBITCOIN_COMMON) \
$(LIBBITCOIN_UTIL) \
$(LIBBITCOIN_CONSENSUS) \
$(LIBBITCOIN_CRYPTO) \
$(LIBBITCOIN_CRYPTO_SSE41) \
$(LIBBITCOIN_CRYPTO_AVX2) \
$(LIBBITCOIN_CRYPTO_SHANI) \
$(LIBSECP256K1)
test_fuzz_inv_deserialize_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS)
test_fuzz_bloomfilter_deserialize_SOURCES = $(FUZZ_SUITE) test/test_bitcoin_fuzzy.cpp
test_fuzz_bloomfilter_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOOMFILTER_DESERIALIZE=1
test_fuzz_bloomfilter_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_bloomfilter_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_fuzz_bloomfilter_deserialize_LDADD = \
$(LIBUNIVALUE) \
$(LIBBITCOIN_SERVER) \
$(LIBBITCOIN_COMMON) \
$(LIBBITCOIN_UTIL) \
$(LIBBITCOIN_CONSENSUS) \
$(LIBBITCOIN_CRYPTO) \
$(LIBBITCOIN_CRYPTO_SSE41) \
$(LIBBITCOIN_CRYPTO_AVX2) \
$(LIBBITCOIN_CRYPTO_SHANI) \
$(LIBSECP256K1)
test_fuzz_bloomfilter_deserialize_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS)
test_fuzz_diskblockindex_deserialize_SOURCES = $(FUZZ_SUITE) test/test_bitcoin_fuzzy.cpp
test_fuzz_diskblockindex_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DDISKBLOCKINDEX_DESERIALIZE=1
test_fuzz_diskblockindex_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_diskblockindex_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_fuzz_diskblockindex_deserialize_LDADD = \
$(LIBUNIVALUE) \
$(LIBBITCOIN_SERVER) \
$(LIBBITCOIN_COMMON) \
$(LIBBITCOIN_UTIL) \
$(LIBBITCOIN_CONSENSUS) \
$(LIBBITCOIN_CRYPTO) \
$(LIBBITCOIN_CRYPTO_SSE41) \
$(LIBBITCOIN_CRYPTO_AVX2) \
$(LIBBITCOIN_CRYPTO_SHANI) \
$(LIBSECP256K1)
test_fuzz_diskblockindex_deserialize_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS)
test_fuzz_txoutcompressor_deserialize_SOURCES = $(FUZZ_SUITE) test/test_bitcoin_fuzzy.cpp
test_fuzz_txoutcompressor_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DTXOUTCOMPRESSOR_DESERIALIZE=1
test_fuzz_txoutcompressor_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_txoutcompressor_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_fuzz_txoutcompressor_deserialize_LDADD = \
$(LIBUNIVALUE) \
$(LIBBITCOIN_SERVER) \
$(LIBBITCOIN_COMMON) \
$(LIBBITCOIN_UTIL) \
$(LIBBITCOIN_CONSENSUS) \
$(LIBBITCOIN_CRYPTO) \
$(LIBBITCOIN_CRYPTO_SSE41) \
$(LIBBITCOIN_CRYPTO_AVX2) \
$(LIBBITCOIN_CRYPTO_SHANI) \
$(LIBSECP256K1)
test_fuzz_txoutcompressor_deserialize_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS)
test_fuzz_blocktransactions_deserialize_SOURCES = $(FUZZ_SUITE) test/test_bitcoin_fuzzy.cpp
test_fuzz_blocktransactions_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCKTRANSACTIONS_DESERIALIZE=1
test_fuzz_blocktransactions_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_blocktransactions_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_fuzz_blocktransactions_deserialize_LDADD = \
$(LIBUNIVALUE) \
$(LIBBITCOIN_SERVER) \
$(LIBBITCOIN_COMMON) \
$(LIBBITCOIN_UTIL) \
$(LIBBITCOIN_CONSENSUS) \
$(LIBBITCOIN_CRYPTO) \
$(LIBBITCOIN_CRYPTO_SSE41) \
$(LIBBITCOIN_CRYPTO_AVX2) \
$(LIBBITCOIN_CRYPTO_SHANI) \
$(LIBSECP256K1)
test_fuzz_blocktransactions_deserialize_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS)
test_fuzz_blocktransactionsrequest_deserialize_SOURCES = $(FUZZ_SUITE) test/test_bitcoin_fuzzy.cpp
test_fuzz_blocktransactionsrequest_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCKTRANSACTIONSREQUEST_DESERIALIZE=1
test_fuzz_blocktransactionsrequest_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_blocktransactionsrequest_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_fuzz_blocktransactionsrequest_deserialize_LDADD = \
$(LIBUNIVALUE) \
$(LIBBITCOIN_SERVER) \
$(LIBBITCOIN_COMMON) \
$(LIBBITCOIN_UTIL) \
$(LIBBITCOIN_CONSENSUS) \
$(LIBBITCOIN_CRYPTO) \
$(LIBBITCOIN_CRYPTO_SSE41) \
$(LIBBITCOIN_CRYPTO_AVX2) \
$(LIBBITCOIN_CRYPTO_SHANI) \
$(LIBSECP256K1)
test_fuzz_blocktransactionsrequest_deserialize_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS)
endif # ENABLE_FUZZ
nodist_test_test_bitcoin_SOURCES = $(GENERATED_TEST_FILES)

77
src/test/fuzz/fuzz.cpp Normal file
View file

@ -0,0 +1,77 @@
// Copyright (c) 2009-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <test/fuzz/fuzz.h>
#include <unistd.h>
#include <pubkey.h>
#include <util/memory.h>
static bool read_stdin(std::vector<uint8_t>& data)
{
uint8_t buffer[1024];
ssize_t length = 0;
while ((length = read(STDIN_FILENO, buffer, 1024)) > 0) {
data.insert(data.end(), buffer, buffer + length);
if (data.size() > (1 << 20)) return false;
}
return length == 0;
}
static void initialize()
{
const static auto verify_handle = MakeUnique<ECCVerifyHandle>();
}
// This function is used by libFuzzer
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
{
test_one_input(std::vector<uint8_t>(data, data + size));
return 0;
}
// This function is used by libFuzzer
extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv)
{
initialize();
return 0;
}
// Disabled under WIN32 due to clash with Cygwin's WinMain.
#ifndef WIN32
// Declare main(...) "weak" to allow for libFuzzer linking. libFuzzer provides
// the main(...) function.
__attribute__((weak))
#endif
int main(int argc, char **argv)
{
initialize();
#ifdef __AFL_INIT
// Enable AFL deferred forkserver mode. Requires compilation using
// afl-clang-fast++. See fuzzing.md for details.
__AFL_INIT();
#endif
#ifdef __AFL_LOOP
// Enable AFL persistent mode. Requires compilation using afl-clang-fast++.
// See fuzzing.md for details.
while (__AFL_LOOP(1000)) {
std::vector<uint8_t> buffer;
if (!read_stdin(buffer)) {
continue;
}
test_one_input(buffer);
}
#else
std::vector<uint8_t> buffer;
if (!read_stdin(buffer)) {
return 0;
}
test_one_input(buffer);
#endif
return 0;
}

17
src/test/fuzz/fuzz.h Normal file
View file

@ -0,0 +1,17 @@
// Copyright (c) 2009-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_TEST_FUZZ_FUZZ_H
#define BITCOIN_TEST_FUZZ_FUZZ_H
#include <functional>
#include <stdint.h>
#include <vector>
const std::function<std::string(const char*)> G_TRANSLATION_FUN = nullptr;
void test_one_input(std::vector<uint8_t> buffer);
#endif // BITCOIN_TEST_FUZZ_FUZZ_H

View file

@ -2,10 +2,6 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#if defined(HAVE_CONFIG_H)
#include <config/bitcoin-config.h>
#endif
#include <addrman.h>
#include <blockencodings.h>
#include <chain.h>
@ -28,304 +24,144 @@
#include <memory>
#include <vector>
const std::function<std::string(const char*)> G_TRANSLATION_FUN = nullptr;
enum TEST_ID {
CBLOCK_DESERIALIZE=0,
CTRANSACTION_DESERIALIZE,
CBLOCKLOCATOR_DESERIALIZE,
CBLOCKMERKLEROOT,
CADDRMAN_DESERIALIZE,
CBLOCKHEADER_DESERIALIZE,
CBANENTRY_DESERIALIZE,
CTXUNDO_DESERIALIZE,
CBLOCKUNDO_DESERIALIZE,
CCOINS_DESERIALIZE,
CNETADDR_DESERIALIZE,
CSERVICE_DESERIALIZE,
CMESSAGEHEADER_DESERIALIZE,
CADDRESS_DESERIALIZE,
CINV_DESERIALIZE,
CBLOOMFILTER_DESERIALIZE,
CDISKBLOCKINDEX_DESERIALIZE,
CTXOUTCOMPRESSOR_DESERIALIZE,
BLOCKTRANSACTIONS_DESERIALIZE,
BLOCKTRANSACTIONSREQUEST_DESERIALIZE,
TEST_ID_END
};
static bool read_stdin(std::vector<uint8_t> &data) {
uint8_t buffer[1024];
ssize_t length=0;
while((length = read(STDIN_FILENO, buffer, 1024)) > 0) {
data.insert(data.end(), buffer, buffer+length);
if (data.size() > (1<<20)) return false;
}
return length==0;
}
static int test_one_input(std::vector<uint8_t> buffer) {
if (buffer.size() < sizeof(uint32_t)) return 0;
uint32_t test_id = 0xffffffff;
memcpy(&test_id, buffer.data(), sizeof(uint32_t));
buffer.erase(buffer.begin(), buffer.begin() + sizeof(uint32_t));
if (test_id >= TEST_ID_END) return 0;
#include <test/fuzz/fuzz.h>
void test_one_input(std::vector<uint8_t> buffer)
{
CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION);
try {
int nVersion;
ds >> nVersion;
ds.SetVersion(nVersion);
} catch (const std::ios_base::failure& e) {
return 0;
return;
}
switch(test_id) {
case CBLOCK_DESERIALIZE:
{
#if BLOCK_DESERIALIZE
try
{
CBlock block;
ds >> block;
} catch (const std::ios_base::failure& e) {return 0;}
break;
}
case CTRANSACTION_DESERIALIZE:
{
} catch (const std::ios_base::failure& e) {return;}
#elif TRANSACTION_DESERIALIZE
try
{
CTransaction tx(deserialize, ds);
} catch (const std::ios_base::failure& e) {return 0;}
break;
}
case CBLOCKLOCATOR_DESERIALIZE:
{
} catch (const std::ios_base::failure& e) {return;}
#elif BLOCKLOCATOR_DESERIALIZE
try
{
CBlockLocator bl;
ds >> bl;
} catch (const std::ios_base::failure& e) {return 0;}
break;
}
case CBLOCKMERKLEROOT:
{
} catch (const std::ios_base::failure& e) {return;}
#elif BLOCKMERKLEROOT
try
{
CBlock block;
ds >> block;
bool mutated;
BlockMerkleRoot(block, &mutated);
} catch (const std::ios_base::failure& e) {return 0;}
break;
}
case CADDRMAN_DESERIALIZE:
{
} catch (const std::ios_base::failure& e) {return;}
#elif ADDRMAN_DESERIALIZE
try
{
CAddrMan am;
ds >> am;
} catch (const std::ios_base::failure& e) {return 0;}
break;
}
case CBLOCKHEADER_DESERIALIZE:
{
} catch (const std::ios_base::failure& e) {return;}
#elif BLOCKHEADER_DESERIALIZE
try
{
CBlockHeader bh;
ds >> bh;
} catch (const std::ios_base::failure& e) {return 0;}
break;
}
case CBANENTRY_DESERIALIZE:
{
} catch (const std::ios_base::failure& e) {return;}
#elif BANENTRY_DESERIALIZE
try
{
CBanEntry be;
ds >> be;
} catch (const std::ios_base::failure& e) {return 0;}
break;
}
case CTXUNDO_DESERIALIZE:
{
} catch (const std::ios_base::failure& e) {return;}
#elif TXUNDO_DESERIALIZE
try
{
CTxUndo tu;
ds >> tu;
} catch (const std::ios_base::failure& e) {return 0;}
break;
}
case CBLOCKUNDO_DESERIALIZE:
{
} catch (const std::ios_base::failure& e) {return;}
#elif BLOCKUNDO_DESERIALIZE
try
{
CBlockUndo bu;
ds >> bu;
} catch (const std::ios_base::failure& e) {return 0;}
break;
}
case CCOINS_DESERIALIZE:
{
} catch (const std::ios_base::failure& e) {return;}
#elif COINS_DESERIALIZE
try
{
Coin coin;
ds >> coin;
} catch (const std::ios_base::failure& e) {return 0;}
break;
}
case CNETADDR_DESERIALIZE:
{
} catch (const std::ios_base::failure& e) {return;}
#elif NETADDR_DESERIALIZE
try
{
CNetAddr na;
ds >> na;
} catch (const std::ios_base::failure& e) {return 0;}
break;
}
case CSERVICE_DESERIALIZE:
{
} catch (const std::ios_base::failure& e) {return;}
#elif SERVICE_DESERIALIZE
try
{
CService s;
ds >> s;
} catch (const std::ios_base::failure& e) {return 0;}
break;
}
case CMESSAGEHEADER_DESERIALIZE:
{
} catch (const std::ios_base::failure& e) {return;}
#elif MESSAGEHEADER_DESERIALIZE
CMessageHeader::MessageStartChars pchMessageStart = {0x00, 0x00, 0x00, 0x00};
try
{
CMessageHeader mh(pchMessageStart);
ds >> mh;
if (!mh.IsValid(pchMessageStart)) {return 0;}
} catch (const std::ios_base::failure& e) {return 0;}
break;
}
case CADDRESS_DESERIALIZE:
{
if (!mh.IsValid(pchMessageStart)) {return;}
} catch (const std::ios_base::failure& e) {return;}
#elif ADDRESS_DESERIALIZE
try
{
CAddress a;
ds >> a;
} catch (const std::ios_base::failure& e) {return 0;}
break;
}
case CINV_DESERIALIZE:
{
} catch (const std::ios_base::failure& e) {return;}
#elif INV_DESERIALIZE
try
{
CInv i;
ds >> i;
} catch (const std::ios_base::failure& e) {return 0;}
break;
}
case CBLOOMFILTER_DESERIALIZE:
{
} catch (const std::ios_base::failure& e) {return;}
#elif BLOOMFILTER_DESERIALIZE
try
{
CBloomFilter bf;
ds >> bf;
} catch (const std::ios_base::failure& e) {return 0;}
break;
}
case CDISKBLOCKINDEX_DESERIALIZE:
{
} catch (const std::ios_base::failure& e) {return;}
#elif DISKBLOCKINDEX_DESERIALIZE
try
{
CDiskBlockIndex dbi;
ds >> dbi;
} catch (const std::ios_base::failure& e) {return 0;}
break;
}
case CTXOUTCOMPRESSOR_DESERIALIZE:
{
} catch (const std::ios_base::failure& e) {return;}
#elif TXOUTCOMPRESSOR_DESERIALIZE
CTxOut to;
CTxOutCompressor toc(to);
try
{
ds >> toc;
} catch (const std::ios_base::failure& e) {return 0;}
break;
}
case BLOCKTRANSACTIONS_DESERIALIZE:
{
} catch (const std::ios_base::failure& e) {return;}
#elif BLOCKTRANSACTIONS_DESERIALIZE
try
{
BlockTransactions bt;
ds >> bt;
} catch (const std::ios_base::failure& e) {return 0;}
break;
}
case BLOCKTRANSACTIONSREQUEST_DESERIALIZE:
{
} catch (const std::ios_base::failure& e) {return;}
#elif BLOCKTRANSACTIONSREQUEST_DESERIALIZE
try
{
BlockTransactionsRequest btr;
ds >> btr;
} catch (const std::ios_base::failure& e) {return 0;}
break;
}
default:
return 0;
}
return 0;
}
static std::unique_ptr<ECCVerifyHandle> globalVerifyHandle;
void initialize() {
globalVerifyHandle = MakeUnique<ECCVerifyHandle>();
}
// This function is used by libFuzzer
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
test_one_input(std::vector<uint8_t>(data, data + size));
return 0;
}
// This function is used by libFuzzer
extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) {
initialize();
return 0;
}
// Disabled under WIN32 due to clash with Cygwin's WinMain.
#ifndef WIN32
// Declare main(...) "weak" to allow for libFuzzer linking. libFuzzer provides
// the main(...) function.
__attribute__((weak))
#endif
int main(int argc, char **argv)
{
initialize();
#ifdef __AFL_INIT
// Enable AFL deferred forkserver mode. Requires compilation using
// afl-clang-fast++. See fuzzing.md for details.
__AFL_INIT();
#endif
#ifdef __AFL_LOOP
// Enable AFL persistent mode. Requires compilation using afl-clang-fast++.
// See fuzzing.md for details.
int ret = 0;
while (__AFL_LOOP(1000)) {
std::vector<uint8_t> buffer;
if (!read_stdin(buffer)) {
continue;
}
ret = test_one_input(buffer);
}
return ret;
} catch (const std::ios_base::failure& e) {return;}
#else
std::vector<uint8_t> buffer;
if (!read_stdin(buffer)) {
return 0;
}
return test_one_input(buffer);
#error Need at least one fuzz target to compile
#endif
}