1
0
forked from 0ad/0ad

Avoid overflow in UnitMotion.

ComputeTargetPosition called Dot() with large enough vectors that it
overflowed. Avoid that by not actually doing the full dot product.

Reported by: Itms
Fixes #5852

Differential Revision: https://code.wildfiregames.com/D3061
This was SVN commit r24152.
This commit is contained in:
wraitii 2020-11-09 13:25:50 +00:00
parent 055a659685
commit bb8456691b
3 changed files with 16 additions and 5 deletions

View File

@ -204,6 +204,7 @@ public:
/**
* Compute the dot product of this vector with another.
* Likely to overflow if both vectors are large-ish (around the 200 range).
*/
fixed Dot(const CFixedVector2D& v) const
{
@ -219,6 +220,16 @@ public:
return ret;
}
/**
* @return -1, 0 or 1 if this and @v face respectively opposite directions, perpendicular, or same directions.
*/
int RelativeOrientation(const CFixedVector2D& v) const
{
i64 x = MUL_I64_I32_I32(X.GetInternalValue(), v.X.GetInternalValue());
i64 y = MUL_I64_I32_I32(Y.GetInternalValue(), v.Y.GetInternalValue());
return x > -y ? 1 : x < -y ? -1 : 0;
}
CFixedVector2D Perpendicular() const
{
return CFixedVector2D(Y, -X);

View File

@ -1149,7 +1149,7 @@ bool CCmpUnitMotion::ComputeTargetPosition(CFixedVector2D& out, const MoveReques
// Check if we anticipate the target to go through us, in which case we shouldn't anticipate
// (or e.g. units fleeing might suddenly turn around towards their attacker).
if ((out - cmpPosition->GetPosition2D()).Dot(tempPos - cmpPosition->GetPosition2D()) >= fixed::Zero())
if ((out - cmpPosition->GetPosition2D()).RelativeOrientation(tempPos - cmpPosition->GetPosition2D()) >= 0)
out = tempPos;
}
}

View File

@ -342,13 +342,13 @@ static bool SquareSAT(const CFixedVector2D& a, const CFixedVector2D& axis, const
fixed hh = halfSize.Y;
CFixedVector2D p = axis.Perpendicular();
if (p.Dot((u.Multiply(hw) + v.Multiply(hh)) - a) <= fixed::Zero())
if (p.RelativeOrientation(u.Multiply(hw) + v.Multiply(hh) - a) <= 0)
return true;
if (p.Dot((u.Multiply(hw) - v.Multiply(hh)) - a) <= fixed::Zero())
if (p.RelativeOrientation(u.Multiply(hw) - v.Multiply(hh) - a) <= 0)
return true;
if (p.Dot((-u.Multiply(hw) - v.Multiply(hh)) - a) <= fixed::Zero())
if (p.RelativeOrientation(-u.Multiply(hw) - v.Multiply(hh) - a) <= 0)
return true;
if (p.Dot((-u.Multiply(hw) + v.Multiply(hh)) - a) <= fixed::Zero())
if (p.RelativeOrientation(-u.Multiply(hw) + v.Multiply(hh) - a) <= 0)
return true;
return false;