Fix: OverflowSafeInt could underflow

Notably, a company with an extremely negative amount of money would
suddenly become very rich
pull/332/head
Charles Pigott 3 years ago
parent 1e439979f7
commit 3d0d9edafd

@ -39,25 +39,41 @@ public:
/**
* Safe implementation of addition.
* @param other the amount to add
* @note when the addition would yield more than T_MAX (or less than T_MIN),
* it will be T_MAX (respectively T_MIN).
* @note when the addition would yield more than T_MAX, it will be T_MAX.
*/
inline OverflowSafeInt& operator += (const OverflowSafeInt& other)
{
if ((T_MAX - abs(other.m_value)) < abs(this->m_value) &&
(this->m_value < 0) == (other.m_value < 0)) {
this->m_value = (this->m_value < 0) ? T_MIN : T_MAX ;
if (this->m_value > 0 && other.m_value > 0 && (T_MAX - other.m_value) < this->m_value) {
this->m_value = T_MAX;
} else if (this->m_value < 0 && other.m_value < 0 && (this->m_value == T_MIN || other.m_value == T_MIN || ((T_MAX + this->m_value) + other.m_value < (T_MIN + T_MAX)))) {
this->m_value = T_MIN;
} else {
this->m_value += other.m_value;
}
return *this;
}
/**
* Safe implementation of subtraction.
* @param other the amount to subtract
* @note when the subtraction would yield less than T_MIN, it will be T_MIN.
*/
inline OverflowSafeInt& operator -= (const OverflowSafeInt& other)
{
if (this->m_value > 0 && other.m_value < 0 && (T_MAX + other.m_value) < this->m_value) {
this->m_value = T_MAX;
} else if (this->m_value < 0 && other.m_value > 0 && (T_MAX + this->m_value) < (T_MIN + T_MAX) + other.m_value) {
this->m_value = T_MIN;
} else {
this->m_value -= other.m_value;
}
return *this;
}
/* Operators for addition and subtraction */
inline OverflowSafeInt operator + (const OverflowSafeInt& other) const { OverflowSafeInt result = *this; result += other; return result; }
inline OverflowSafeInt operator + (const int other) const { OverflowSafeInt result = *this; result += (int64)other; return result; }
inline OverflowSafeInt operator + (const uint other) const { OverflowSafeInt result = *this; result += (int64)other; return result; }
inline OverflowSafeInt& operator -= (const OverflowSafeInt& other) { return *this += (-other); }
inline OverflowSafeInt operator - (const OverflowSafeInt& other) const { OverflowSafeInt result = *this; result -= other; return result; }
inline OverflowSafeInt operator - (const int other) const { OverflowSafeInt result = *this; result -= (int64)other; return result; }
inline OverflowSafeInt operator - (const uint other) const { OverflowSafeInt result = *this; result -= (int64)other; return result; }
@ -75,10 +91,18 @@ public:
*/
inline OverflowSafeInt& operator *= (const int factor)
{
if (factor != 0 && (T_MAX / abs(factor)) < abs(this->m_value)) {
this->m_value = ((this->m_value < 0) == (factor < 0)) ? T_MAX : T_MIN ;
if (factor == -1) {
this->m_value = (this->m_value == T_MIN) ? T_MAX : -this->m_value;
} else if (factor > 0 && this->m_value > 0 && (T_MAX / factor) < this->m_value) {
this->m_value = T_MAX;
} else if (factor > 0 && this->m_value < 0 && (T_MIN / factor) > this->m_value) {
this->m_value = T_MIN;
} else if (factor < 0 && this->m_value > 0 && (T_MIN / factor) < this->m_value) {
this->m_value = T_MIN;
} else if (factor < 0 && this->m_value < 0 && (T_MAX / factor) > this->m_value) {
this->m_value = T_MAX;
} else {
this->m_value *= factor ;
this->m_value *= factor;
}
return *this;
}

Loading…
Cancel
Save