mirror of
https://github.com/OpenTTD/OpenTTD.git
synced 2025-03-10 08:00:05 +00:00
Fix: OverflowSafeInt could underflow
Notably, a company with an extremely negative amount of money would suddenly become very rich
This commit is contained in:
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,8 +91,16 @@ 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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user