diff options
Diffstat (limited to 'src/test')
-rw-r--r-- | src/test/denialofservice_tests.cpp | 1 | ||||
-rw-r--r-- | src/test/fuzz/addition_overflow.cpp | 55 | ||||
-rw-r--r-- | src/test/fuzz/checkqueue.cpp | 65 | ||||
-rw-r--r-- | src/test/fuzz/cuckoocache.cpp | 49 | ||||
-rw-r--r-- | src/test/fuzz/fees.cpp | 26 | ||||
-rw-r--r-- | src/test/fuzz/integer.cpp | 16 | ||||
-rw-r--r-- | src/test/fuzz/process_message.cpp | 2 | ||||
-rw-r--r-- | src/test/fuzz/util.h | 11 | ||||
-rw-r--r-- | src/test/gen/crypto_gen.cpp | 19 | ||||
-rw-r--r-- | src/test/gen/crypto_gen.h | 63 | ||||
-rw-r--r-- | src/test/key_properties.cpp | 48 | ||||
-rw-r--r-- | src/test/validationinterface_tests.cpp | 60 |
12 files changed, 281 insertions, 134 deletions
diff --git a/src/test/denialofservice_tests.cpp b/src/test/denialofservice_tests.cpp index 7310498eb6..6314c1a42f 100644 --- a/src/test/denialofservice_tests.cpp +++ b/src/test/denialofservice_tests.cpp @@ -52,7 +52,6 @@ struct COrphanTx { NodeId fromPeer; int64_t nTimeExpire; }; -extern RecursiveMutex g_cs_orphans; extern std::map<uint256, COrphanTx> mapOrphanTransactions GUARDED_BY(g_cs_orphans); static CService ip(uint32_t i) diff --git a/src/test/fuzz/addition_overflow.cpp b/src/test/fuzz/addition_overflow.cpp new file mode 100644 index 0000000000..a455992b13 --- /dev/null +++ b/src/test/fuzz/addition_overflow.cpp @@ -0,0 +1,55 @@ +// Copyright (c) 2020 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/FuzzedDataProvider.h> +#include <test/fuzz/fuzz.h> +#include <test/fuzz/util.h> + +#include <cstdint> +#include <string> +#include <vector> + +#if defined(__has_builtin) +#if __has_builtin(__builtin_add_overflow) +#define HAVE_BUILTIN_ADD_OVERFLOW +#endif +#elif defined(__GNUC__) && (__GNUC__ >= 5) +#define HAVE_BUILTIN_ADD_OVERFLOW +#endif + +namespace { +template <typename T> +void TestAdditionOverflow(FuzzedDataProvider& fuzzed_data_provider) +{ + const T i = fuzzed_data_provider.ConsumeIntegral<T>(); + const T j = fuzzed_data_provider.ConsumeIntegral<T>(); + const bool is_addition_overflow_custom = AdditionOverflow(i, j); +#if defined(HAVE_BUILTIN_ADD_OVERFLOW) + T result_builtin; + const bool is_addition_overflow_builtin = __builtin_add_overflow(i, j, &result_builtin); + assert(is_addition_overflow_custom == is_addition_overflow_builtin); + if (!is_addition_overflow_custom) { + assert(i + j == result_builtin); + } +#else + if (!is_addition_overflow_custom) { + (void)(i + j); + } +#endif +} +} // namespace + +void test_one_input(const std::vector<uint8_t>& buffer) +{ + FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); + TestAdditionOverflow<int64_t>(fuzzed_data_provider); + TestAdditionOverflow<uint64_t>(fuzzed_data_provider); + TestAdditionOverflow<int32_t>(fuzzed_data_provider); + TestAdditionOverflow<uint32_t>(fuzzed_data_provider); + TestAdditionOverflow<int16_t>(fuzzed_data_provider); + TestAdditionOverflow<uint16_t>(fuzzed_data_provider); + TestAdditionOverflow<char>(fuzzed_data_provider); + TestAdditionOverflow<unsigned char>(fuzzed_data_provider); + TestAdditionOverflow<signed char>(fuzzed_data_provider); +} diff --git a/src/test/fuzz/checkqueue.cpp b/src/test/fuzz/checkqueue.cpp new file mode 100644 index 0000000000..2ed097b827 --- /dev/null +++ b/src/test/fuzz/checkqueue.cpp @@ -0,0 +1,65 @@ +// Copyright (c) 2020 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 <checkqueue.h> +#include <optional.h> +#include <test/fuzz/FuzzedDataProvider.h> +#include <test/fuzz/fuzz.h> +#include <test/fuzz/util.h> + +#include <cstdint> +#include <string> +#include <vector> + +namespace { +struct DumbCheck { + const bool result = false; + + DumbCheck() = default; + + explicit DumbCheck(const bool _result) : result(_result) + { + } + + bool operator()() const + { + return result; + } + + void swap(DumbCheck& x) + { + } +}; +} // namespace + +void test_one_input(const std::vector<uint8_t>& buffer) +{ + FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); + + const unsigned int batch_size = fuzzed_data_provider.ConsumeIntegralInRange<unsigned int>(0, 1024); + CCheckQueue<DumbCheck> check_queue_1{batch_size}; + CCheckQueue<DumbCheck> check_queue_2{batch_size}; + std::vector<DumbCheck> checks_1; + std::vector<DumbCheck> checks_2; + const int size = fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 1024); + for (int i = 0; i < size; ++i) { + const bool result = fuzzed_data_provider.ConsumeBool(); + checks_1.emplace_back(result); + checks_2.emplace_back(result); + } + if (fuzzed_data_provider.ConsumeBool()) { + check_queue_1.Add(checks_1); + } + if (fuzzed_data_provider.ConsumeBool()) { + (void)check_queue_1.Wait(); + } + + CCheckQueueControl<DumbCheck> check_queue_control{&check_queue_2}; + if (fuzzed_data_provider.ConsumeBool()) { + check_queue_control.Add(checks_2); + } + if (fuzzed_data_provider.ConsumeBool()) { + (void)check_queue_control.Wait(); + } +} diff --git a/src/test/fuzz/cuckoocache.cpp b/src/test/fuzz/cuckoocache.cpp new file mode 100644 index 0000000000..f674efe1b1 --- /dev/null +++ b/src/test/fuzz/cuckoocache.cpp @@ -0,0 +1,49 @@ +// Copyright (c) 2020 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 <cuckoocache.h> +#include <optional.h> +#include <script/sigcache.h> +#include <test/fuzz/FuzzedDataProvider.h> +#include <test/fuzz/fuzz.h> +#include <test/fuzz/util.h> +#include <test/util/setup_common.h> + +#include <cstdint> +#include <string> +#include <vector> + +namespace { +FuzzedDataProvider* fuzzed_data_provider_ptr = nullptr; + +struct RandomHasher { + template <uint8_t> + uint32_t operator()(const bool& /* unused */) const + { + assert(fuzzed_data_provider_ptr != nullptr); + return fuzzed_data_provider_ptr->ConsumeIntegral<uint32_t>(); + } +}; +} // namespace + +void test_one_input(const std::vector<uint8_t>& buffer) +{ + FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); + fuzzed_data_provider_ptr = &fuzzed_data_provider; + CuckooCache::cache<bool, RandomHasher> cuckoo_cache{}; + if (fuzzed_data_provider.ConsumeBool()) { + const size_t megabytes = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 16); + cuckoo_cache.setup_bytes(megabytes << 20); + } else { + cuckoo_cache.setup(fuzzed_data_provider.ConsumeIntegralInRange<uint32_t>(0, 4096)); + } + while (fuzzed_data_provider.ConsumeBool()) { + if (fuzzed_data_provider.ConsumeBool()) { + cuckoo_cache.insert(fuzzed_data_provider.ConsumeBool()); + } else { + cuckoo_cache.contains(fuzzed_data_provider.ConsumeBool(), fuzzed_data_provider.ConsumeBool()); + } + } + fuzzed_data_provider_ptr = nullptr; +} diff --git a/src/test/fuzz/fees.cpp b/src/test/fuzz/fees.cpp new file mode 100644 index 0000000000..090994263e --- /dev/null +++ b/src/test/fuzz/fees.cpp @@ -0,0 +1,26 @@ +// Copyright (c) 2020 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 <amount.h> +#include <optional.h> +#include <policy/fees.h> +#include <test/fuzz/FuzzedDataProvider.h> +#include <test/fuzz/fuzz.h> +#include <test/fuzz/util.h> + +#include <cstdint> +#include <string> +#include <vector> + +void test_one_input(const std::vector<uint8_t>& buffer) +{ + FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); + const CFeeRate minimal_incremental_fee{ConsumeMoney(fuzzed_data_provider)}; + FeeFilterRounder fee_filter_rounder{minimal_incremental_fee}; + while (fuzzed_data_provider.ConsumeBool()) { + const CAmount current_minimum_fee = ConsumeMoney(fuzzed_data_provider); + const CAmount rounded_fee = fee_filter_rounder.round(current_minimum_fee); + assert(MoneyRange(rounded_fee)); + } +} diff --git a/src/test/fuzz/integer.cpp b/src/test/fuzz/integer.cpp index fff2fabd17..7c2537aaf5 100644 --- a/src/test/fuzz/integer.cpp +++ b/src/test/fuzz/integer.cpp @@ -23,6 +23,7 @@ #include <streams.h> #include <test/fuzz/FuzzedDataProvider.h> #include <test/fuzz/fuzz.h> +#include <test/fuzz/util.h> #include <time.h> #include <uint256.h> #include <util/moneystr.h> @@ -35,6 +36,7 @@ #include <cassert> #include <chrono> #include <limits> +#include <set> #include <vector> void initialize() @@ -90,8 +92,12 @@ void test_one_input(const std::vector<uint8_t>& buffer) } (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 + if (!MultiplicationOverflow(i64, static_cast<int64_t>(::nBytesPerSigOp)) && !AdditionOverflow(i64 * ::nBytesPerSigOp, static_cast<int64_t>(4))) { + (void)GetVirtualTransactionSize(i64, i64); + } + if (!MultiplicationOverflow(i64, static_cast<int64_t>(u32)) && !AdditionOverflow(i64, static_cast<int64_t>(4)) && !AdditionOverflow(i64 * u32, static_cast<int64_t>(4))) { + (void)GetVirtualTransactionSize(i64, i64, u32); + } (void)HexDigit(ch); (void)MoneyRange(i64); (void)ToString(i64); @@ -109,6 +115,12 @@ void test_one_input(const std::vector<uint8_t>& buffer) (void)memusage::DynamicUsage(u8); const unsigned char uch = static_cast<unsigned char>(u8); (void)memusage::DynamicUsage(uch); + { + const std::set<int64_t> i64s{i64, static_cast<int64_t>(u64)}; + const size_t dynamic_usage = memusage::DynamicUsage(i64s); + const size_t incremental_dynamic_usage = memusage::IncrementalDynamicUsage(i64s); + assert(dynamic_usage == incremental_dynamic_usage * i64s.size()); + } (void)MillisToTimeval(i64); const double d = ser_uint64_to_double(u64); assert(ser_double_to_uint64(d) == u64); diff --git a/src/test/fuzz/process_message.cpp b/src/test/fuzz/process_message.cpp index dc49dd499a..9e3586d162 100644 --- a/src/test/fuzz/process_message.cpp +++ b/src/test/fuzz/process_message.cpp @@ -32,7 +32,7 @@ #include <string> #include <vector> -bool ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, int64_t nTimeReceived, const CChainParams& chainparams, CTxMemPool& mempool, CConnman* connman, BanMan* banman, const std::atomic<bool>& interruptMsgProc); +bool ProcessMessage(CNode* pfrom, const std::string& msg_type, CDataStream& vRecv, int64_t nTimeReceived, const CChainParams& chainparams, CTxMemPool& mempool, CConnman* connman, BanMan* banman, const std::atomic<bool>& interruptMsgProc); namespace { diff --git a/src/test/fuzz/util.h b/src/test/fuzz/util.h index b70ea6d90e..ba4b012f95 100644 --- a/src/test/fuzz/util.h +++ b/src/test/fuzz/util.h @@ -120,4 +120,15 @@ NODISCARD bool MultiplicationOverflow(const T i, const T j) noexcept } } +template <class T> +NODISCARD bool AdditionOverflow(const T i, const T j) noexcept +{ + static_assert(std::is_integral<T>::value, "Integral required."); + if (std::numeric_limits<T>::is_signed) { + return (i > 0 && j > std::numeric_limits<T>::max() - i) || + (i < 0 && j < std::numeric_limits<T>::min() - i); + } + return std::numeric_limits<T>::max() - i < j; +} + #endif // BITCOIN_TEST_FUZZ_UTIL_H diff --git a/src/test/gen/crypto_gen.cpp b/src/test/gen/crypto_gen.cpp deleted file mode 100644 index ca8c65806f..0000000000 --- a/src/test/gen/crypto_gen.cpp +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) 2018 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/gen/crypto_gen.h> - -#include <key.h> - -#include <rapidcheck/gen/Arbitrary.h> -#include <rapidcheck/Gen.h> -#include <rapidcheck/gen/Predicate.h> -#include <rapidcheck/gen/Container.h> - -/** Generates 1 to 20 keys for OP_CHECKMULTISIG */ -rc::Gen<std::vector<CKey>> MultisigKeys() -{ - return rc::gen::suchThat(rc::gen::arbitrary<std::vector<CKey>>(), [](const std::vector<CKey>& keys) { - return keys.size() >= 1 && keys.size() <= 15; - }); -}; diff --git a/src/test/gen/crypto_gen.h b/src/test/gen/crypto_gen.h deleted file mode 100644 index 7c2fb0350f..0000000000 --- a/src/test/gen/crypto_gen.h +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (c) 2018 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_GEN_CRYPTO_GEN_H -#define BITCOIN_TEST_GEN_CRYPTO_GEN_H - -#include <key.h> -#include <random.h> -#include <uint256.h> -#include <rapidcheck/gen/Arbitrary.h> -#include <rapidcheck/Gen.h> -#include <rapidcheck/gen/Create.h> -#include <rapidcheck/gen/Numeric.h> - -/** Generates 1 to 15 keys for OP_CHECKMULTISIG */ -rc::Gen<std::vector<CKey>> MultisigKeys(); - -namespace rc -{ -/** Generator for a new CKey */ -template <> -struct Arbitrary<CKey> { - static Gen<CKey> arbitrary() - { - return rc::gen::map<int>([](int x) { - CKey key; - key.MakeNewKey(true); - return key; - }); - }; -}; - -/** Generator for a CPrivKey */ -template <> -struct Arbitrary<CPrivKey> { - static Gen<CPrivKey> arbitrary() - { - return gen::map(gen::arbitrary<CKey>(), [](const CKey& key) { - return key.GetPrivKey(); - }); - }; -}; - -/** Generator for a new CPubKey */ -template <> -struct Arbitrary<CPubKey> { - static Gen<CPubKey> arbitrary() - { - return gen::map(gen::arbitrary<CKey>(), [](const CKey& key) { - return key.GetPubKey(); - }); - }; -}; -/** Generates a arbitrary uint256 */ -template <> -struct Arbitrary<uint256> { - static Gen<uint256> arbitrary() - { - return rc::gen::just(GetRandHash()); - }; -}; -} //namespace rc -#endif diff --git a/src/test/key_properties.cpp b/src/test/key_properties.cpp deleted file mode 100644 index 0e45a2549d..0000000000 --- a/src/test/key_properties.cpp +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) 2018-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 <key.h> - -#include <uint256.h> -#include <test/util/setup_common.h> -#include <vector> - -#include <boost/test/unit_test.hpp> -#include <rapidcheck/boost_test.h> -#include <rapidcheck/gen/Arbitrary.h> -#include <rapidcheck/Gen.h> - -#include <test/gen/crypto_gen.h> - -BOOST_FIXTURE_TEST_SUITE(key_properties, BasicTestingSetup) - -/** Check CKey uniqueness */ -RC_BOOST_PROP(key_uniqueness, (const CKey& key1, const CKey& key2)) -{ - RC_ASSERT(!(key1 == key2)); -} - -/** Verify that a private key generates the correct public key */ -RC_BOOST_PROP(key_generates_correct_pubkey, (const CKey& key)) -{ - CPubKey pubKey = key.GetPubKey(); - RC_ASSERT(key.VerifyPubKey(pubKey)); -} - -/** Create a CKey using the 'Set' function must give us the same key */ -RC_BOOST_PROP(key_set_symmetry, (const CKey& key)) -{ - CKey key1; - key1.Set(key.begin(), key.end(), key.IsCompressed()); - RC_ASSERT(key1 == key); -} - -/** Create a CKey, sign a piece of data, then verify it with the public key */ -RC_BOOST_PROP(key_sign_symmetry, (const CKey& key, const uint256& hash)) -{ - std::vector<unsigned char> vchSig; - key.Sign(hash, vchSig, 0); - const CPubKey& pubKey = key.GetPubKey(); - RC_ASSERT(pubKey.Verify(hash, vchSig)); -} -BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/validationinterface_tests.cpp b/src/test/validationinterface_tests.cpp new file mode 100644 index 0000000000..208be92852 --- /dev/null +++ b/src/test/validationinterface_tests.cpp @@ -0,0 +1,60 @@ +// Copyright (c) 2020 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 <boost/test/unit_test.hpp> +#include <consensus/validation.h> +#include <primitives/block.h> +#include <scheduler.h> +#include <test/util/setup_common.h> +#include <util/check.h> +#include <validationinterface.h> + +BOOST_FIXTURE_TEST_SUITE(validationinterface_tests, TestingSetup) + +class TestInterface : public CValidationInterface +{ +public: + TestInterface(std::function<void()> on_call = nullptr, std::function<void()> on_destroy = nullptr) + : m_on_call(std::move(on_call)), m_on_destroy(std::move(on_destroy)) + { + } + virtual ~TestInterface() + { + if (m_on_destroy) m_on_destroy(); + } + void BlockChecked(const CBlock& block, const BlockValidationState& state) override + { + if (m_on_call) m_on_call(); + } + static void Call() + { + CBlock block; + BlockValidationState state; + GetMainSignals().BlockChecked(block, state); + } + std::function<void()> m_on_call; + std::function<void()> m_on_destroy; +}; + +// Regression test to ensure UnregisterAllValidationInterfaces calls don't +// destroy a validation interface while it is being called. Bug: +// https://github.com/bitcoin/bitcoin/pull/18551 +BOOST_AUTO_TEST_CASE(unregister_all_during_call) +{ + bool destroyed = false; + RegisterSharedValidationInterface(std::make_shared<TestInterface>( + [&] { + // First call should decrements reference count 2 -> 1 + UnregisterAllValidationInterfaces(); + BOOST_CHECK(!destroyed); + // Second call should not decrement reference count 1 -> 0 + UnregisterAllValidationInterfaces(); + BOOST_CHECK(!destroyed); + }, + [&] { destroyed = true; })); + TestInterface::Call(); + BOOST_CHECK(destroyed); +} + +BOOST_AUTO_TEST_SUITE_END() |