Skip to content

Commit a65b55f

Browse files
author
MarcoFalke
committed
Merge #18994: tests: Add fuzzing harnesses for functions in script/
f898ef6 tests: Add fuzzing harness for functions in script/sign.h (practicalswift) c91d2f0 tests: Add fuzzing harness for functions in script/sigcache.h (practicalswift) d3d8adb tests: Add fuzzing harness for functions in script/interpreter.h (practicalswift) fa80117 tests: Add fuzzing harness for functions in script/descriptor.h (practicalswift) 43fb8f0 tests: Add fuzzing harness for functions in script/bitcoinconsensus.h (practicalswift) 8de7271 tests: Fill fuzzing coverage gaps for functions in script/script.h, script/script_error.h and script/standard.h (practicalswift) c571ecb tests: Add fuzzing helper functions ConsumeDataStream, ConsumeTxDestination and ConsumeUInt160 (practicalswift) Pull request description: Add fuzzing harnesses for functions in `script/`: * Add fuzzing helper functions `ConsumeDataStream` and `ConsumeUInt160` * Fill fuzzing coverage gaps for functions in `script/script.h`, `script/script_error.h` and `script/standard.h` * Add fuzzing harness for functions in `script/bitcoinconsensus.h` * Add fuzzing harness for functions in `script/descriptor.h` * Add fuzzing harness for functions in `script/interpreter.h` * Add fuzzing harness for functions in `script/sigcache.h` * Add fuzzing harness for functions in `script/sign.h` See [`doc/fuzzing.md`](https://github.com/bitcoin/bitcoin/blob/master/doc/fuzzing.md) for information on how to fuzz Bitcoin Core. Don't forget to contribute any coverage increasing inputs you find to the [Bitcoin Core fuzzing corpus repo](https://github.com/bitcoin-core/qa-assets). Happy fuzzing :) ACKs for top commit: MarcoFalke: ACK f898ef6 🔉 Tree-SHA512: f6e77b34dc79f23de5fa9e38ac06e6554b5b946ec3e9a67e2bd982e60aca37ce844f785457ef427a5e3b45e31c305456bca8587cc9f4a0b50b3852e39726eb04
2 parents 07d0e0d + f898ef6 commit a65b55f

9 files changed

+442
-2
lines changed

src/Makefile.test.include

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,14 @@ FUZZ_TARGETS = \
110110
test/fuzz/rbf \
111111
test/fuzz/rolling_bloom_filter \
112112
test/fuzz/script \
113+
test/fuzz/script_bitcoin_consensus \
114+
test/fuzz/script_descriptor_cache \
113115
test/fuzz/script_deserialize \
114116
test/fuzz/script_flags \
117+
test/fuzz/script_interpreter \
115118
test/fuzz/script_ops \
119+
test/fuzz/script_sigcache \
120+
test/fuzz/script_sign \
116121
test/fuzz/scriptnum_ops \
117122
test/fuzz/service_deserialize \
118123
test/fuzz/signature_checker \
@@ -941,6 +946,18 @@ test_fuzz_script_LDADD = $(FUZZ_SUITE_LD_COMMON)
941946
test_fuzz_script_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
942947
test_fuzz_script_SOURCES = test/fuzz/script.cpp
943948

949+
test_fuzz_script_bitcoin_consensus_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
950+
test_fuzz_script_bitcoin_consensus_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
951+
test_fuzz_script_bitcoin_consensus_LDADD = $(FUZZ_SUITE_LD_COMMON)
952+
test_fuzz_script_bitcoin_consensus_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
953+
test_fuzz_script_bitcoin_consensus_SOURCES = test/fuzz/script_bitcoin_consensus.cpp
954+
955+
test_fuzz_script_descriptor_cache_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
956+
test_fuzz_script_descriptor_cache_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
957+
test_fuzz_script_descriptor_cache_LDADD = $(FUZZ_SUITE_LD_COMMON)
958+
test_fuzz_script_descriptor_cache_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
959+
test_fuzz_script_descriptor_cache_SOURCES = test/fuzz/script_descriptor_cache.cpp
960+
944961
test_fuzz_script_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DSCRIPT_DESERIALIZE=1
945962
test_fuzz_script_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
946963
test_fuzz_script_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
@@ -953,12 +970,30 @@ test_fuzz_script_flags_LDADD = $(FUZZ_SUITE_LD_COMMON)
953970
test_fuzz_script_flags_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
954971
test_fuzz_script_flags_SOURCES = test/fuzz/script_flags.cpp
955972

973+
test_fuzz_script_interpreter_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
974+
test_fuzz_script_interpreter_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
975+
test_fuzz_script_interpreter_LDADD = $(FUZZ_SUITE_LD_COMMON)
976+
test_fuzz_script_interpreter_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
977+
test_fuzz_script_interpreter_SOURCES = test/fuzz/script_interpreter.cpp
978+
956979
test_fuzz_script_ops_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
957980
test_fuzz_script_ops_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
958981
test_fuzz_script_ops_LDADD = $(FUZZ_SUITE_LD_COMMON)
959982
test_fuzz_script_ops_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
960983
test_fuzz_script_ops_SOURCES = test/fuzz/script_ops.cpp
961984

985+
test_fuzz_script_sigcache_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
986+
test_fuzz_script_sigcache_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
987+
test_fuzz_script_sigcache_LDADD = $(FUZZ_SUITE_LD_COMMON)
988+
test_fuzz_script_sigcache_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
989+
test_fuzz_script_sigcache_SOURCES = test/fuzz/script_sigcache.cpp
990+
991+
test_fuzz_script_sign_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
992+
test_fuzz_script_sign_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
993+
test_fuzz_script_sign_LDADD = $(FUZZ_SUITE_LD_COMMON)
994+
test_fuzz_script_sign_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
995+
test_fuzz_script_sign_SOURCES = test/fuzz/script_sign.cpp
996+
962997
test_fuzz_scriptnum_ops_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
963998
test_fuzz_scriptnum_ops_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
964999
test_fuzz_scriptnum_ops_LDADD = $(FUZZ_SUITE_LD_COMMON)

src/test/fuzz/script.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <script/descriptor.h>
1212
#include <script/interpreter.h>
1313
#include <script/script.h>
14+
#include <script/script_error.h>
1415
#include <script/sign.h>
1516
#include <script/signingprovider.h>
1617
#include <script/standard.h>
@@ -21,6 +22,8 @@
2122
#include <univalue.h>
2223
#include <util/memory.h>
2324

25+
#include <algorithm>
26+
#include <cassert>
2427
#include <cstdint>
2528
#include <optional>
2629
#include <string>
@@ -124,4 +127,40 @@ void test_one_input(const std::vector<uint8_t>& buffer)
124127
wit.SetNull();
125128
}
126129
}
130+
131+
(void)GetOpName(ConsumeOpcodeType(fuzzed_data_provider));
132+
(void)ScriptErrorString(static_cast<ScriptError>(fuzzed_data_provider.ConsumeIntegralInRange<int>(0, SCRIPT_ERR_ERROR_COUNT)));
133+
134+
{
135+
const std::vector<uint8_t> bytes = ConsumeRandomLengthByteVector(fuzzed_data_provider);
136+
CScript append_script{bytes.begin(), bytes.end()};
137+
append_script << fuzzed_data_provider.ConsumeIntegral<int64_t>();
138+
append_script << ConsumeOpcodeType(fuzzed_data_provider);
139+
append_script << CScriptNum{fuzzed_data_provider.ConsumeIntegral<int64_t>()};
140+
append_script << ConsumeRandomLengthByteVector(fuzzed_data_provider);
141+
}
142+
143+
{
144+
WitnessUnknown witness_unknown_1{};
145+
witness_unknown_1.version = fuzzed_data_provider.ConsumeIntegral<int>();
146+
const std::vector<uint8_t> witness_unknown_program_1 = fuzzed_data_provider.ConsumeBytes<uint8_t>(40);
147+
witness_unknown_1.length = witness_unknown_program_1.size();
148+
std::copy(witness_unknown_program_1.begin(), witness_unknown_program_1.end(), witness_unknown_1.program);
149+
150+
WitnessUnknown witness_unknown_2{};
151+
witness_unknown_2.version = fuzzed_data_provider.ConsumeIntegral<int>();
152+
const std::vector<uint8_t> witness_unknown_program_2 = fuzzed_data_provider.ConsumeBytes<uint8_t>(40);
153+
witness_unknown_2.length = witness_unknown_program_2.size();
154+
std::copy(witness_unknown_program_2.begin(), witness_unknown_program_2.end(), witness_unknown_2.program);
155+
156+
(void)(witness_unknown_1 == witness_unknown_2);
157+
(void)(witness_unknown_1 < witness_unknown_2);
158+
}
159+
160+
{
161+
const CTxDestination tx_destination_1 = ConsumeTxDestination(fuzzed_data_provider);
162+
const CTxDestination tx_destination_2 = ConsumeTxDestination(fuzzed_data_provider);
163+
(void)(tx_destination_1 == tx_destination_2);
164+
(void)(tx_destination_1 < tx_destination_2);
165+
}
127166
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright (c) 2020 The Bitcoin Core developers
2+
// Distributed under the MIT software license, see the accompanying
3+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
#include <script/bitcoinconsensus.h>
6+
#include <script/interpreter.h>
7+
#include <test/fuzz/FuzzedDataProvider.h>
8+
#include <test/fuzz/fuzz.h>
9+
#include <test/fuzz/util.h>
10+
11+
#include <cstdint>
12+
#include <string>
13+
#include <vector>
14+
15+
void test_one_input(const std::vector<uint8_t>& buffer)
16+
{
17+
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
18+
const std::vector<uint8_t> random_bytes_1 = ConsumeRandomLengthByteVector(fuzzed_data_provider);
19+
const std::vector<uint8_t> random_bytes_2 = ConsumeRandomLengthByteVector(fuzzed_data_provider);
20+
const CAmount money = ConsumeMoney(fuzzed_data_provider);
21+
bitcoinconsensus_error err;
22+
bitcoinconsensus_error* err_p = fuzzed_data_provider.ConsumeBool() ? &err : nullptr;
23+
const unsigned int n_in = fuzzed_data_provider.ConsumeIntegral<unsigned int>();
24+
const unsigned int flags = fuzzed_data_provider.ConsumeIntegral<unsigned int>();
25+
assert(bitcoinconsensus_version() == BITCOINCONSENSUS_API_VER);
26+
if ((flags & SCRIPT_VERIFY_WITNESS) != 0 && (flags & SCRIPT_VERIFY_P2SH) == 0) {
27+
return;
28+
}
29+
(void)bitcoinconsensus_verify_script(random_bytes_1.data(), random_bytes_1.size(), random_bytes_2.data(), random_bytes_2.size(), n_in, flags, err_p);
30+
(void)bitcoinconsensus_verify_script_with_amount(random_bytes_1.data(), random_bytes_1.size(), money, random_bytes_2.data(), random_bytes_2.size(), n_in, flags, err_p);
31+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Copyright (c) 2020 The Bitcoin Core developers
2+
// Distributed under the MIT software license, see the accompanying
3+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
#include <optional.h>
6+
#include <pubkey.h>
7+
#include <script/descriptor.h>
8+
#include <test/fuzz/FuzzedDataProvider.h>
9+
#include <test/fuzz/fuzz.h>
10+
#include <test/fuzz/util.h>
11+
12+
#include <cstdint>
13+
#include <string>
14+
#include <vector>
15+
16+
void test_one_input(const std::vector<uint8_t>& buffer)
17+
{
18+
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
19+
DescriptorCache descriptor_cache;
20+
while (fuzzed_data_provider.ConsumeBool()) {
21+
const std::vector<uint8_t> code = fuzzed_data_provider.ConsumeBytes<uint8_t>(BIP32_EXTKEY_SIZE);
22+
if (code.size() == BIP32_EXTKEY_SIZE) {
23+
CExtPubKey xpub;
24+
xpub.Decode(code.data());
25+
const uint32_t key_exp_pos = fuzzed_data_provider.ConsumeIntegral<uint32_t>();
26+
CExtPubKey xpub_fetched;
27+
if (fuzzed_data_provider.ConsumeBool()) {
28+
(void)descriptor_cache.GetCachedParentExtPubKey(key_exp_pos, xpub_fetched);
29+
descriptor_cache.CacheParentExtPubKey(key_exp_pos, xpub);
30+
assert(descriptor_cache.GetCachedParentExtPubKey(key_exp_pos, xpub_fetched));
31+
} else {
32+
const uint32_t der_index = fuzzed_data_provider.ConsumeIntegral<uint32_t>();
33+
(void)descriptor_cache.GetCachedDerivedExtPubKey(key_exp_pos, der_index, xpub_fetched);
34+
descriptor_cache.CacheDerivedExtPubKey(key_exp_pos, der_index, xpub);
35+
assert(descriptor_cache.GetCachedDerivedExtPubKey(key_exp_pos, der_index, xpub_fetched));
36+
}
37+
assert(xpub == xpub_fetched);
38+
}
39+
(void)descriptor_cache.GetCachedParentExtPubKeys();
40+
(void)descriptor_cache.GetCachedDerivedExtPubKeys();
41+
}
42+
}

src/test/fuzz/script_interpreter.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Copyright (c) 2020 The Bitcoin Core developers
2+
// Distributed under the MIT software license, see the accompanying
3+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
#include <primitives/transaction.h>
6+
#include <script/interpreter.h>
7+
#include <test/fuzz/FuzzedDataProvider.h>
8+
#include <test/fuzz/fuzz.h>
9+
#include <test/fuzz/util.h>
10+
11+
#include <cstdint>
12+
#include <optional>
13+
#include <string>
14+
#include <vector>
15+
16+
bool CastToBool(const std::vector<unsigned char>& vch);
17+
18+
void test_one_input(const std::vector<uint8_t>& buffer)
19+
{
20+
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
21+
{
22+
const CScript script_code = ConsumeScript(fuzzed_data_provider);
23+
const std::optional<CMutableTransaction> mtx = ConsumeDeserializable<CMutableTransaction>(fuzzed_data_provider);
24+
if (mtx) {
25+
const CTransaction tx_to{*mtx};
26+
const unsigned int in = fuzzed_data_provider.ConsumeIntegral<unsigned int>();
27+
if (in < tx_to.vin.size()) {
28+
(void)SignatureHash(script_code, tx_to, in, fuzzed_data_provider.ConsumeIntegral<int>(), ConsumeMoney(fuzzed_data_provider), fuzzed_data_provider.PickValueInArray({SigVersion::BASE, SigVersion::WITNESS_V0}), nullptr);
29+
const std::optional<CMutableTransaction> mtx_precomputed = ConsumeDeserializable<CMutableTransaction>(fuzzed_data_provider);
30+
if (mtx_precomputed) {
31+
const CTransaction tx_precomputed{*mtx_precomputed};
32+
const PrecomputedTransactionData precomputed_transaction_data{tx_precomputed};
33+
(void)SignatureHash(script_code, tx_to, in, fuzzed_data_provider.ConsumeIntegral<int>(), ConsumeMoney(fuzzed_data_provider), fuzzed_data_provider.PickValueInArray({SigVersion::BASE, SigVersion::WITNESS_V0}), &precomputed_transaction_data);
34+
}
35+
}
36+
}
37+
}
38+
{
39+
(void)CastToBool(ConsumeRandomLengthByteVector(fuzzed_data_provider));
40+
}
41+
}

src/test/fuzz/script_sigcache.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Copyright (c) 2020 The Bitcoin Core developers
2+
// Distributed under the MIT software license, see the accompanying
3+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
#include <chainparams.h>
6+
#include <chainparamsbase.h>
7+
#include <key.h>
8+
#include <pubkey.h>
9+
#include <script/sigcache.h>
10+
#include <test/fuzz/FuzzedDataProvider.h>
11+
#include <test/fuzz/fuzz.h>
12+
#include <test/fuzz/util.h>
13+
14+
#include <cstdint>
15+
#include <optional>
16+
#include <string>
17+
#include <vector>
18+
19+
void initialize()
20+
{
21+
static const ECCVerifyHandle ecc_verify_handle;
22+
ECC_Start();
23+
SelectParams(CBaseChainParams::REGTEST);
24+
InitSignatureCache();
25+
}
26+
27+
void test_one_input(const std::vector<uint8_t>& buffer)
28+
{
29+
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
30+
31+
const std::optional<CMutableTransaction> mutable_transaction = ConsumeDeserializable<CMutableTransaction>(fuzzed_data_provider);
32+
const CTransaction tx = mutable_transaction ? CTransaction{*mutable_transaction} : CTransaction{};
33+
const unsigned int n_in = fuzzed_data_provider.ConsumeIntegral<unsigned int>();
34+
const CAmount amount = ConsumeMoney(fuzzed_data_provider);
35+
const bool store = fuzzed_data_provider.ConsumeBool();
36+
PrecomputedTransactionData tx_data;
37+
CachingTransactionSignatureChecker caching_transaction_signature_checker{mutable_transaction ? &tx : nullptr, n_in, amount, store, tx_data};
38+
const std::optional<CPubKey> pub_key = ConsumeDeserializable<CPubKey>(fuzzed_data_provider);
39+
if (pub_key) {
40+
const std::vector<uint8_t> random_bytes = ConsumeRandomLengthByteVector(fuzzed_data_provider);
41+
if (!random_bytes.empty()) {
42+
(void)caching_transaction_signature_checker.VerifySignature(random_bytes, *pub_key, ConsumeUInt256(fuzzed_data_provider));
43+
}
44+
}
45+
}

0 commit comments

Comments
 (0)