From bb8456691b72aacdd045e94a57a6dcf5241ef87d Mon Sep 17 00:00:00 2001 From: wraitii Date: Mon, 9 Nov 2020 13:25:50 +0000 Subject: [PATCH] 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. --- source/maths/FixedVector2D.h | 11 +++++++++++ source/simulation2/components/CCmpUnitMotion.cpp | 2 +- source/simulation2/helpers/Geometry.cpp | 8 ++++---- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/source/maths/FixedVector2D.h b/source/maths/FixedVector2D.h index 87c8fd4916..100c42597e 100644 --- a/source/maths/FixedVector2D.h +++ b/source/maths/FixedVector2D.h @@ -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); diff --git a/source/simulation2/components/CCmpUnitMotion.cpp b/source/simulation2/components/CCmpUnitMotion.cpp index 92722eead2..b8635700fe 100644 --- a/source/simulation2/components/CCmpUnitMotion.cpp +++ b/source/simulation2/components/CCmpUnitMotion.cpp @@ -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; } } diff --git a/source/simulation2/helpers/Geometry.cpp b/source/simulation2/helpers/Geometry.cpp index f7563969ad..4be531c8ce 100644 --- a/source/simulation2/helpers/Geometry.cpp +++ b/source/simulation2/helpers/Geometry.cpp @@ -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;