scriptnum_ops.cpp
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 <script/script.h> 6 #include <test/fuzz/FuzzedDataProvider.h> 7 #include <test/fuzz/fuzz.h> 8 #include <test/fuzz/util.h> 9 10 #include <cassert> 11 #include <cstdint> 12 #include <limits> 13 #include <vector> 14 15 namespace { 16 bool IsValidAddition(const CScriptNum& lhs, const CScriptNum& rhs) 17 { 18 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); 19 } 20 21 bool IsValidSubtraction(const CScriptNum& lhs, const CScriptNum& rhs) 22 { 23 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); 24 } 25 } // namespace 26 27 FUZZ_TARGET(scriptnum_ops) 28 { 29 FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); 30 CScriptNum script_num = ConsumeScriptNum(fuzzed_data_provider); 31 LIMITED_WHILE(fuzzed_data_provider.remaining_bytes() > 0, 1000000) { 32 CallOneOf( 33 fuzzed_data_provider, 34 [&] { 35 const int64_t i = fuzzed_data_provider.ConsumeIntegral<int64_t>(); 36 assert((script_num == i) != (script_num != i)); 37 assert((script_num <= i) != (script_num > i)); 38 assert((script_num >= i) != (script_num < i)); 39 // Avoid signed integer overflow: 40 // script/script.h:264:93: runtime error: signed integer overflow: -2261405121394637306 + -9223372036854775802 cannot be represented in type 'long' 41 if (IsValidAddition(script_num, CScriptNum{i})) { 42 assert((script_num + i) - i == script_num); 43 } 44 // Avoid signed integer overflow: 45 // script/script.h:265:93: runtime error: signed integer overflow: 9223371895120855039 - -9223372036854710486 cannot be represented in type 'long' 46 if (IsValidSubtraction(script_num, CScriptNum{i})) { 47 assert((script_num - i) + i == script_num); 48 } 49 }, 50 [&] { 51 const CScriptNum random_script_num = ConsumeScriptNum(fuzzed_data_provider); 52 assert((script_num == random_script_num) != (script_num != random_script_num)); 53 assert((script_num <= random_script_num) != (script_num > random_script_num)); 54 assert((script_num >= random_script_num) != (script_num < random_script_num)); 55 // Avoid signed integer overflow: 56 // script/script.h:264:93: runtime error: signed integer overflow: -9223126527765971126 + -9223372036854756825 cannot be represented in type 'long' 57 if (IsValidAddition(script_num, random_script_num)) { 58 assert((script_num + random_script_num) - random_script_num == script_num); 59 } 60 // Avoid signed integer overflow: 61 // script/script.h:265:93: runtime error: signed integer overflow: 6052837899185946624 - -9223372036854775808 cannot be represented in type 'long' 62 if (IsValidSubtraction(script_num, random_script_num)) { 63 assert((script_num - random_script_num) + random_script_num == script_num); 64 } 65 }, 66 [&] { 67 const CScriptNum random_script_num = ConsumeScriptNum(fuzzed_data_provider); 68 if (!IsValidAddition(script_num, random_script_num)) { 69 // Avoid assertion failure: 70 // ./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. 71 return; 72 } 73 script_num += random_script_num; 74 }, 75 [&] { 76 const CScriptNum random_script_num = ConsumeScriptNum(fuzzed_data_provider); 77 if (!IsValidSubtraction(script_num, random_script_num)) { 78 // Avoid assertion failure: 79 // ./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. 80 return; 81 } 82 script_num -= random_script_num; 83 }, 84 [&] { 85 script_num = script_num & fuzzed_data_provider.ConsumeIntegral<int64_t>(); 86 }, 87 [&] { 88 script_num = script_num & ConsumeScriptNum(fuzzed_data_provider); 89 }, 90 [&] { 91 script_num &= ConsumeScriptNum(fuzzed_data_provider); 92 }, 93 [&] { 94 if (script_num == CScriptNum{std::numeric_limits<int64_t>::min()}) { 95 // Avoid assertion failure: 96 // ./script/script.h:279: CScriptNum CScriptNum::operator-() const: Assertion `m_value != std::numeric_limits<int64_t>::min()' failed. 97 return; 98 } 99 script_num = -script_num; 100 }, 101 [&] { 102 script_num = fuzzed_data_provider.ConsumeIntegral<int64_t>(); 103 }, 104 [&] { 105 const int64_t random_integer = fuzzed_data_provider.ConsumeIntegral<int64_t>(); 106 if (!IsValidAddition(script_num, CScriptNum{random_integer})) { 107 // Avoid assertion failure: 108 // ./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. 109 return; 110 } 111 script_num += random_integer; 112 }, 113 [&] { 114 const int64_t random_integer = fuzzed_data_provider.ConsumeIntegral<int64_t>(); 115 if (!IsValidSubtraction(script_num, CScriptNum{random_integer})) { 116 // Avoid assertion failure: 117 // ./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. 118 return; 119 } 120 script_num -= random_integer; 121 }, 122 [&] { 123 script_num &= fuzzed_data_provider.ConsumeIntegral<int64_t>(); 124 }); 125 (void)script_num.getint(); 126 (void)script_num.getvch(); 127 } 128 }