| 91 | } |
| 92 | |
| 93 | CScript ConsumeScript(FuzzedDataProvider& fuzzed_data_provider, const bool maybe_p2wsh) noexcept |
| 94 | { |
| 95 | CScript r_script{}; |
| 96 | { |
| 97 | // Keep a buffer of bytes to allow the fuzz engine to produce smaller |
| 98 | // inputs to generate CScripts with repeated data. |
| 99 | static constexpr unsigned MAX_BUFFER_SZ{128}; |
| 100 | std::vector<uint8_t> buffer(MAX_BUFFER_SZ, uint8_t{'a'}); |
| 101 | while (fuzzed_data_provider.ConsumeBool()) { |
| 102 | CallOneOf( |
| 103 | fuzzed_data_provider, |
| 104 | [&] { |
| 105 | // Insert byte vector directly to allow malformed or unparsable scripts |
| 106 | r_script.insert(r_script.end(), buffer.begin(), buffer.begin() + fuzzed_data_provider.ConsumeIntegralInRange(0U, MAX_BUFFER_SZ)); |
| 107 | }, |
| 108 | [&] { |
| 109 | // Push a byte vector from the buffer |
| 110 | r_script << std::vector<uint8_t>{buffer.begin(), buffer.begin() + fuzzed_data_provider.ConsumeIntegralInRange(0U, MAX_BUFFER_SZ)}; |
| 111 | }, |
| 112 | [&] { |
| 113 | // Push multisig |
| 114 | // There is a special case for this to aid the fuzz engine |
| 115 | // navigate the highly structured multisig format. |
| 116 | r_script << fuzzed_data_provider.ConsumeIntegralInRange<int64_t>(0, 22); |
| 117 | int num_data{fuzzed_data_provider.ConsumeIntegralInRange(1, 22)}; |
| 118 | while (num_data--) { |
| 119 | auto pubkey_bytes{ConstructPubKeyBytes(fuzzed_data_provider, buffer, fuzzed_data_provider.ConsumeBool())}; |
| 120 | if (fuzzed_data_provider.ConsumeBool()) { |
| 121 | pubkey_bytes.back() = num_data; // Make each pubkey different |
| 122 | } |
| 123 | r_script << pubkey_bytes; |
| 124 | } |
| 125 | r_script << fuzzed_data_provider.ConsumeIntegralInRange<int64_t>(0, 22); |
| 126 | }, |
| 127 | [&] { |
| 128 | // Mutate the buffer |
| 129 | const auto vec{ConsumeRandomLengthByteVector(fuzzed_data_provider, /*max_length=*/MAX_BUFFER_SZ)}; |
| 130 | std::copy(vec.begin(), vec.end(), buffer.begin()); |
| 131 | }, |
| 132 | [&] { |
| 133 | // Push an integral |
| 134 | r_script << fuzzed_data_provider.ConsumeIntegral<int64_t>(); |
| 135 | }, |
| 136 | [&] { |
| 137 | // Push an opcode |
| 138 | r_script << ConsumeOpcodeType(fuzzed_data_provider); |
| 139 | }, |
| 140 | [&] { |
| 141 | // Push a scriptnum |
| 142 | r_script << ConsumeScriptNum(fuzzed_data_provider); |
| 143 | }); |
| 144 | } |
| 145 | } |
| 146 | if (maybe_p2wsh && fuzzed_data_provider.ConsumeBool()) { |
| 147 | uint256 script_hash; |
| 148 | CSHA256().Write(r_script.data(), r_script.size()).Finalize(script_hash.begin()); |
| 149 | r_script.clear(); |
| 150 | r_script << OP_0 << ToByteVector(script_hash); |
no test coverage detected