aboutsummaryrefslogtreecommitdiff
path: root/src/test/fuzz/scriptnum_ops.cpp
blob: 42b1432f13aa52435cf865f6a563375205a38d88 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
// Copyright (c) 2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <script/script.h>
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
#include <test/fuzz/util.h>

#include <cassert>
#include <cstdint>
#include <limits>
#include <vector>

namespace {
bool IsValidAddition(const CScriptNum& lhs, const CScriptNum& rhs)
{
    return rhs == 0 || (rhs > 0 && lhs <= CScriptNum{std::numeric_limits<int64_t>::max()} - rhs) || (rhs < 0 && lhs >= CScriptNum{std::numeric_limits<int64_t>::min()} - rhs);
}

bool IsValidSubtraction(const CScriptNum& lhs, const CScriptNum& rhs)
{
    return rhs == 0 || (rhs > 0 && lhs >= CScriptNum{std::numeric_limits<int64_t>::min()} + rhs) || (rhs < 0 && lhs <= CScriptNum{std::numeric_limits<int64_t>::max()} + rhs);
}
} // namespace

void test_one_input(const std::vector<uint8_t>& buffer)
{
    FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
    CScriptNum script_num = ConsumeScriptNum(fuzzed_data_provider);
    while (fuzzed_data_provider.remaining_bytes() > 0) {
        switch (fuzzed_data_provider.ConsumeIntegralInRange(0, 11)) {
        case 0: {
            const int64_t i = fuzzed_data_provider.ConsumeIntegral<int64_t>();
            assert((script_num == i) != (script_num != i));
            assert((script_num <= i) != script_num > i);
            assert((script_num >= i) != (script_num < i));
            // Avoid signed integer overflow:
            // script/script.h:264:93: runtime error: signed integer overflow: -2261405121394637306 + -9223372036854775802 cannot be represented in type 'long'
            if (IsValidAddition(script_num, CScriptNum{i})) {
                assert((script_num + i) - i == script_num);
            }
            // Avoid signed integer overflow:
            // script/script.h:265:93: runtime error: signed integer overflow: 9223371895120855039 - -9223372036854710486 cannot be represented in type 'long'
            if (IsValidSubtraction(script_num, CScriptNum{i})) {
                assert((script_num - i) + i == script_num);
            }
            break;
        }
        case 1: {
            const CScriptNum random_script_num = ConsumeScriptNum(fuzzed_data_provider);
            assert((script_num == random_script_num) != (script_num != random_script_num));
            assert((script_num <= random_script_num) != (script_num > random_script_num));
            assert((script_num >= random_script_num) != (script_num < random_script_num));
            // Avoid signed integer overflow:
            // script/script.h:264:93: runtime error: signed integer overflow: -9223126527765971126 + -9223372036854756825 cannot be represented in type 'long'
            if (IsValidAddition(script_num, random_script_num)) {
                assert((script_num + random_script_num) - random_script_num == script_num);
            }
            // Avoid signed integer overflow:
            // script/script.h:265:93: runtime error: signed integer overflow: 6052837899185946624 - -9223372036854775808 cannot be represented in type 'long'
            if (IsValidSubtraction(script_num, random_script_num)) {
                assert((script_num - random_script_num) + random_script_num == script_num);
            }
            break;
        }
        case 2: {
            const CScriptNum random_script_num = ConsumeScriptNum(fuzzed_data_provider);
            if (!IsValidAddition(script_num, random_script_num)) {
                // Avoid assertion failure:
                // ./script/script.h:292: CScriptNum &CScriptNum::operator+=(const int64_t &): Assertion `rhs == 0 || (rhs > 0 && m_value <= std::numeric_limits<int64_t>::max() - rhs) || (rhs < 0 && m_value >= std::numeric_limits<int64_t>::min() - rhs)' failed.
                break;
            }
            script_num += random_script_num;
            break;
        }
        case 3: {
            const CScriptNum random_script_num = ConsumeScriptNum(fuzzed_data_provider);
            if (!IsValidSubtraction(script_num, random_script_num)) {
                // Avoid assertion failure:
                // ./script/script.h:300: CScriptNum &CScriptNum::operator-=(const int64_t &): Assertion `rhs == 0 || (rhs > 0 && m_value >= std::numeric_limits<int64_t>::min() + rhs) || (rhs < 0 && m_value <= std::numeric_limits<int64_t>::max() + rhs)' failed.
                break;
            }
            script_num -= random_script_num;
            break;
        }
        case 4:
            script_num = script_num & fuzzed_data_provider.ConsumeIntegral<int64_t>();
            break;
        case 5:
            script_num = script_num & ConsumeScriptNum(fuzzed_data_provider);
            break;
        case 6:
            script_num &= ConsumeScriptNum(fuzzed_data_provider);
            break;
        case 7:
            if (script_num == CScriptNum{std::numeric_limits<int64_t>::min()}) {
                // Avoid assertion failure:
                // ./script/script.h:279: CScriptNum CScriptNum::operator-() const: Assertion `m_value != std::numeric_limits<int64_t>::min()' failed.
                break;
            }
            script_num = -script_num;
            break;
        case 8:
            script_num = fuzzed_data_provider.ConsumeIntegral<int64_t>();
            break;
        case 9: {
            const int64_t random_integer = fuzzed_data_provider.ConsumeIntegral<int64_t>();
            if (!IsValidAddition(script_num, CScriptNum{random_integer})) {
                // Avoid assertion failure:
                // ./script/script.h:292: CScriptNum &CScriptNum::operator+=(const int64_t &): Assertion `rhs == 0 || (rhs > 0 && m_value <= std::numeric_limits<int64_t>::max() - rhs) || (rhs < 0 && m_value >= std::numeric_limits<int64_t>::min() - rhs)' failed.
                break;
            }
            script_num += random_integer;
            break;
        }
        case 10: {
            const int64_t random_integer = fuzzed_data_provider.ConsumeIntegral<int64_t>();
            if (!IsValidSubtraction(script_num, CScriptNum{random_integer})) {
                // Avoid assertion failure:
                // ./script/script.h:300: CScriptNum &CScriptNum::operator-=(const int64_t &): Assertion `rhs == 0 || (rhs > 0 && m_value >= std::numeric_limits<int64_t>::min() + rhs) || (rhs < 0 && m_value <= std::numeric_limits<int64_t>::max() + rhs)' failed.
                break;
            }
            script_num -= random_integer;
            break;
        }
        case 11:
            script_num &= fuzzed_data_provider.ConsumeIntegral<int64_t>();
            break;
        }
        (void)script_num.getint();
        // Avoid negation failure:
        // script/script.h:332:35: runtime error: negation of -9223372036854775808 cannot be represented in type 'int64_t' (aka 'long'); cast to an unsigned type to negate this value to itself
        if (script_num != CScriptNum{std::numeric_limits<int64_t>::min()}) {
            (void)script_num.getvch();
        }
    }
}