Skip to content

Commit 635bc58

Browse files
l0rinchodlinator
andcommitted
test: Fuzz Base32/Base58/Base64 roundtrip conversions
This commit introduces symmetric encode-decode roundtrips for all bases. Minor refactors were also included: • Split each base into a separate fuzz target. • Added symmetric encode-decode roundtrip tests for all bases. • Removed trim testing for encoded_string, as Base58 does not use whitespace padding. • Made comparisons stricter by removing unnecessary lowercase conversions for bases that have mixed-case alphabets. Co-authored-by: Hodlinator <[email protected]>
1 parent 5dd3a0d commit 635bc58

File tree

2 files changed

+64
-39
lines changed

2 files changed

+64
-39
lines changed

src/test/base58_tests.cpp

-16
Original file line numberDiff line numberDiff line change
@@ -82,20 +82,4 @@ BOOST_AUTO_TEST_CASE(base58_DecodeBase58)
8282
BOOST_CHECK(!DecodeBase58Check("3vQB7B6MrGQZaxCuFg4oh\0" "0IOl"s, result, 100));
8383
}
8484

85-
BOOST_AUTO_TEST_CASE(base58_random_encode_decode)
86-
{
87-
for (int n = 0; n < 1000; ++n) {
88-
unsigned int len = 1 + m_rng.randbits(8);
89-
unsigned int zeroes = m_rng.randbool() ? m_rng.randrange(len + 1) : 0;
90-
auto data = Cat(std::vector<unsigned char>(zeroes, '\000'), m_rng.randbytes(len - zeroes));
91-
auto encoded = EncodeBase58Check(data);
92-
std::vector<unsigned char> decoded;
93-
auto ok_too_small = DecodeBase58Check(encoded, decoded, m_rng.randrange(len));
94-
BOOST_CHECK(!ok_too_small);
95-
auto ok = DecodeBase58Check(encoded, decoded, len + m_rng.randrange(257 - len));
96-
BOOST_CHECK(ok);
97-
BOOST_CHECK(data == decoded);
98-
}
99-
}
100-
10185
BOOST_AUTO_TEST_SUITE_END()

src/test/fuzz/base_encode_decode.cpp

+64-23
Original file line numberDiff line numberDiff line change
@@ -6,49 +6,90 @@
66

77
#include <base58.h>
88
#include <psbt.h>
9+
#include <test/fuzz/FuzzedDataProvider.h>
910
#include <util/strencodings.h>
1011
#include <util/string.h>
1112

1213
#include <cassert>
13-
#include <cstdint>
1414
#include <string>
1515
#include <vector>
16+
#include <ranges>
1617

17-
using util::TrimString;
1818
using util::TrimStringView;
1919

