/root/bitcoin/src/test/fuzz/script_interpreter.cpp
Line | Count | Source |
1 | | // Copyright (c) 2020-present 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 <primitives/transaction.h> |
6 | | #include <script/interpreter.h> |
7 | | #include <test/fuzz/FuzzedDataProvider.h> |
8 | | #include <test/fuzz/fuzz.h> |
9 | | #include <test/fuzz/util.h> |
10 | | #include <util/check.h> |
11 | | |
12 | | #include <cstdint> |
13 | | #include <optional> |
14 | | #include <string> |
15 | | #include <vector> |
16 | | |
17 | | bool CastToBool(const std::vector<unsigned char>& vch); |
18 | | |
19 | | FUZZ_TARGET(script_interpreter) |
20 | 0 | { |
21 | 0 | FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); |
22 | 0 | { |
23 | 0 | const CScript script_code = ConsumeScript(fuzzed_data_provider); |
24 | 0 | const std::optional<CMutableTransaction> mtx = ConsumeDeserializable<CMutableTransaction>(fuzzed_data_provider, TX_WITH_WITNESS); |
25 | 0 | if (mtx) { Branch (25:13): [True: 0, False: 0]
|
26 | 0 | const CTransaction tx_to{*mtx}; |
27 | 0 | const unsigned int in = fuzzed_data_provider.ConsumeIntegral<unsigned int>(); |
28 | 0 | if (in < tx_to.vin.size()) { Branch (28:17): [True: 0, False: 0]
|
29 | 0 | auto n_hash_type = fuzzed_data_provider.ConsumeIntegral<int>(); |
30 | 0 | auto amount = ConsumeMoney(fuzzed_data_provider); |
31 | 0 | auto sigversion = fuzzed_data_provider.PickValueInArray({SigVersion::BASE, SigVersion::WITNESS_V0}); |
32 | 0 | (void)SignatureHash(script_code, tx_to, in, n_hash_type, amount, sigversion, nullptr); |
33 | 0 | const std::optional<CMutableTransaction> mtx_precomputed = ConsumeDeserializable<CMutableTransaction>(fuzzed_data_provider, TX_WITH_WITNESS); |
34 | 0 | if (mtx_precomputed) { Branch (34:21): [True: 0, False: 0]
|
35 | 0 | const CTransaction tx_precomputed{*mtx_precomputed}; |
36 | 0 | const PrecomputedTransactionData precomputed_transaction_data{tx_precomputed}; |
37 | 0 | n_hash_type = fuzzed_data_provider.ConsumeIntegral<int>(); |
38 | 0 | amount = ConsumeMoney(fuzzed_data_provider); |
39 | 0 | sigversion = fuzzed_data_provider.PickValueInArray({SigVersion::BASE, SigVersion::WITNESS_V0}); |
40 | 0 | (void)SignatureHash(script_code, tx_to, in, n_hash_type, amount, sigversion, &precomputed_transaction_data); |
41 | 0 | } |
42 | 0 | } |
43 | 0 | } |
44 | 0 | } |
45 | 0 | { |
46 | 0 | (void)CastToBool(ConsumeRandomLengthByteVector(fuzzed_data_provider)); |
47 | 0 | } |
48 | 0 | } |
49 | | |
50 | | /** Differential fuzzing for SignatureHash with and without cache. */ |
51 | | FUZZ_TARGET(sighash_cache) |
52 | 0 | { |
53 | 0 | FuzzedDataProvider provider(buffer.data(), buffer.size()); |
54 | | |
55 | | // Get inputs to the sighash function that won't change across types. |
56 | 0 | const auto scriptcode{ConsumeScript(provider)}; |
57 | 0 | const auto tx{ConsumeTransaction(provider, std::nullopt)}; |
58 | 0 | if (tx.vin.empty()) return; Branch (58:9): [True: 0, False: 0]
|
59 | 0 | const auto in_index{provider.ConsumeIntegralInRange<uint32_t>(0, tx.vin.size() - 1)}; |
60 | 0 | const auto amount{ConsumeMoney(provider)}; |
61 | 0 | const auto sigversion{(SigVersion)provider.ConsumeIntegralInRange(0, 1)}; |
62 | | |
63 | | // Check the sighash function will give the same result for 100 fuzzer-generated hash types whether or not a cache is |
64 | | // provided. The cache is conserved across types to exercise cache hits. |
65 | 0 | SigHashCache sighash_cache{}; |
66 | 0 | for (int i{0}; i < 100; ++i) { Branch (66:20): [True: 0, False: 0]
|
67 | 0 | const auto hash_type{((i & 2) == 0) ? provider.ConsumeIntegral<int8_t>() : provider.ConsumeIntegral<int32_t>()}; Branch (67:30): [True: 0, False: 0]
|
68 | 0 | const auto nocache_res{SignatureHash(scriptcode, tx, in_index, hash_type, amount, sigversion)}; |
69 | 0 | const auto cache_res{SignatureHash(scriptcode, tx, in_index, hash_type, amount, sigversion, nullptr, &sighash_cache)}; |
70 | 0 | Assert(nocache_res == cache_res); |
71 | 0 | } |
72 | 0 | } |