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