Merge bitcoin/bitcoin#31917: fuzz: provide more realistic values to the base58(check) decoders

d5537c18a9034647ba4c9ed4008abd7fee33989e fuzz: make sure DecodeBase58(Check) is called with valid values more often (Lőrinc)
bad1433ef2b5b02ac4b1c6c1d9482c513e5b2192 fuzz: Always restrict base conversion input lengths (Lőrinc)

Pull request description:

  This is a follow-up to https://github.com/bitcoin/bitcoin/pull/30746, expanding coverage by:
  * restricting every input for the base58 conversions, capping max sizes to `100` instead of `1000` or all available input (suggested by marcofleon in https://github.com/bitcoin/bitcoin/pull/30746#discussion_r1963718683) since most actual usage has lengths of e.g. `21`, `34`, `78`.
  * providing more valid values to the decoder (suggested by maflcko in https://github.com/bitcoin/bitcoin/pull/30746#discussion_r1957847712) by randomly providing a random input or a valid encoded one; this also enables unifying the roundtrip tests to a single roundtrip per fuzz.

ACKs for top commit:
  mzumsande:
    Code Review / lightly tested ACK d5537c18a9034647ba4c9ed4008abd7fee33989e
  maflcko:
    review ACK d5537c18a9034647ba4c9ed4008abd7fee33989e 🚛

Tree-SHA512: 50365654cdac8a38708a7475eaa43396642b7337e2ee8999374c3faafff4f05457abc1a54c701211e0ed24d36c12af77bcad17b49695699be42664f2be660659
This commit is contained in:
merge-script 2025-03-16 17:02:58 +08:00
commit ab2df1726e
No known key found for this signature in database
GPG Key ID: 2EEB9F5CC09526C1

View File

@ -6,6 +6,7 @@
#include <base58.h>
#include <psbt.h>
#include <span.h>
#include <test/fuzz/FuzzedDataProvider.h>
#include <util/strencodings.h>
#include <util/string.h>
@ -19,42 +20,40 @@ using util::TrimStringView;
FUZZ_TARGET(base58_encode_decode)
{
FuzzedDataProvider provider(buffer.data(), buffer.size());
const std::string random_string{provider.ConsumeRandomLengthString(1000)};
const int max_ret_len{provider.ConsumeIntegralInRange<int>(-1, 1000)};
FuzzedDataProvider provider{buffer.data(), buffer.size()};
const auto random_string{provider.ConsumeRandomLengthString(100)};
// Decode/Encode roundtrip
std::vector<unsigned char> decoded;
if (DecodeBase58(random_string, decoded, max_ret_len)) {
const auto encoded{EncodeBase58(MakeUCharSpan(random_string))};
const auto decode_input{provider.ConsumeBool() ? random_string : encoded};
const int max_ret_len{provider.ConsumeIntegralInRange<int>(-1, decode_input.size() + 1)};
if (std::vector<unsigned char> decoded; DecodeBase58(decode_input, decoded, max_ret_len)) {
const auto encoded_string{EncodeBase58(decoded)};
assert(encoded_string == TrimStringView(random_string));
assert(encoded_string.empty() || !DecodeBase58(encoded_string, decoded, provider.ConsumeIntegralInRange<int>(0, decoded.size() - 1)));
assert(encoded_string == TrimStringView(decode_input));
if (decoded.size() > 0) {
assert(max_ret_len > 0);
assert(decoded.size() <= static_cast<size_t>(max_ret_len));
assert(!DecodeBase58(encoded_string, decoded, provider.ConsumeIntegralInRange<int>(0, decoded.size() - 1)));
}
}
// Encode/Decode roundtrip
const auto encoded{EncodeBase58(buffer)};
std::vector<unsigned char> roundtrip_decoded;
assert(DecodeBase58(encoded, roundtrip_decoded, buffer.size())
&& std::ranges::equal(roundtrip_decoded, buffer));
}
FUZZ_TARGET(base58check_encode_decode)
{
FuzzedDataProvider provider(buffer.data(), buffer.size());
const std::string random_string{provider.ConsumeRandomLengthString(1000)};
const int max_ret_len{provider.ConsumeIntegralInRange<int>(-1, 1000)};
FuzzedDataProvider provider{buffer.data(), buffer.size()};
const auto random_string{provider.ConsumeRandomLengthString(100)};
// Decode/Encode roundtrip
std::vector<unsigned char> decoded;
if (DecodeBase58Check(random_string, decoded, max_ret_len)) {
const auto encoded{EncodeBase58Check(MakeUCharSpan(random_string))};
const auto decode_input{provider.ConsumeBool() ? random_string : encoded};
const int max_ret_len{provider.ConsumeIntegralInRange<int>(-1, decode_input.size() + 1)};
if (std::vector<unsigned char> decoded; DecodeBase58Check(decode_input, decoded, max_ret_len)) {
const auto encoded_string{EncodeBase58Check(decoded)};
assert(encoded_string == TrimStringView(random_string));
assert(encoded_string.empty() || !DecodeBase58Check(encoded_string, decoded, provider.ConsumeIntegralInRange<int>(0, decoded.size() - 1)));
assert(encoded_string == TrimStringView(decode_input));
if (decoded.size() > 0) {
assert(max_ret_len > 0);
assert(decoded.size() <= static_cast<size_t>(max_ret_len));
assert(!DecodeBase58Check(encoded_string, decoded, provider.ConsumeIntegralInRange<int>(0, decoded.size() - 1)));
}
}
// Encode/Decode roundtrip
const auto encoded{EncodeBase58Check(buffer)};
std::vector<unsigned char> roundtrip_decoded;
assert(DecodeBase58Check(encoded, roundtrip_decoded, buffer.size())
&& std::ranges::equal(roundtrip_decoded, buffer));
}
FUZZ_TARGET(base32_encode_decode)