diff options
Diffstat (limited to 'src/test')
-rw-r--r-- | src/test/fuzz/descriptor_parse.cpp | 7 | ||||
-rw-r--r-- | src/test/fuzz/pow.cpp | 81 | ||||
-rw-r--r-- | src/test/fuzz/script.cpp | 30 | ||||
-rw-r--r-- | src/test/fuzz/util.h | 6 |
4 files changed, 119 insertions, 5 deletions
diff --git a/src/test/fuzz/descriptor_parse.cpp b/src/test/fuzz/descriptor_parse.cpp index a0ef08cca6..1e0abe94f8 100644 --- a/src/test/fuzz/descriptor_parse.cpp +++ b/src/test/fuzz/descriptor_parse.cpp @@ -20,6 +20,11 @@ void test_one_input(const std::vector<uint8_t>& buffer) FlatSigningProvider signing_provider; std::string error; for (const bool require_checksum : {true, false}) { - Parse(descriptor, signing_provider, error, require_checksum); + const auto desc = Parse(descriptor, signing_provider, error, require_checksum); + if (desc) { + (void)desc->ToString(); + (void)desc->IsRange(); + (void)desc->IsSolvable(); + } } } diff --git a/src/test/fuzz/pow.cpp b/src/test/fuzz/pow.cpp new file mode 100644 index 0000000000..0343d33401 --- /dev/null +++ b/src/test/fuzz/pow.cpp @@ -0,0 +1,81 @@ +// 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 <chain.h> +#include <chainparams.h> +#include <optional.h> +#include <pow.h> +#include <primitives/block.h> +#include <test/fuzz/FuzzedDataProvider.h> +#include <test/fuzz/fuzz.h> +#include <test/fuzz/util.h> + +#include <cstdint> +#include <string> +#include <vector> + +void initialize() +{ + SelectParams(CBaseChainParams::MAIN); +} + +void test_one_input(const std::vector<uint8_t>& buffer) +{ + FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); + const Consensus::Params& consensus_params = Params().GetConsensus(); + std::vector<CBlockIndex> blocks; + const uint32_t fixed_time = fuzzed_data_provider.ConsumeIntegral<uint32_t>(); + const uint32_t fixed_bits = fuzzed_data_provider.ConsumeIntegral<uint32_t>(); + while (fuzzed_data_provider.remaining_bytes() > 0) { + const Optional<CBlockHeader> block_header = ConsumeDeserializable<CBlockHeader>(fuzzed_data_provider); + if (!block_header) { + continue; + } + CBlockIndex current_block{*block_header}; + { + CBlockIndex* previous_block = !blocks.empty() ? &blocks[fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, blocks.size() - 1)] : nullptr; + const int current_height = (previous_block != nullptr && previous_block->nHeight != std::numeric_limits<int>::max()) ? previous_block->nHeight + 1 : 0; + if (fuzzed_data_provider.ConsumeBool()) { + current_block.pprev = previous_block; + } + if (fuzzed_data_provider.ConsumeBool()) { + current_block.nHeight = current_height; + } + if (fuzzed_data_provider.ConsumeBool()) { + current_block.nTime = fixed_time + current_height * consensus_params.nPowTargetSpacing; + } + if (fuzzed_data_provider.ConsumeBool()) { + current_block.nBits = fixed_bits; + } + if (fuzzed_data_provider.ConsumeBool()) { + current_block.nChainWork = previous_block != nullptr ? previous_block->nChainWork + GetBlockProof(*previous_block) : arith_uint256{0}; + } else { + current_block.nChainWork = ConsumeArithUInt256(fuzzed_data_provider); + } + blocks.push_back(current_block); + } + { + (void)GetBlockProof(current_block); + (void)CalculateNextWorkRequired(¤t_block, fuzzed_data_provider.ConsumeIntegralInRange<int64_t>(0, std::numeric_limits<int64_t>::max()), consensus_params); + if (current_block.nHeight != std::numeric_limits<int>::max() && current_block.nHeight - (consensus_params.DifficultyAdjustmentInterval() - 1) >= 0) { + (void)GetNextWorkRequired(¤t_block, &(*block_header), consensus_params); + } + } + { + const CBlockIndex* to = &blocks[fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, blocks.size() - 1)]; + const CBlockIndex* from = &blocks[fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, blocks.size() - 1)]; + const CBlockIndex* tip = &blocks[fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, blocks.size() - 1)]; + try { + (void)GetBlockProofEquivalentTime(*to, *from, *tip, consensus_params); + } catch (const uint_error&) { + } + } + { + const Optional<uint256> hash = ConsumeDeserializable<uint256>(fuzzed_data_provider); + if (hash) { + (void)CheckProofOfWork(*hash, fuzzed_data_provider.ConsumeIntegral<unsigned int>(), consensus_params); + } + } + } +} diff --git a/src/test/fuzz/script.cpp b/src/test/fuzz/script.cpp index 2f50f1b838..80e2f234d7 100644 --- a/src/test/fuzz/script.cpp +++ b/src/test/fuzz/script.cpp @@ -9,6 +9,7 @@ #include <policy/policy.h> #include <pubkey.h> #include <script/descriptor.h> +#include <script/interpreter.h> #include <script/script.h> #include <script/sign.h> #include <script/signingprovider.h> @@ -30,7 +31,10 @@ void initialize() void test_one_input(const std::vector<uint8_t>& buffer) { - const CScript script(buffer.begin(), buffer.end()); + FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); + const Optional<CScript> script_opt = ConsumeDeserializable<CScript>(fuzzed_data_provider); + if (!script_opt) return; + const CScript script{*script_opt}; std::vector<unsigned char> compressed; if (CompressScript(script, compressed)) { @@ -89,12 +93,30 @@ void test_one_input(const std::vector<uint8_t>& buffer) ScriptToUniv(script, o4, false); { - FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); const std::vector<uint8_t> bytes = ConsumeRandomLengthByteVector(fuzzed_data_provider); - // DecompressScript(..., ..., bytes) is not guaranteed to be defined if bytes.size() <= 23. - if (bytes.size() >= 24) { + // DecompressScript(..., ..., bytes) is not guaranteed to be defined if the bytes vector is too short + if (bytes.size() >= 32) { CScript decompressed_script; DecompressScript(decompressed_script, fuzzed_data_provider.ConsumeIntegral<unsigned int>(), bytes); } } + + const Optional<CScript> other_script = ConsumeDeserializable<CScript>(fuzzed_data_provider); + if (other_script) { + { + CScript script_mut{script}; + (void)FindAndDelete(script_mut, *other_script); + } + const std::vector<std::string> random_string_vector = ConsumeRandomLengthStringVector(fuzzed_data_provider); + const uint32_t u32{fuzzed_data_provider.ConsumeIntegral<uint32_t>()}; + const uint32_t flags{u32 | SCRIPT_VERIFY_P2SH}; + { + CScriptWitness wit; + for (const auto& s : random_string_vector) { + wit.stack.emplace_back(s.begin(), s.end()); + } + (void)CountWitnessSigOps(script, *other_script, &wit, flags); + wit.SetNull(); + } + } } diff --git a/src/test/fuzz/util.h b/src/test/fuzz/util.h index 7004aff420..b70ea6d90e 100644 --- a/src/test/fuzz/util.h +++ b/src/test/fuzz/util.h @@ -6,6 +6,7 @@ #define BITCOIN_TEST_FUZZ_UTIL_H #include <amount.h> +#include <arith_uint256.h> #include <attributes.h> #include <optional.h> #include <script/script.h> @@ -91,6 +92,11 @@ NODISCARD inline uint256 ConsumeUInt256(FuzzedDataProvider& fuzzed_data_provider return uint256{v256}; } +NODISCARD inline arith_uint256 ConsumeArithUInt256(FuzzedDataProvider& fuzzed_data_provider) noexcept +{ + return UintToArith256(ConsumeUInt256(fuzzed_data_provider)); +} + template <typename T> NODISCARD bool MultiplicationOverflow(const T i, const T j) noexcept { |