Merge f1f3f2d9cc into merged_master (Bitcoin PR bitcoin/bitcoin#28815)

This commit is contained in:
Byron Hambly 2025-11-06 10:32:53 +02:00
commit 54f0d405f3
No known key found for this signature in database
GPG key ID: DE8F6EA20A661697
5 changed files with 60 additions and 28 deletions

View file

@ -3,18 +3,14 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <base58.h>
#include <core_io.h>
#include <key.h>
#include <key_io.h>
#include <node/context.h>
#include <primitives/block.h>
#include <primitives/transaction.h>
#include <psbt.h>
#include <rpc/blockchain.h>
#include <rpc/client.h>
#include <rpc/request.h>
#include <rpc/server.h>
#include <rpc/util.h>
#include <span.h>
#include <streams.h>
#include <test/fuzz/FuzzedDataProvider.h>
@ -22,19 +18,23 @@
#include <test/fuzz/util.h>
#include <test/util/setup_common.h>
#include <tinyformat.h>
#include <uint256.h>
#include <univalue.h>
#include <util/chaintype.h>
#include <util/strencodings.h>
#include <util/string.h>
#include <util/time.h>
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <cstdlib>
#include <exception>
#include <iostream>
#include <memory>
#include <optional>
#include <stdexcept>
#include <string>
#include <vector>
enum class ChainType;
namespace {
struct RPCFuzzTestingSetup : public TestingSetup {
@ -206,7 +206,7 @@ const std::vector<std::string> RPC_COMMANDS_SAFE_FOR_FUZZING{
"updatepsbtpegin",
};
std::string ConsumeScalarRPCArgument(FuzzedDataProvider& fuzzed_data_provider)
std::string ConsumeScalarRPCArgument(FuzzedDataProvider& fuzzed_data_provider, bool& good_data)
{
const size_t max_string_length = 4096;
const size_t max_base58_bytes_length{64};
@ -273,6 +273,7 @@ std::string ConsumeScalarRPCArgument(FuzzedDataProvider& fuzzed_data_provider)
// hex encoded block
std::optional<CBlock> opt_block = ConsumeDeserializable<CBlock>(fuzzed_data_provider);
if (!opt_block) {
good_data = false;
return;
}
CDataStream data_stream{SER_NETWORK, PROTOCOL_VERSION};
@ -283,6 +284,7 @@ std::string ConsumeScalarRPCArgument(FuzzedDataProvider& fuzzed_data_provider)
// hex encoded block header
std::optional<CBlockHeader> opt_block_header = ConsumeDeserializable<CBlockHeader>(fuzzed_data_provider);
if (!opt_block_header) {
good_data = false;
return;
}
CDataStream data_stream{SER_NETWORK, INIT_PROTO_VERSION};
@ -293,6 +295,7 @@ std::string ConsumeScalarRPCArgument(FuzzedDataProvider& fuzzed_data_provider)
// hex encoded tx
std::optional<CMutableTransaction> opt_tx = ConsumeDeserializable<CMutableTransaction>(fuzzed_data_provider);
if (!opt_tx) {
good_data = false;
return;
}
CDataStream data_stream{SER_NETWORK, fuzzed_data_provider.ConsumeBool() ? PROTOCOL_VERSION : (PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS)};
@ -303,6 +306,7 @@ std::string ConsumeScalarRPCArgument(FuzzedDataProvider& fuzzed_data_provider)
// base64 encoded psbt
std::optional<PartiallySignedTransaction> opt_psbt = ConsumeDeserializable<PartiallySignedTransaction>(fuzzed_data_provider);
if (!opt_psbt) {
good_data = false;
return;
}
CDataStream data_stream{SER_NETWORK, PROTOCOL_VERSION};
@ -313,6 +317,7 @@ std::string ConsumeScalarRPCArgument(FuzzedDataProvider& fuzzed_data_provider)
// base58 encoded key
CKey key = ConsumePrivateKey(fuzzed_data_provider);
if (!key.IsValid()) {
good_data = false;
return;
}
r = EncodeSecret(key);
@ -321,6 +326,7 @@ std::string ConsumeScalarRPCArgument(FuzzedDataProvider& fuzzed_data_provider)
// hex encoded pubkey
CKey key = ConsumePrivateKey(fuzzed_data_provider);
if (!key.IsValid()) {
good_data = false;
return;
}
r = HexStr(key.GetPubKey());
@ -328,18 +334,19 @@ std::string ConsumeScalarRPCArgument(FuzzedDataProvider& fuzzed_data_provider)
return r;
}
std::string ConsumeArrayRPCArgument(FuzzedDataProvider& fuzzed_data_provider)
std::string ConsumeArrayRPCArgument(FuzzedDataProvider& fuzzed_data_provider, bool& good_data)
{
std::vector<std::string> scalar_arguments;
LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 100) {
scalar_arguments.push_back(ConsumeScalarRPCArgument(fuzzed_data_provider));
LIMITED_WHILE(good_data && fuzzed_data_provider.ConsumeBool(), 100)
{
scalar_arguments.push_back(ConsumeScalarRPCArgument(fuzzed_data_provider, good_data));
}
return "[\"" + Join(scalar_arguments, "\",\"") + "\"]";
}
std::string ConsumeRPCArgument(FuzzedDataProvider& fuzzed_data_provider)
std::string ConsumeRPCArgument(FuzzedDataProvider& fuzzed_data_provider, bool& good_data)
{
return fuzzed_data_provider.ConsumeBool() ? ConsumeScalarRPCArgument(fuzzed_data_provider) : ConsumeArrayRPCArgument(fuzzed_data_provider);
return fuzzed_data_provider.ConsumeBool() ? ConsumeScalarRPCArgument(fuzzed_data_provider, good_data) : ConsumeArrayRPCArgument(fuzzed_data_provider, good_data);
}
RPCFuzzTestingSetup* InitializeRPCFuzzTestingSetup()
@ -375,6 +382,7 @@ void initialize_rpc()
FUZZ_TARGET(rpc, .init = initialize_rpc)
{
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
bool good_data{true};
SetMockTime(ConsumeTime(fuzzed_data_provider));
const std::string rpc_command = fuzzed_data_provider.ConsumeRandomLengthString(64);
if (!g_limit_to_rpc_command.empty() && rpc_command != g_limit_to_rpc_command) {
@ -385,8 +393,9 @@ FUZZ_TARGET(rpc, .init = initialize_rpc)
return;
}
std::vector<std::string> arguments;
LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 100) {
arguments.push_back(ConsumeRPCArgument(fuzzed_data_provider));
LIMITED_WHILE(good_data && fuzzed_data_provider.ConsumeBool(), 100)
{
arguments.push_back(ConsumeRPCArgument(fuzzed_data_provider, good_data));
}
try {
rpc_testing_setup->CallRPC(rpc_command, arguments);