Changeset View
Changeset View
Standalone View
Standalone View
src/script/script.h
Show First 20 Lines • Show All 265 Lines • ▼ Show 20 Lines | public: | ||||
inline bool operator>=(const CScriptNum &rhs) const { | inline bool operator>=(const CScriptNum &rhs) const { | ||||
return operator>=(rhs.m_value); | return operator>=(rhs.m_value); | ||||
} | } | ||||
inline bool operator>(const CScriptNum &rhs) const { | inline bool operator>(const CScriptNum &rhs) const { | ||||
return operator>(rhs.m_value); | return operator>(rhs.m_value); | ||||
} | } | ||||
inline CScriptNum operator+(const int64_t &rhs) const { | inline CScriptNum operator+(const int64_t &rhs) const { | ||||
return CScriptNum(m_value + rhs); | int64_t result; | ||||
if (overflow_add_int64(m_value, rhs, result)) { | |||||
throw scriptnum_error("script number add overflow"); | |||||
deadalnix: This is clearly a new error condition that is being added to existing code.
If you modify… | |||||
} | |||||
return CScriptNum(result); | |||||
} | } | ||||
inline CScriptNum operator-(const int64_t &rhs) const { | inline CScriptNum operator-(const int64_t &rhs) const { | ||||
return CScriptNum(m_value - rhs); | int64_t result; | ||||
if (overflow_sub_int64(m_value, rhs, result)) { | |||||
throw scriptnum_error("script number sub overflow"); | |||||
} | |||||
return CScriptNum(result); | |||||
} | } | ||||
inline CScriptNum operator+(const CScriptNum &rhs) const { | inline CScriptNum operator+(const CScriptNum &rhs) const { | ||||
return operator+(rhs.m_value); | return operator+(rhs.m_value); | ||||
} | } | ||||
inline CScriptNum operator-(const CScriptNum &rhs) const { | inline CScriptNum operator-(const CScriptNum &rhs) const { | ||||
return operator-(rhs.m_value); | return operator-(rhs.m_value); | ||||
} | } | ||||
inline CScriptNum operator/(const int64_t &rhs) const { | inline CScriptNum operator/(const int64_t &rhs) const { | ||||
// Sanity check for invalid script num; should never occur | |||||
assert(m_value != std::numeric_limits<int64_t>::min()); | |||||
// Sanity check for division by 0; should be handled before | |||||
assert(rhs != 0); | |||||
return CScriptNum(m_value / rhs); | return CScriptNum(m_value / rhs); | ||||
} | } | ||||
inline CScriptNum operator/(const CScriptNum &rhs) const { | inline CScriptNum operator/(const CScriptNum &rhs) const { | ||||
return operator/(rhs.m_value); | return operator/(rhs.m_value); | ||||
} | } | ||||
inline CScriptNum operator%(const int64_t &rhs) const { | inline CScriptNum operator%(const int64_t &rhs) const { | ||||
// Sanity check for invalid script num; should never occur | |||||
assert(m_value != std::numeric_limits<int64_t>::min()); | |||||
// Sanity check for division by 0; should be handled before | |||||
assert(rhs != 0); | |||||
return CScriptNum(m_value % rhs); | return CScriptNum(m_value % rhs); | ||||
} | } | ||||
inline CScriptNum operator%(const CScriptNum &rhs) const { | inline CScriptNum operator%(const CScriptNum &rhs) const { | ||||
return operator%(rhs.m_value); | return operator%(rhs.m_value); | ||||
} | } | ||||
inline CScriptNum &operator+=(const CScriptNum &rhs) { | inline CScriptNum &operator+=(const CScriptNum &rhs) { | ||||
return operator+=(rhs.m_value); | return operator+=(rhs.m_value); | ||||
Show All 9 Lines | inline CScriptNum operator&(const CScriptNum &rhs) const { | ||||
return operator&(rhs.m_value); | return operator&(rhs.m_value); | ||||
} | } | ||||
inline CScriptNum &operator&=(const CScriptNum &rhs) { | inline CScriptNum &operator&=(const CScriptNum &rhs) { | ||||
return operator&=(rhs.m_value); | return operator&=(rhs.m_value); | ||||
} | } | ||||
inline CScriptNum operator-() const { | inline CScriptNum operator-() const { | ||||
// Sanity check for invalid script num; should never occur | |||||
assert(m_value != std::numeric_limits<int64_t>::min()); | assert(m_value != std::numeric_limits<int64_t>::min()); | ||||
return CScriptNum(-m_value); | return CScriptNum(-m_value); | ||||
} | } | ||||
inline CScriptNum &operator=(const int64_t &rhs) { | inline CScriptNum &operator=(const int64_t &rhs) { | ||||
m_value = rhs; | m_value = rhs; | ||||
return *this; | return *this; | ||||
} | } | ||||
inline CScriptNum &operator+=(const int64_t &rhs) { | inline CScriptNum &operator+=(const int64_t &rhs) { | ||||
assert( | int64_t result; | ||||
rhs == 0 || | if (overflow_add_int64(m_value, rhs, result)) { | ||||
(rhs > 0 && m_value <= std::numeric_limits<int64_t>::max() - rhs) || | throw scriptnum_error("script number add overflow"); | ||||
(rhs < 0 && m_value >= std::numeric_limits<int64_t>::min() - rhs)); | } | ||||
m_value += rhs; | m_value = result; | ||||
return *this; | return *this; | ||||
} | } | ||||
inline CScriptNum &operator-=(const int64_t &rhs) { | inline CScriptNum &operator-=(const int64_t &rhs) { | ||||
assert( | int64_t result; | ||||
rhs == 0 || | if (overflow_sub_int64(m_value, rhs, result)) { | ||||
(rhs > 0 && m_value >= std::numeric_limits<int64_t>::min() + rhs) || | throw scriptnum_error("script number sub overflow"); | ||||
(rhs < 0 && m_value <= std::numeric_limits<int64_t>::max() + rhs)); | } | ||||
m_value -= rhs; | m_value = result; | ||||
return *this; | return *this; | ||||
} | } | ||||
inline CScriptNum &operator&=(const int64_t &rhs) { | inline CScriptNum &operator&=(const int64_t &rhs) { | ||||
m_value &= rhs; | m_value &= rhs; | ||||
return *this; | return *this; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 55 Lines • ▼ Show 20 Lines | static int64_t set_vch(const std::vector<uint8_t> &vch) { | ||||
// the result's msb and return a negative. | // the result's msb and return a negative. | ||||
if (vch.back() & 0x80) { | if (vch.back() & 0x80) { | ||||
return -int64_t(result & ~(0x80ULL << (8 * (vch.size() - 1)))); | return -int64_t(result & ~(0x80ULL << (8 * (vch.size() - 1)))); | ||||
} | } | ||||
return result; | return result; | ||||
} | } | ||||
/** | |||||
* Computes a + b and stores it in result. If the sum overflows or results | |||||
* in an invalid Script integer, return true, otherwise false. | |||||
*/ | |||||
static bool overflow_add_int64(int64_t a, int64_t b, int64_t &result) { | |||||
#if HAVE_DECL___BUILTIN_SADDLL_OVERFLOW | |||||
static_assert(std::numeric_limits<long long int>::max() == | |||||
std::numeric_limits<int64_t>::max()); | |||||
long long int tmp_result; // must use long long int due to types | |||||
if (__builtin_saddll_overflow(a, b, &tmp_result)) { | |||||
return true; | |||||
} | |||||
result = tmp_result; | |||||
#else | |||||
if (a > 0 && b > std::numeric_limits<int64_t>::max() - a) { | |||||
// integer overflow | |||||
return true; | |||||
} | |||||
if (a < 0 && b <= std::numeric_limits<int64_t>::min() - a) { | |||||
// integer underflow | |||||
return true; | |||||
} | |||||
result = a + b; | |||||
#endif | |||||
if (result == std::numeric_limits<int64_t>::min()) { | |||||
return true; | |||||
} | |||||
return false; | |||||
} | |||||
/** | |||||
* Computes a - b and stores it in result. If the difference overflows or | |||||
* results in an invalid Script integer, return true, otherwise false. | |||||
*/ | |||||
static bool overflow_sub_int64(int64_t a, int64_t b, int64_t &result) { | |||||
#if HAVE_DECL___BUILTIN_SSUBLL_OVERFLOW | |||||
static_assert(std::numeric_limits<long long int>::max() == | |||||
std::numeric_limits<int64_t>::max()); | |||||
long long int tmp_result; // must use long long int due to types | |||||
if (__builtin_ssubll_overflow(a, b, &tmp_result)) { | |||||
return true; | |||||
} | |||||
result = tmp_result; | |||||
#else | |||||
if (a < 0 && b > std::numeric_limits<int64_t>::max() + a) { | |||||
// integer overflow | |||||
return true; | |||||
} | |||||
if (a > 0 && b <= std::numeric_limits<int64_t>::min() + a) { | |||||
// integer underflow | |||||
return true; | |||||
} | |||||
result = a - b; | |||||
#endif | |||||
if (result == std::numeric_limits<int64_t>::min()) { | |||||
return true; | |||||
} | |||||
return false; | |||||
} | |||||
int64_t m_value; | int64_t m_value; | ||||
}; | }; | ||||
/** | /** | ||||
* We use a prevector for the script to reduce the considerable memory overhead | * We use a prevector for the script to reduce the considerable memory overhead | ||||
* of vectors in cases where they normally contain a small number of small | * of vectors in cases where they normally contain a small number of small | ||||
* elements. Tests in October 2015 showed use of this reduced dbcache memory | * elements. Tests in October 2015 showed use of this reduced dbcache memory | ||||
* usage by 23% and made an initial sync 13% faster. | * usage by 23% and made an initial sync 13% faster. | ||||
▲ Show 20 Lines • Show All 139 Lines • Show Last 20 Lines |
This is clearly a new error condition that is being added to existing code.
If you modify existing consensus code, please do not mix this with additional changes. Do them standalone.