Branch data Line data Source code
1 : : // Copyright (c) 2009-2021 The Bitcoin Core developers
2 : : // Distributed under the MIT software license, see the accompanying
3 : : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 : :
5 : : #include <chainparams.h>
6 : : #include <key_io.h>
7 : : #include <pubkey.h>
8 : : #include <script/descriptor.h>
9 : : #include <test/fuzz/fuzz.h>
10 : : #include <test/fuzz/util/descriptor.h>
11 : : #include <util/chaintype.h>
12 : : #include <util/strencodings.h>
13 : :
14 : : //! The converter of mocked descriptors, needs to be initialized when the target is.
15 : : MockedDescriptorConverter MOCKED_DESC_CONVERTER;
16 : :
17 : : /** Test a successfully parsed descriptor. */
18 : 10930 : static void TestDescriptor(const Descriptor& desc, FlatSigningProvider& sig_provider, std::string& dummy, std::optional<bool>& is_ranged, std::optional<bool>& is_solvable)
19 : : {
20 : : // Trivial helpers.
21 : 10930 : (void)desc.IsRange();
22 : 10930 : (void)desc.IsSingleType();
23 : 10930 : (void)desc.GetOutputType();
24 : :
25 [ + + ]: 10930 : if (is_ranged.has_value()) {
26 [ - + ]: 8235 : assert(desc.IsRange() == *is_ranged);
27 : : } else {
28 : 2695 : is_ranged = desc.IsRange();
29 : : }
30 [ + + ]: 10930 : if (is_solvable.has_value()) {
31 [ - + ]: 8235 : assert(desc.IsSolvable() == *is_solvable);
32 : : } else {
33 : 2695 : is_solvable = desc.IsSolvable();
34 : : }
35 : :
36 : : // Serialization to string representation.
37 : 10930 : (void)desc.ToString();
38 : 10930 : (void)desc.ToPrivateString(sig_provider, dummy);
39 : 10930 : (void)desc.ToNormalizedString(sig_provider, dummy);
40 : :
41 : : // Serialization to Script.
42 : 10930 : DescriptorCache cache;
43 : 10930 : std::vector<CScript> out_scripts;
44 [ + - ]: 10930 : (void)desc.Expand(0, sig_provider, out_scripts, sig_provider, &cache);
45 [ + - ]: 10930 : (void)desc.ExpandPrivate(0, sig_provider, sig_provider);
46 [ + - ]: 10930 : (void)desc.ExpandFromCache(0, cache, out_scripts, sig_provider);
47 : :
48 : : // If we could serialize to script we must be able to infer using the same provider.
49 [ + + ]: 10930 : if (!out_scripts.empty()) {
50 [ + - - + ]: 10242 : assert(InferDescriptor(out_scripts.back(), sig_provider));
51 : :
52 : : // The ScriptSize() must match the size of the serialized Script. (ScriptSize() is set for all descs but 'combo()'.)
53 [ + - ]: 10242 : const bool is_combo{!desc.IsSingleType()};
54 [ + + + + : 18064 : assert(is_combo || desc.ScriptSize() == out_scripts.back().size());
+ - ]
55 : : }
56 : :
57 [ + - ]: 10930 : const auto max_sat_maxsig{desc.MaxSatisfactionWeight(true)};
58 [ + - ]: 10930 : const auto max_sat_nonmaxsig{desc.MaxSatisfactionWeight(true)};
59 [ + - ]: 10930 : const auto max_elems{desc.MaxSatisfactionElems()};
60 : : // We must be able to estimate the max satisfaction size for any solvable descriptor (but combo).
61 [ + + + - : 10930 : const bool is_nontop_or_nonsolvable{!*is_solvable || !desc.GetOutputType()};
+ + ]
62 [ + + + - : 10930 : const bool is_input_size_info_set{max_sat_maxsig && max_sat_nonmaxsig && max_elems};
- + ]
63 [ - + ]: 581 : assert(is_input_size_info_set || is_nontop_or_nonsolvable);
64 : 10930 : }
65 : :
66 : 2 : void initialize_descriptor_parse()
67 : : {
68 [ + - + - : 2 : static ECC_Context ecc_context{};
+ - ]
69 : 2 : SelectParams(ChainType::MAIN);
70 : 2 : }
71 : :
72 : 1 : void initialize_mocked_descriptor_parse()
73 : : {
74 : 1 : initialize_descriptor_parse();
75 : 1 : MOCKED_DESC_CONVERTER.Init();
76 : 1 : }
77 : :
78 [ + - ]: 3453 : FUZZ_TARGET(mocked_descriptor_parse, .init = initialize_mocked_descriptor_parse)
79 : : {
80 : : // Key derivation is expensive. Deriving deep derivation paths take a lot of compute and we'd
81 : : // rather spend time elsewhere in this target, like on the actual descriptor syntax. So rule
82 : : // out strings which could correspond to a descriptor containing a too large derivation path.
83 [ + + ]: 3041 : if (HasDeepDerivPath(buffer)) return;
84 : :
85 : : // Some fragments can take a virtually unlimited number of sub-fragments (thresh, multi_a) but
86 : : // may perform quadratic operations on them. Limit the number of sub-fragments per fragment.
87 [ + + ]: 3040 : if (HasTooManySubFrag(buffer)) return;
88 : :
89 : : // The script building logic performs quadratic copies in the number of nested wrappers. Limit
90 : : // the number of nested wrappers per fragment.
91 [ + + ]: 3038 : if (HasTooManyWrappers(buffer)) return;
92 : :
93 [ + - ]: 3036 : const std::string mocked_descriptor{buffer.begin(), buffer.end()};
94 [ + - + + ]: 3036 : if (const auto descriptor = MOCKED_DESC_CONVERTER.GetDescriptor(mocked_descriptor)) {
95 : 3013 : FlatSigningProvider signing_provider;
96 [ + - ]: 3013 : std::string error;
97 [ + - ]: 3013 : const auto desc = Parse(*descriptor, signing_provider, error);
98 : 3013 : std::optional<bool> is_ranged;
99 : 3013 : std::optional<bool> is_solvable;
100 [ + + ]: 12889 : for (const auto& d : desc) {
101 [ - + ]: 9876 : assert(d);
102 [ + - ]: 9876 : TestDescriptor(*d, signing_provider, error, is_ranged, is_solvable);
103 : : }
104 : 6049 : }
105 : 3036 : }
106 : :
107 [ + - ]: 2902 : FUZZ_TARGET(descriptor_parse, .init = initialize_descriptor_parse)
108 : : {
109 : : // See comments above for rationales.
110 [ + + ]: 2490 : if (HasDeepDerivPath(buffer)) return;
111 [ + + ]: 2489 : if (HasTooManySubFrag(buffer)) return;
112 [ + + ]: 2486 : if (HasTooManyWrappers(buffer)) return;
113 : :
114 : 2483 : const std::string descriptor(buffer.begin(), buffer.end());
115 : 2483 : FlatSigningProvider signing_provider;
116 : 2483 : std::string error;
117 [ + + ]: 7449 : for (const bool require_checksum : {true, false}) {
118 [ + - ]: 4966 : const auto desc = Parse(descriptor, signing_provider, error, require_checksum);
119 : 4966 : std::optional<bool> is_ranged;
120 : 4966 : std::optional<bool> is_solvable;
121 [ + + ]: 6020 : for (const auto& d : desc) {
122 [ - + ]: 1054 : assert(d);
123 [ + - ]: 1054 : TestDescriptor(*d, signing_provider, error, is_ranged, is_solvable);
124 : : }
125 : 4966 : }
126 : 2483 : }
|