diff options
Diffstat (limited to 'src/test')
-rw-r--r-- | src/test/base58_tests.cpp | 37 | ||||
-rw-r--r-- | src/test/crypto_tests.cpp | 15 | ||||
-rw-r--r-- | src/test/dbwrapper_tests.cpp | 12 | ||||
-rw-r--r-- | src/test/fuzz/descriptor_parse.cpp | 3 | ||||
-rw-r--r-- | src/test/fuzz/deserialize.cpp | 270 | ||||
-rw-r--r-- | src/test/fuzz/integer.cpp | 127 | ||||
-rw-r--r-- | src/test/fuzz/parse_hd_keypath.cpp | 13 | ||||
-rw-r--r-- | src/test/fuzz/parse_numbers.cpp | 35 | ||||
-rw-r--r-- | src/test/fuzz/parse_script.cpp | 16 | ||||
-rw-r--r-- | src/test/fuzz/parse_univalue.cpp | 91 | ||||
-rw-r--r-- | src/test/fuzz/transaction.cpp | 22 | ||||
-rw-r--r-- | src/test/fuzz/tx_in.cpp | 33 | ||||
-rw-r--r-- | src/test/fuzz/tx_out.cpp | 35 | ||||
-rw-r--r-- | src/test/transaction_tests.cpp | 34 |
14 files changed, 620 insertions, 123 deletions
diff --git a/src/test/base58_tests.cpp b/src/test/base58_tests.cpp index 52301f799a..57559fa687 100644 --- a/src/test/base58_tests.cpp +++ b/src/test/base58_tests.cpp @@ -7,6 +7,7 @@ #include <base58.h> #include <test/util/setup_common.h> #include <util/strencodings.h> +#include <util/vector.h> #include <univalue.h> @@ -53,17 +54,45 @@ BOOST_AUTO_TEST_CASE(base58_DecodeBase58) } std::vector<unsigned char> expected = ParseHex(test[0].get_str()); std::string base58string = test[1].get_str(); - BOOST_CHECK_MESSAGE(DecodeBase58(base58string, result), strTest); + BOOST_CHECK_MESSAGE(DecodeBase58(base58string, result, 256), strTest); BOOST_CHECK_MESSAGE(result.size() == expected.size() && std::equal(result.begin(), result.end(), expected.begin()), strTest); } - BOOST_CHECK(!DecodeBase58("invalid", result)); + BOOST_CHECK(!DecodeBase58("invalid", result, 100)); + BOOST_CHECK(!DecodeBase58(std::string("invalid"), result, 100)); + BOOST_CHECK(!DecodeBase58(std::string("\0invalid", 8), result, 100)); + + BOOST_CHECK(DecodeBase58(std::string("good", 4), result, 100)); + BOOST_CHECK(!DecodeBase58(std::string("bad0IOl", 7), result, 100)); + BOOST_CHECK(!DecodeBase58(std::string("goodbad0IOl", 11), result, 100)); + BOOST_CHECK(!DecodeBase58(std::string("good\0bad0IOl", 12), result, 100)); // check that DecodeBase58 skips whitespace, but still fails with unexpected non-whitespace at the end. - BOOST_CHECK(!DecodeBase58(" \t\n\v\f\r skip \r\f\v\n\t a", result)); - BOOST_CHECK( DecodeBase58(" \t\n\v\f\r skip \r\f\v\n\t ", result)); + BOOST_CHECK(!DecodeBase58(" \t\n\v\f\r skip \r\f\v\n\t a", result, 3)); + BOOST_CHECK( DecodeBase58(" \t\n\v\f\r skip \r\f\v\n\t ", result, 3)); std::vector<unsigned char> expected = ParseHex("971a55"); BOOST_CHECK_EQUAL_COLLECTIONS(result.begin(), result.end(), expected.begin(), expected.end()); + + BOOST_CHECK(DecodeBase58Check(std::string("3vQB7B6MrGQZaxCuFg4oh", 21), result, 100)); + BOOST_CHECK(!DecodeBase58Check(std::string("3vQB7B6MrGQZaxCuFg4oi", 21), result, 100)); + BOOST_CHECK(!DecodeBase58Check(std::string("3vQB7B6MrGQZaxCuFg4oh0IOl", 25), result, 100)); + BOOST_CHECK(!DecodeBase58Check(std::string("3vQB7B6MrGQZaxCuFg4oh\00IOl", 26), result, 100)); +} + +BOOST_AUTO_TEST_CASE(base58_random_encode_decode) +{ + for (int n = 0; n < 1000; ++n) { + unsigned int len = 1 + InsecureRandBits(8); + unsigned int zeroes = InsecureRandBool() ? InsecureRandRange(len + 1) : 0; + auto data = Cat(std::vector<unsigned char>(zeroes, '\000'), g_insecure_rand_ctx.randbytes(len - zeroes)); + auto encoded = EncodeBase58Check(data); + std::vector<unsigned char> decoded; + auto ok_too_small = DecodeBase58Check(encoded, decoded, InsecureRandRange(len)); + BOOST_CHECK(!ok_too_small); + auto ok = DecodeBase58Check(encoded, decoded, len + InsecureRandRange(257 - len)); + BOOST_CHECK(ok); + BOOST_CHECK(data == decoded); + } } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp index 591a317d17..2deb0c5bfc 100644 --- a/src/test/crypto_tests.cpp +++ b/src/test/crypto_tests.cpp @@ -186,14 +186,15 @@ static void TestHKDF_SHA256_32(const std::string &ikm_hex, const std::string &sa BOOST_CHECK(HexStr(out, out + 32) == okm_check_hex); } -static std::string LongTestString() { +static std::string LongTestString() +{ std::string ret; - for (int i=0; i<200000; i++) { - ret += (unsigned char)(i); - ret += (unsigned char)(i >> 4); - ret += (unsigned char)(i >> 8); - ret += (unsigned char)(i >> 12); - ret += (unsigned char)(i >> 16); + for (int i = 0; i < 200000; i++) { + ret += (char)(i); + ret += (char)(i >> 4); + ret += (char)(i >> 8); + ret += (char)(i >> 12); + ret += (char)(i >> 16); } return ret; } diff --git a/src/test/dbwrapper_tests.cpp b/src/test/dbwrapper_tests.cpp index 57d5b2bb5c..b647c0f70b 100644 --- a/src/test/dbwrapper_tests.cpp +++ b/src/test/dbwrapper_tests.cpp @@ -397,6 +397,18 @@ BOOST_AUTO_TEST_CASE(iterator_string_ordering) } } +BOOST_AUTO_TEST_CASE(unicodepath) +{ + // Attempt to create a database with a utf8 character in the path. + // On Windows this test will fail if the directory is created using + // the ANSI CreateDirectoryA call and the code page isn't UTF8. + // It will succeed if the created with CreateDirectoryW. + fs::path ph = GetDataDir() / "test_runner_₿_🏃_20191128_104644"; + CDBWrapper dbw(ph, (1 << 20)); + + fs::path lockPath = ph / "LOCK"; + BOOST_CHECK(boost::filesystem::exists(lockPath)); +} BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/fuzz/descriptor_parse.cpp b/src/test/fuzz/descriptor_parse.cpp index c4c25854fd..47d5038c26 100644 --- a/src/test/fuzz/descriptor_parse.cpp +++ b/src/test/fuzz/descriptor_parse.cpp @@ -3,11 +3,14 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <chainparams.h> +#include <pubkey.h> #include <script/descriptor.h> #include <test/fuzz/fuzz.h> +#include <util/memory.h> void initialize() { + static const auto verify_handle = MakeUnique<ECCVerifyHandle>(); SelectParams(CBaseChainParams::REGTEST); } diff --git a/src/test/fuzz/deserialize.cpp b/src/test/fuzz/deserialize.cpp index bcd8691359..bd05283b78 100644 --- a/src/test/fuzz/deserialize.cpp +++ b/src/test/fuzz/deserialize.cpp @@ -5,18 +5,25 @@ #include <addrdb.h> #include <addrman.h> #include <blockencodings.h> +#include <blockfilter.h> #include <chain.h> #include <coins.h> #include <compressor.h> #include <consensus/merkle.h> +#include <key.h> +#include <merkleblock.h> #include <net.h> #include <primitives/block.h> #include <protocol.h> +#include <psbt.h> #include <pubkey.h> +#include <script/keyorigin.h> #include <streams.h> #include <undo.h> #include <version.h> +#include <exception> +#include <stdexcept> #include <stdint.h> #include <unistd.h> @@ -30,137 +37,186 @@ void initialize() static const auto verify_handle = MakeUnique<ECCVerifyHandle>(); } -void test_one_input(const std::vector<uint8_t>& buffer) +namespace { + +struct invalid_fuzzing_input_exception : public std::exception { +}; + +template <typename T> +CDataStream Serialize(const T& obj) +{ + CDataStream ds(SER_NETWORK, INIT_PROTO_VERSION); + ds << obj; + return ds; +} + +template <typename T> +T Deserialize(CDataStream ds) +{ + T obj; + ds >> obj; + return obj; +} + +template <typename T> +void DeserializeFromFuzzingInput(const std::vector<uint8_t>& buffer, T& obj) { CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION); try { - int nVersion; - ds >> nVersion; - ds.SetVersion(nVersion); - } catch (const std::ios_base::failure& e) { - return; + int version; + ds >> version; + ds.SetVersion(version); + } catch (const std::ios_base::failure&) { + throw invalid_fuzzing_input_exception(); + } + try { + ds >> obj; + } catch (const std::ios_base::failure&) { + throw invalid_fuzzing_input_exception(); } + assert(buffer.empty() || !Serialize(obj).empty()); +} + +template <typename T> +void AssertEqualAfterSerializeDeserialize(const T& obj) +{ + assert(Deserialize<T>(Serialize(obj)) == obj); +} -#if BLOCK_DESERIALIZE - try - { - CBlock block; - ds >> block; - } catch (const std::ios_base::failure& e) {return;} +} // namespace + +void test_one_input(const std::vector<uint8_t>& buffer) +{ + try { +#if BLOCK_FILTER_DESERIALIZE + BlockFilter block_filter; + DeserializeFromFuzzingInput(buffer, block_filter); +#elif ADDR_INFO_DESERIALIZE + CAddrInfo addr_info; + DeserializeFromFuzzingInput(buffer, addr_info); +#elif BLOCK_FILE_INFO_DESERIALIZE + CBlockFileInfo block_file_info; + DeserializeFromFuzzingInput(buffer, block_file_info); +#elif BLOCK_HEADER_AND_SHORT_TXIDS_DESERIALIZE + CBlockHeaderAndShortTxIDs block_header_and_short_txids; + DeserializeFromFuzzingInput(buffer, block_header_and_short_txids); +#elif FEE_RATE_DESERIALIZE + CFeeRate fee_rate; + DeserializeFromFuzzingInput(buffer, fee_rate); + AssertEqualAfterSerializeDeserialize(fee_rate); +#elif MERKLE_BLOCK_DESERIALIZE + CMerkleBlock merkle_block; + DeserializeFromFuzzingInput(buffer, merkle_block); +#elif OUT_POINT_DESERIALIZE + COutPoint out_point; + DeserializeFromFuzzingInput(buffer, out_point); + AssertEqualAfterSerializeDeserialize(out_point); +#elif PARTIAL_MERKLE_TREE_DESERIALIZE + CPartialMerkleTree partial_merkle_tree; + DeserializeFromFuzzingInput(buffer, partial_merkle_tree); +#elif PUB_KEY_DESERIALIZE + CPubKey pub_key; + DeserializeFromFuzzingInput(buffer, pub_key); + // TODO: The following equivalence should hold for CPubKey? Fix. + // AssertEqualAfterSerializeDeserialize(pub_key); +#elif SCRIPT_DESERIALIZE + CScript script; + DeserializeFromFuzzingInput(buffer, script); +#elif SUB_NET_DESERIALIZE + CSubNet sub_net; + DeserializeFromFuzzingInput(buffer, sub_net); + AssertEqualAfterSerializeDeserialize(sub_net); +#elif TX_IN_DESERIALIZE + CTxIn tx_in; + DeserializeFromFuzzingInput(buffer, tx_in); + AssertEqualAfterSerializeDeserialize(tx_in); +#elif FLAT_FILE_POS_DESERIALIZE + FlatFilePos flat_file_pos; + DeserializeFromFuzzingInput(buffer, flat_file_pos); + AssertEqualAfterSerializeDeserialize(flat_file_pos); +#elif KEY_ORIGIN_INFO_DESERIALIZE + KeyOriginInfo key_origin_info; + DeserializeFromFuzzingInput(buffer, key_origin_info); + AssertEqualAfterSerializeDeserialize(key_origin_info); +#elif PARTIALLY_SIGNED_TRANSACTION_DESERIALIZE + PartiallySignedTransaction partially_signed_transaction; + DeserializeFromFuzzingInput(buffer, partially_signed_transaction); +#elif PREFILLED_TRANSACTION_DESERIALIZE + PrefilledTransaction prefilled_transaction; + DeserializeFromFuzzingInput(buffer, prefilled_transaction); +#elif PSBT_INPUT_DESERIALIZE + PSBTInput psbt_input; + DeserializeFromFuzzingInput(buffer, psbt_input); +#elif PSBT_OUTPUT_DESERIALIZE + PSBTOutput psbt_output; + DeserializeFromFuzzingInput(buffer, psbt_output); +#elif BLOCK_DESERIALIZE + CBlock block; + DeserializeFromFuzzingInput(buffer, block); #elif BLOCKLOCATOR_DESERIALIZE - try - { - CBlockLocator bl; - ds >> bl; - } catch (const std::ios_base::failure& e) {return;} + CBlockLocator bl; + DeserializeFromFuzzingInput(buffer, bl); #elif BLOCKMERKLEROOT - try - { - CBlock block; - ds >> block; - bool mutated; - BlockMerkleRoot(block, &mutated); - } catch (const std::ios_base::failure& e) {return;} + CBlock block; + DeserializeFromFuzzingInput(buffer, block); + bool mutated; + BlockMerkleRoot(block, &mutated); #elif ADDRMAN_DESERIALIZE - try - { - CAddrMan am; - ds >> am; - } catch (const std::ios_base::failure& e) {return;} + CAddrMan am; + DeserializeFromFuzzingInput(buffer, am); #elif BLOCKHEADER_DESERIALIZE - try - { - CBlockHeader bh; - ds >> bh; - } catch (const std::ios_base::failure& e) {return;} + CBlockHeader bh; + DeserializeFromFuzzingInput(buffer, bh); #elif BANENTRY_DESERIALIZE - try - { - CBanEntry be; - ds >> be; - } catch (const std::ios_base::failure& e) {return;} + CBanEntry be; + DeserializeFromFuzzingInput(buffer, be); #elif TXUNDO_DESERIALIZE - try - { - CTxUndo tu; - ds >> tu; - } catch (const std::ios_base::failure& e) {return;} + CTxUndo tu; + DeserializeFromFuzzingInput(buffer, tu); #elif BLOCKUNDO_DESERIALIZE - try - { - CBlockUndo bu; - ds >> bu; - } catch (const std::ios_base::failure& e) {return;} + CBlockUndo bu; + DeserializeFromFuzzingInput(buffer, bu); #elif COINS_DESERIALIZE - try - { - Coin coin; - ds >> coin; - } catch (const std::ios_base::failure& e) {return;} + Coin coin; + DeserializeFromFuzzingInput(buffer, coin); #elif NETADDR_DESERIALIZE - try - { - CNetAddr na; - ds >> na; - } catch (const std::ios_base::failure& e) {return;} + CNetAddr na; + DeserializeFromFuzzingInput(buffer, na); + AssertEqualAfterSerializeDeserialize(na); #elif SERVICE_DESERIALIZE - try - { - CService s; - ds >> s; - } catch (const std::ios_base::failure& e) {return;} + CService s; + DeserializeFromFuzzingInput(buffer, s); + AssertEqualAfterSerializeDeserialize(s); #elif MESSAGEHEADER_DESERIALIZE - CMessageHeader::MessageStartChars pchMessageStart = {0x00, 0x00, 0x00, 0x00}; - try - { - CMessageHeader mh(pchMessageStart); - ds >> mh; - if (!mh.IsValid(pchMessageStart)) {return;} - } catch (const std::ios_base::failure& e) {return;} + const CMessageHeader::MessageStartChars pchMessageStart = {0x00, 0x00, 0x00, 0x00}; + CMessageHeader mh(pchMessageStart); + DeserializeFromFuzzingInput(buffer, mh); + (void)mh.IsValid(pchMessageStart); #elif ADDRESS_DESERIALIZE - try - { - CAddress a; - ds >> a; - } catch (const std::ios_base::failure& e) {return;} + CAddress a; + DeserializeFromFuzzingInput(buffer, a); #elif INV_DESERIALIZE - try - { - CInv i; - ds >> i; - } catch (const std::ios_base::failure& e) {return;} + CInv i; + DeserializeFromFuzzingInput(buffer, i); #elif BLOOMFILTER_DESERIALIZE - try - { - CBloomFilter bf; - ds >> bf; - } catch (const std::ios_base::failure& e) {return;} + CBloomFilter bf; + DeserializeFromFuzzingInput(buffer, bf); #elif DISKBLOCKINDEX_DESERIALIZE - try - { - CDiskBlockIndex dbi; - ds >> dbi; - } catch (const std::ios_base::failure& e) {return;} + CDiskBlockIndex dbi; + DeserializeFromFuzzingInput(buffer, dbi); #elif TXOUTCOMPRESSOR_DESERIALIZE - CTxOut to; - CTxOutCompressor toc(to); - try - { - ds >> toc; - } catch (const std::ios_base::failure& e) {return;} + CTxOut to; + CTxOutCompressor toc(to); + DeserializeFromFuzzingInput(buffer, toc); #elif BLOCKTRANSACTIONS_DESERIALIZE - try - { - BlockTransactions bt; - ds >> bt; - } catch (const std::ios_base::failure& e) {return;} + BlockTransactions bt; + DeserializeFromFuzzingInput(buffer, bt); #elif BLOCKTRANSACTIONSREQUEST_DESERIALIZE - try - { - BlockTransactionsRequest btr; - ds >> btr; - } catch (const std::ios_base::failure& e) {return;} + BlockTransactionsRequest btr; + DeserializeFromFuzzingInput(buffer, btr); #else #error Need at least one fuzz target to compile #endif + } catch (const invalid_fuzzing_input_exception&) { + } } diff --git a/src/test/fuzz/integer.cpp b/src/test/fuzz/integer.cpp new file mode 100644 index 0000000000..723938bcdb --- /dev/null +++ b/src/test/fuzz/integer.cpp @@ -0,0 +1,127 @@ +// Copyright (c) 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 <arith_uint256.h> +#include <compressor.h> +#include <consensus/merkle.h> +#include <core_io.h> +#include <crypto/common.h> +#include <crypto/siphash.h> +#include <key_io.h> +#include <memusage.h> +#include <netbase.h> +#include <policy/settings.h> +#include <pow.h> +#include <pubkey.h> +#include <rpc/util.h> +#include <script/signingprovider.h> +#include <script/standard.h> +#include <serialize.h> +#include <test/fuzz/FuzzedDataProvider.h> +#include <test/fuzz/fuzz.h> +#include <uint256.h> +#include <util/strencodings.h> +#include <util/system.h> +#include <util/time.h> + +#include <cassert> +#include <limits> +#include <vector> + +void initialize() +{ + SelectParams(CBaseChainParams::REGTEST); +} + +void test_one_input(const std::vector<uint8_t>& buffer) +{ + if (buffer.size() < sizeof(uint256) + sizeof(uint160)) { + return; + } + FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); + const uint256 u256(fuzzed_data_provider.ConsumeBytes<unsigned char>(sizeof(uint256))); + const uint160 u160(fuzzed_data_provider.ConsumeBytes<unsigned char>(sizeof(uint160))); + const uint64_t u64 = fuzzed_data_provider.ConsumeIntegral<uint64_t>(); + const int64_t i64 = fuzzed_data_provider.ConsumeIntegral<int64_t>(); + const uint32_t u32 = fuzzed_data_provider.ConsumeIntegral<uint32_t>(); + const int32_t i32 = fuzzed_data_provider.ConsumeIntegral<int32_t>(); + const uint16_t u16 = fuzzed_data_provider.ConsumeIntegral<uint16_t>(); + const int16_t i16 = fuzzed_data_provider.ConsumeIntegral<int16_t>(); + const uint8_t u8 = fuzzed_data_provider.ConsumeIntegral<uint8_t>(); + const int8_t i8 = fuzzed_data_provider.ConsumeIntegral<int8_t>(); + // We cannot assume a specific value of std::is_signed<char>::value: + // ConsumeIntegral<char>() instead of casting from {u,}int8_t. + const char ch = fuzzed_data_provider.ConsumeIntegral<char>(); + + const Consensus::Params& consensus_params = Params().GetConsensus(); + (void)CheckProofOfWork(u256, u32, consensus_params); + (void)CompressAmount(u64); + static const uint256 u256_min(uint256S("0000000000000000000000000000000000000000000000000000000000000000")); + static const uint256 u256_max(uint256S("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")); + const std::vector<uint256> v256{u256, u256_min, u256_max}; + (void)ComputeMerkleRoot(v256); + (void)CountBits(u64); + (void)DecompressAmount(u64); + (void)FormatISO8601Date(i64); + (void)FormatISO8601DateTime(i64); + (void)GetSizeOfCompactSize(u64); + (void)GetSpecialScriptSize(u32); + // (void)GetVirtualTransactionSize(i64, i64); // function defined only for a subset of int64_t inputs + // (void)GetVirtualTransactionSize(i64, i64, u32); // function defined only for a subset of int64_t/uint32_t inputs + (void)HexDigit(ch); + (void)i64tostr(i64); + (void)IsDigit(ch); + (void)IsSpace(ch); + (void)IsSwitchChar(ch); + (void)itostr(i32); + (void)memusage::DynamicUsage(ch); + (void)memusage::DynamicUsage(i16); + (void)memusage::DynamicUsage(i32); + (void)memusage::DynamicUsage(i64); + (void)memusage::DynamicUsage(i8); + (void)memusage::DynamicUsage(u16); + (void)memusage::DynamicUsage(u32); + (void)memusage::DynamicUsage(u64); + (void)memusage::DynamicUsage(u8); + const unsigned char uch = static_cast<unsigned char>(u8); + (void)memusage::DynamicUsage(uch); + (void)MillisToTimeval(i64); + const double d = ser_uint64_to_double(u64); + assert(ser_double_to_uint64(d) == u64); + const float f = ser_uint32_to_float(u32); + assert(ser_float_to_uint32(f) == u32); + (void)SighashToStr(uch); + (void)SipHashUint256(u64, u64, u256); + (void)SipHashUint256Extra(u64, u64, u256, u32); + (void)ToLower(ch); + + const arith_uint256 au256 = UintToArith256(u256); + assert(ArithToUint256(au256) == u256); + assert(uint256S(au256.GetHex()) == u256); + (void)au256.bits(); + (void)au256.GetCompact(/* fNegative= */ false); + (void)au256.GetCompact(/* fNegative= */ true); + (void)au256.getdouble(); + (void)au256.GetHex(); + (void)au256.GetLow64(); + (void)au256.size(); + (void)au256.ToString(); + + const CKeyID key_id{u160}; + const CScriptID script_id{u160}; + // CTxDestination = CNoDestination ∪ PKHash ∪ ScriptHash ∪ WitnessV0ScriptHash ∪ WitnessV0KeyHash ∪ WitnessUnknown + const PKHash pk_hash{u160}; + const ScriptHash script_hash{u160}; + const WitnessV0KeyHash witness_v0_key_hash{u160}; + const WitnessV0ScriptHash witness_v0_script_hash{u256}; + const std::vector<CTxDestination> destinations{pk_hash, script_hash, witness_v0_key_hash, witness_v0_script_hash}; + const SigningProvider store; + for (const CTxDestination& destination : destinations) { + (void)DescribeAddress(destination); + (void)EncodeDestination(destination); + (void)GetKeyForDestination(store, destination); + (void)GetScriptForDestination(destination); + (void)IsValidDestination(destination); + } +} diff --git a/src/test/fuzz/parse_hd_keypath.cpp b/src/test/fuzz/parse_hd_keypath.cpp new file mode 100644 index 0000000000..9a23f4b2d4 --- /dev/null +++ b/src/test/fuzz/parse_hd_keypath.cpp @@ -0,0 +1,13 @@ +// 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 <util/bip32.h> + +void test_one_input(const std::vector<uint8_t>& buffer) +{ + const std::string keypath_str(buffer.begin(), buffer.end()); + std::vector<uint32_t> keypath; + (void)ParseHDKeypath(keypath_str, keypath); +} diff --git a/src/test/fuzz/parse_numbers.cpp b/src/test/fuzz/parse_numbers.cpp new file mode 100644 index 0000000000..59f89dc9fb --- /dev/null +++ b/src/test/fuzz/parse_numbers.cpp @@ -0,0 +1,35 @@ +// 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 <util/moneystr.h> +#include <util/strencodings.h> + +#include <string> + +void test_one_input(const std::vector<uint8_t>& buffer) +{ + const std::string random_string(buffer.begin(), buffer.end()); + + CAmount amount; + (void)ParseMoney(random_string, amount); + + double d; + (void)ParseDouble(random_string, &d); + + int32_t i32; + (void)ParseInt32(random_string, &i32); + (void)atoi(random_string); + + uint32_t u32; + (void)ParseUInt32(random_string, &u32); + + int64_t i64; + (void)atoi64(random_string); + (void)ParseFixedPoint(random_string, 3, &i64); + (void)ParseInt64(random_string, &i64); + + uint64_t u64; + (void)ParseUInt64(random_string, &u64); +} diff --git a/src/test/fuzz/parse_script.cpp b/src/test/fuzz/parse_script.cpp new file mode 100644 index 0000000000..21ac1aecf3 --- /dev/null +++ b/src/test/fuzz/parse_script.cpp @@ -0,0 +1,16 @@ +// 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 <core_io.h> +#include <script/script.h> +#include <test/fuzz/fuzz.h> + +void test_one_input(const std::vector<uint8_t>& buffer) +{ + const std::string script_string(buffer.begin(), buffer.end()); + try { + (void)ParseScript(script_string); + } catch (const std::runtime_error&) { + } +} diff --git a/src/test/fuzz/parse_univalue.cpp b/src/test/fuzz/parse_univalue.cpp new file mode 100644 index 0000000000..3ad112dbad --- /dev/null +++ b/src/test/fuzz/parse_univalue.cpp @@ -0,0 +1,91 @@ +// 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 <chainparams.h> +#include <core_io.h> +#include <rpc/client.h> +#include <rpc/util.h> +#include <test/fuzz/fuzz.h> +#include <util/memory.h> + +#include <limits> +#include <string> + +void initialize() +{ + static const auto verify_handle = MakeUnique<ECCVerifyHandle>(); + SelectParams(CBaseChainParams::REGTEST); +} + +void test_one_input(const std::vector<uint8_t>& buffer) +{ + const std::string random_string(buffer.begin(), buffer.end()); + bool valid = true; + const UniValue univalue = [&] { + try { + return ParseNonRFCJSONValue(random_string); + } catch (const std::runtime_error&) { + valid = false; + return NullUniValue; + } + }(); + if (!valid) { + return; + } + try { + (void)ParseHashO(univalue, "A"); + (void)ParseHashO(univalue, random_string); + } catch (const UniValue&) { + } catch (const std::runtime_error&) { + } + try { + (void)ParseHashV(univalue, "A"); + (void)ParseHashV(univalue, random_string); + } catch (const UniValue&) { + } catch (const std::runtime_error&) { + } + try { + (void)ParseHexO(univalue, "A"); + (void)ParseHexO(univalue, random_string); + } catch (const UniValue&) { + } catch (const std::runtime_error&) { + } + try { + (void)ParseHexUV(univalue, "A"); + (void)ParseHexUV(univalue, random_string); + } catch (const UniValue&) { + } catch (const std::runtime_error&) { + } + try { + (void)ParseHexV(univalue, "A"); + (void)ParseHexV(univalue, random_string); + } catch (const UniValue&) { + } catch (const std::runtime_error&) { + } + try { + (void)ParseSighashString(univalue); + } catch (const std::runtime_error&) { + } + try { + (void)AmountFromValue(univalue); + } catch (const UniValue&) { + } catch (const std::runtime_error&) { + } + try { + FlatSigningProvider provider; + (void)EvalDescriptorStringOrObject(univalue, provider); + } catch (const UniValue&) { + } catch (const std::runtime_error&) { + } + try { + (void)ParseConfirmTarget(univalue, std::numeric_limits<unsigned int>::max()); + } catch (const UniValue&) { + } catch (const std::runtime_error&) { + } + try { + (void)ParseDescriptorRange(univalue); + } catch (const UniValue&) { + } catch (const std::runtime_error&) { + } +} diff --git a/src/test/fuzz/transaction.cpp b/src/test/fuzz/transaction.cpp index 76b230ef3c..fefafda36b 100644 --- a/src/test/fuzz/transaction.cpp +++ b/src/test/fuzz/transaction.cpp @@ -26,19 +26,31 @@ void test_one_input(const std::vector<uint8_t>& buffer) int nVersion; ds >> nVersion; ds.SetVersion(nVersion); - } catch (const std::ios_base::failure& e) { + } catch (const std::ios_base::failure&) { return; } - bool valid = true; + bool valid_tx = true; const CTransaction tx = [&] { try { return CTransaction(deserialize, ds); - } catch (const std::ios_base::failure& e) { - valid = false; + } catch (const std::ios_base::failure&) { + valid_tx = false; return CTransaction(); } }(); - if (!valid) { + bool valid_mutable_tx = true; + CDataStream ds_mtx(buffer, SER_NETWORK, INIT_PROTO_VERSION); + CMutableTransaction mutable_tx; + try { + int nVersion; + ds_mtx >> nVersion; + ds_mtx.SetVersion(nVersion); + ds_mtx >> mutable_tx; + } catch (const std::ios_base::failure&) { + valid_mutable_tx = false; + } + assert(valid_tx == valid_mutable_tx); + if (!valid_tx) { return; } diff --git a/src/test/fuzz/tx_in.cpp b/src/test/fuzz/tx_in.cpp new file mode 100644 index 0000000000..8e116537d1 --- /dev/null +++ b/src/test/fuzz/tx_in.cpp @@ -0,0 +1,33 @@ +// Copyright (c) 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 <consensus/validation.h> +#include <core_memusage.h> +#include <policy/policy.h> +#include <primitives/transaction.h> +#include <streams.h> +#include <test/fuzz/fuzz.h> +#include <version.h> + +#include <cassert> + +void test_one_input(const std::vector<uint8_t>& buffer) +{ + CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION); + CTxIn tx_in; + try { + int version; + ds >> version; + ds.SetVersion(version); + ds >> tx_in; + } catch (const std::ios_base::failure&) { + return; + } + + (void)GetTransactionInputWeight(tx_in); + (void)GetVirtualTransactionInputSize(tx_in); + (void)RecursiveDynamicUsage(tx_in); + + (void)tx_in.ToString(); +} diff --git a/src/test/fuzz/tx_out.cpp b/src/test/fuzz/tx_out.cpp new file mode 100644 index 0000000000..aa1338d5ba --- /dev/null +++ b/src/test/fuzz/tx_out.cpp @@ -0,0 +1,35 @@ +// Copyright (c) 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 <consensus/validation.h> +#include <core_memusage.h> +#include <policy/policy.h> +#include <primitives/transaction.h> +#include <streams.h> +#include <test/fuzz/fuzz.h> +#include <version.h> + +void test_one_input(const std::vector<uint8_t>& buffer) +{ + CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION); + CTxOut tx_out; + try { + int version; + ds >> version; + ds.SetVersion(version); + ds >> tx_out; + } catch (const std::ios_base::failure&) { + return; + } + + const CFeeRate dust_relay_fee{DUST_RELAY_TX_FEE}; + (void)GetDustThreshold(tx_out, dust_relay_fee); + (void)IsDust(tx_out, dust_relay_fee); + (void)RecursiveDynamicUsage(tx_out); + + (void)tx_out.ToString(); + (void)tx_out.IsNull(); + tx_out.SetNull(); + assert(tx_out.IsNull()); +} diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index eb0050a4a3..0939803953 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -713,6 +713,29 @@ BOOST_AUTO_TEST_CASE(test_IsStandard) t.vout[0].nValue = nDustThreshold; BOOST_CHECK(IsStandardTx(CTransaction(t), reason)); + // Disallowed nVersion + t.nVersion = -1; + reason.clear(); + BOOST_CHECK(!IsStandardTx(CTransaction(t), reason)); + BOOST_CHECK_EQUAL(reason, "version"); + + t.nVersion = 0; + reason.clear(); + BOOST_CHECK(!IsStandardTx(CTransaction(t), reason)); + BOOST_CHECK_EQUAL(reason, "version"); + + t.nVersion = 3; + reason.clear(); + BOOST_CHECK(!IsStandardTx(CTransaction(t), reason)); + BOOST_CHECK_EQUAL(reason, "version"); + + // Allowed nVersion + t.nVersion = 1; + BOOST_CHECK(IsStandardTx(CTransaction(t), reason)); + + t.nVersion = 2; + BOOST_CHECK(IsStandardTx(CTransaction(t), reason)); + // Check dust with odd relay fee to verify rounding: // nDustThreshold = 182 * 3702 / 1000 dustRelayFee = CFeeRate(3702); @@ -797,6 +820,17 @@ BOOST_AUTO_TEST_CASE(test_IsStandard) reason.clear(); BOOST_CHECK(!IsStandardTx(CTransaction(t), reason)); BOOST_CHECK_EQUAL(reason, "scriptsig-size"); + + // Check bare multisig (standard if policy flag fIsBareMultisigStd is set) + fIsBareMultisigStd = true; + t.vout[0].scriptPubKey = GetScriptForMultisig(1, {key.GetPubKey()}); // simple 1-of-1 + t.vin[0].scriptSig = CScript() << std::vector<unsigned char>(65, 0); + BOOST_CHECK(IsStandardTx(CTransaction(t), reason)); + + fIsBareMultisigStd = false; + reason.clear(); + BOOST_CHECK(!IsStandardTx(CTransaction(t), reason)); + BOOST_CHECK_EQUAL(reason, "bare-multisig"); } BOOST_AUTO_TEST_SUITE_END() |