1 // Copyright (c) 2009-2020 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 <pubkey.h>
6 #include <script/interpreter.h>
7 #include <test/fuzz/FuzzedDataProvider.h>
8 #include <test/fuzz/fuzz.h>
9 #include <util/memory.h>
10 
11 #include <cstdint>
12 #include <limits>
13 #include <string>
14 #include <vector>
15 
initialize()16 void initialize()
17 {
18     static const auto verify_handle = MakeUnique<ECCVerifyHandle>();
19 }
20 
21 namespace {
22 class FuzzedSignatureChecker : public BaseSignatureChecker
23 {
24     FuzzedDataProvider& m_fuzzed_data_provider;
25 
26 public:
FuzzedSignatureChecker(FuzzedDataProvider & fuzzed_data_provider)27     FuzzedSignatureChecker(FuzzedDataProvider& fuzzed_data_provider) : m_fuzzed_data_provider(fuzzed_data_provider)
28     {
29     }
30 
CheckECDSASignature(const std::vector<unsigned char> & scriptSig,const std::vector<unsigned char> & vchPubKey,const CScript & scriptCode,SigVersion sigversion) const31     bool CheckECDSASignature(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const override
32     {
33         return m_fuzzed_data_provider.ConsumeBool();
34     }
35 
CheckSchnorrSignature(Span<const unsigned char> sig,Span<const unsigned char> pubkey,SigVersion sigversion,const ScriptExecutionData & execdata,ScriptError * serror=nullptr) const36     bool CheckSchnorrSignature(Span<const unsigned char> sig, Span<const unsigned char> pubkey, SigVersion sigversion, const ScriptExecutionData& execdata, ScriptError* serror = nullptr) const override
37     {
38         return m_fuzzed_data_provider.ConsumeBool();
39     }
40 
CheckLockTime(const CScriptNum & nLockTime) const41     bool CheckLockTime(const CScriptNum& nLockTime) const override
42     {
43         return m_fuzzed_data_provider.ConsumeBool();
44     }
45 
CheckSequence(const CScriptNum & nSequence) const46     bool CheckSequence(const CScriptNum& nSequence) const override
47     {
48         return m_fuzzed_data_provider.ConsumeBool();
49     }
50 
~FuzzedSignatureChecker()51     virtual ~FuzzedSignatureChecker() {}
52 };
53 } // namespace
54 
test_one_input(const std::vector<uint8_t> & buffer)55 void test_one_input(const std::vector<uint8_t>& buffer)
56 {
57     FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
58     const unsigned int flags = fuzzed_data_provider.ConsumeIntegral<unsigned int>();
59     const SigVersion sig_version = fuzzed_data_provider.PickValueInArray({SigVersion::BASE, SigVersion::WITNESS_V0});
60     const std::string script_string_1 = fuzzed_data_provider.ConsumeRandomLengthString(65536);
61     const std::vector<uint8_t> script_bytes_1{script_string_1.begin(), script_string_1.end()};
62     const std::string script_string_2 = fuzzed_data_provider.ConsumeRandomLengthString(65536);
63     const std::vector<uint8_t> script_bytes_2{script_string_2.begin(), script_string_2.end()};
64     std::vector<std::vector<unsigned char>> stack;
65     (void)EvalScript(stack, {script_bytes_1.begin(), script_bytes_1.end()}, flags, FuzzedSignatureChecker(fuzzed_data_provider), sig_version, nullptr);
66     if ((flags & SCRIPT_VERIFY_CLEANSTACK) != 0 && ((flags & SCRIPT_VERIFY_P2SH) == 0 || (flags & SCRIPT_VERIFY_WITNESS) == 0)) {
67         return;
68     }
69     if ((flags & SCRIPT_VERIFY_WITNESS) != 0 && (flags & SCRIPT_VERIFY_P2SH) == 0) {
70         return;
71     }
72     (void)VerifyScript({script_bytes_1.begin(), script_bytes_1.end()}, {script_bytes_2.begin(), script_bytes_2.end()}, nullptr, flags, FuzzedSignatureChecker(fuzzed_data_provider), nullptr);
73 }
74