20-
FUZZ_TARGET(base_encode_decode)
20+
FUZZ_TARGET(base58_encode_decode)
2121
{
22-
const std::string random_encoded_string(buffer.begin(), buffer.end());
22+
FuzzedDataProvider provider(buffer.data(), buffer.size());
23+
const std::string random_string{provider.ConsumeRandomLengthString(1000)};
2324

25+
// Decode/Encode roundtrip
2426
std::vector<unsigned char> decoded;
25-
if (DecodeBase58(random_encoded_string, decoded, 100)) {
26-
const std::string encoded_string = EncodeBase58(decoded);
27-
assert(encoded_string == TrimStringView(encoded_string));
28-
assert(ToLower(encoded_string) == ToLower(TrimString(random_encoded_string)));
27+
if (DecodeBase58(random_string, decoded, 100)) {
28+
const auto encoded_string{EncodeBase58(decoded)};
29+
assert(encoded_string == TrimStringView(random_string));
30+
assert(encoded_string.empty() || !DecodeBase58(encoded_string, decoded, provider.ConsumeIntegralInRange<int>(0, decoded.size() - 1)));
2931
}
32+
// Encode/Decode roundtrip
33+
const auto encoded{EncodeBase58(buffer)};
34+
std::vector<unsigned char> roundtrip_decoded;
35+
assert(DecodeBase58(encoded, roundtrip_decoded, buffer.size())
36+
&& std::ranges::equal(roundtrip_decoded, buffer));
37+
}
38+
39+
FUZZ_TARGET(base58check_encode_decode)
40+
{
41+
FuzzedDataProvider provider(buffer.data(), buffer.size());
42+
const std::string random_string{provider.ConsumeRandomLengthString(1000)};
3043

31-
if (DecodeBase58Check(random_encoded_string, decoded, 100)) {
32-
const std::string encoded_string = EncodeBase58Check(decoded);
33-
assert(encoded_string == TrimString(encoded_string));
34-
assert(ToLower(encoded_string) == ToLower(TrimString(random_encoded_string)));
44+
// Decode/Encode roundtrip
45+
std::vector<unsigned char> decoded;
46+
if (DecodeBase58Check(random_string, decoded, 100)) {
47+
const auto encoded_string{EncodeBase58Check(decoded)};
48+
assert(encoded_string == TrimStringView(random_string));
49+
assert(encoded_string.empty() || !DecodeBase58Check(encoded_string, decoded, provider.ConsumeIntegralInRange<int>(0, decoded.size() - 1)));
3550
}
51+
// Encode/Decode roundtrip
52+
const auto encoded{EncodeBase58Check(buffer)};
53+
std::vector<unsigned char> roundtrip_decoded;
54+
assert(DecodeBase58Check(encoded, roundtrip_decoded, buffer.size())
55+
&& std::ranges::equal(roundtrip_decoded, buffer));
56+
}
57+
58+
FUZZ_TARGET(base32_encode_decode)
59+
{
60+
const std::string random_string{buffer.begin(), buffer.end()};
3661

37-
auto result = DecodeBase32(random_encoded_string);
38-
if (result) {
39-
const std::string encoded_string = EncodeBase32(*result);
40-
assert(encoded_string == TrimStringView(encoded_string));
41-
assert(ToLower(encoded_string) == ToLower(TrimString(random_encoded_string)));
62+
// Decode/Encode roundtrip
63+
if (auto result{DecodeBase32(random_string)}) {
64+
const auto encoded_string{EncodeBase32(*result)};
65+
assert(encoded_string == ToLower(TrimStringView(random_string)));
4266
}
67+
// Encode/Decode roundtrip
68+
const auto encoded{EncodeBase32(buffer)};
69+
const auto decoded{DecodeBase32(encoded)};
70+
assert(decoded && std::ranges::equal(*decoded, buffer));
71+
}
72+
73+
FUZZ_TARGET(base64_encode_decode)
74+
{
75+
const std::string random_string{buffer.begin(), buffer.end()};
4376

44-
result = DecodeBase64(random_encoded_string);
45-
if (result) {
46-
const std::string encoded_string = EncodeBase64(*result);
47-
assert(encoded_string == TrimString(encoded_string));
48-
assert(ToLower(encoded_string) == ToLower(TrimString(random_encoded_string)));
77+
// Decode/Encode roundtrip
78+
if (auto result{DecodeBase64(random_string)}) {
79+
const auto encoded_string{EncodeBase64(*result)};
80+
assert(encoded_string == TrimStringView(random_string));
4981
}
82+
// Encode/Decode roundtrip
83+
const auto encoded{EncodeBase64(buffer)};
84+
const auto decoded{DecodeBase64(encoded)};
85+
assert(decoded && std::ranges::equal(*decoded, buffer));
86+
}
87+
88+
FUZZ_TARGET(psbt_base64_decode)
89+
{
90+
const std::string random_string{buffer.begin(), buffer.end()};
5091

5192
PartiallySignedTransaction psbt;
5293
std::string error;
53-
(void)DecodeBase64PSBT(psbt, random_encoded_string, error);
94+
assert(DecodeBase64PSBT(psbt, random_string, error) == error.empty());
5495
}

0 commit comments

Comments
 (0)