4
4
5
5
#include < bech32.h>
6
6
#include < test/fuzz/fuzz.h>
7
+ #include < test/fuzz/FuzzedDataProvider.h>
7
8
#include < test/util/str.h>
8
9
#include < util/strencodings.h>
9
10
10
11
#include < cassert>
11
12
#include < cstdint>
12
13
#include < string>
13
- #include < utility>
14
14
#include < vector>
15
15
16
- FUZZ_TARGET (bech32 )
16
+ FUZZ_TARGET (bech32_random_decode )
17
17
{
18
- const std::string random_string (buffer.begin (), buffer.end ());
19
- const auto r1 = bech32::Decode (random_string);
20
- if (r1.hrp .empty ()) {
21
- assert (r1.encoding == bech32::Encoding::INVALID);
22
- assert (r1.data .empty ());
18
+ auto limit = bech32::CharLimit::BECH32;
19
+ FuzzedDataProvider fdp (buffer.data (), buffer.size ());
20
+ auto random_string = fdp.ConsumeRandomLengthString (limit + 1 );
21
+ auto decoded = bech32::Decode (random_string, limit);
22
+
23
+ if (decoded.hrp .empty ()) {
24
+ assert (decoded.encoding == bech32::Encoding::INVALID);
25
+ assert (decoded.data .empty ());
23
26
} else {
24
- assert (r1 .encoding != bech32::Encoding::INVALID);
25
- const std::string reencoded = bech32::Encode (r1 .encoding , r1 .hrp , r1 .data );
27
+ assert (decoded .encoding != bech32::Encoding::INVALID);
28
+ auto reencoded = bech32::Encode (decoded .encoding , decoded .hrp , decoded .data );
26
29
assert (CaseInsensitiveEqual (random_string, reencoded));
27
30
}
31
+ }
32
+
33
+ // https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki and https://github.com/bitcoin/bips/blob/master/bip-0350.mediawiki
34
+ std::string GenerateRandomHRP (FuzzedDataProvider& fdp)
35
+ {
36
+ std::string hrp;
37
+ size_t length = fdp.ConsumeIntegralInRange <size_t >(1 , 83 );
38
+ for (size_t i = 0 ; i < length; ++i) {
39
+ // Generate lowercase ASCII characters in ([33-126] - ['A'-'Z']) range
40
+ char c = fdp.ConsumeBool ()
41
+ ? fdp.ConsumeIntegralInRange <char >(33 , ' A' - 1 )
42
+ : fdp.ConsumeIntegralInRange <char >(' Z' + 1 , 126 );
43
+ hrp += c;
44
+ }
45
+ return hrp;
46
+ }
47
+
48
+ FUZZ_TARGET (bech32_roundtrip)
49
+ {
50
+ FuzzedDataProvider fdp (buffer.data (), buffer.size ());
51
+ auto hrp = GenerateRandomHRP (fdp);
28
52
29
- std::vector<unsigned char > input;
30
- ConvertBits<8 , 5 , true >([&](unsigned char c) { input.push_back (c); }, buffer.begin (), buffer.end ());
53
+ auto input_chars = fdp.ConsumeBytes <unsigned char >(fdp.ConsumeIntegralInRange <size_t >(0 , 82 ));
54
+ std::vector<uint8_t > converted_input;
55
+ ConvertBits<8 , 5 , true >([&](auto c) { converted_input.push_back (c); }, input_chars.begin (), input_chars.end ());
31
56
32
- // Input data part + 3 characters for the HRP and separator (bc1) + the checksum characters
33
- if (input.size () + 3 + bech32::CHECKSUM_SIZE <= bech32::CharLimit::BECH32) {
34
- // If it's possible to encode input in Bech32(m) without exceeding the bech32-character limit:
35
- for (auto encoding : {bech32::Encoding::BECH32, bech32::Encoding::BECH32M}) {
36
- const std::string encoded = bech32::Encode (encoding, " bc" , input);
57
+ auto size = converted_input.size () + hrp.length () + std::string ({bech32::SEPARATOR}).size () + bech32::CHECKSUM_SIZE;
58
+ if (size <= bech32::CharLimit::BECH32) {
59
+ for (auto encoding: {bech32::Encoding::BECH32, bech32::Encoding::BECH32M}) {
60
+ auto encoded = bech32::Encode (encoding, hrp, converted_input);
37
61
assert (!encoded.empty ());
38
- const auto r2 = bech32::Decode (encoded);
39
- assert (r2.encoding == encoding);
40
- assert (r2.hrp == " bc" );
41
- assert (r2.data == input);
62
+
63
+ const auto decoded = bech32::Decode (encoded);
64
+ assert (decoded.encoding == encoding);
65
+ assert (decoded.hrp == hrp);
66
+ assert (decoded.data == converted_input);
42
67
}
43
68
}
44
- }
69
+ }
0 commit comments