From 1bb6b7acddc7dfe0c8b5fc566cafd555d971613a Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Fri, 3 Mar 2023 12:53:22 +0000 Subject: [PATCH] Overflow safety. Potential fix for some or all of https://gitlab.com/kicad/code/kicad/-/issues/13969 (cherry picked from commit 2f2a00c30743d48d0e2eed46e38dcf8b3081142f) --- libs/kimath/include/math/vector2d.h | 28 ++++++++++++++++++++++++--- libs/kimath/src/geometry/seg.cpp | 30 +++++++++++++++++++---------- 2 files changed, 45 insertions(+), 13 deletions(-) diff --git a/libs/kimath/include/math/vector2d.h b/libs/kimath/include/math/vector2d.h index 79a804e714..e57cbbb3c4 100644 --- a/libs/kimath/include/math/vector2d.h +++ b/libs/kimath/include/math/vector2d.h @@ -99,8 +99,19 @@ public: template VECTOR2( const VECTOR2& aVec ) { - x = (T) aVec.x; - y = (T) aVec.y; + if( std::is_same::value ) + { + CastingType minI = static_cast( std::numeric_limits::min() ); + CastingType maxI = static_cast( std::numeric_limits::max() ); + + x = static_cast( std::max( minI, std::min( aVec.x, maxI ) ) ); + y = static_cast( std::max( minI, std::min( aVec.y, maxI ) ) ); + } + else + { + x = static_cast( aVec.x ); + y = static_cast( aVec.y ); + } } /// Copy a vector @@ -114,7 +125,18 @@ public: template VECTOR2 operator()() const { - return VECTOR2( (CastedType) x, (CastedType) y ); + if( std::is_same::value ) + { + T minI = static_cast( std::numeric_limits::min() ); + T maxI = static_cast( std::numeric_limits::max() ); + + return VECTOR2( static_cast( std::max( minI, std::min( x, maxI ) ) ), + static_cast( std::max( minI, std::min( y, maxI ) ) ) ); + } + else + { + return VECTOR2( static_cast( x ), static_cast( y ) ); + } } /** diff --git a/libs/kimath/src/geometry/seg.cpp b/libs/kimath/src/geometry/seg.cpp index 37e2ab3006..f94f4b366f 100644 --- a/libs/kimath/src/geometry/seg.cpp +++ b/libs/kimath/src/geometry/seg.cpp @@ -171,8 +171,16 @@ bool SEG::intersects( const SEG& aSeg, bool aIgnoreEndpoints, bool aLines, VECTO if( aPt ) { - *aPt = VECTOR2I( aSeg.A.x + rescale( q, (ecoord) f.x, d ), - aSeg.A.y + rescale( q, (ecoord) f.y, d ) ); + VECTOR2 result( aSeg.A.x + rescale( q, (ecoord) f.x, d ), + aSeg.A.y + rescale( q, (ecoord) f.y, d ) ); + + if( abs( result.x ) >= std::numeric_limits::max() + || abs( result.y ) >= std::numeric_limits::max() ) + { + return false; + } + + *aPt = VECTOR2I( (int) result.x, (int) result.y ); } return true; @@ -273,10 +281,10 @@ const VECTOR2I SEG::NearestPoint( const VECTOR2I& aP ) const else if( t > l_squared ) return B; - int xp = rescale( t, (ecoord) d.x, l_squared ); - int yp = rescale( t, (ecoord) d.y, l_squared ); + ecoord xp = rescale( t, (ecoord) d.x, l_squared ); + ecoord yp = rescale( t, (ecoord) d.y, l_squared ); - return A + VECTOR2I( xp, yp ); + return VECTOR2( A.x + xp, A.y + yp ); } @@ -285,17 +293,19 @@ const VECTOR2I SEG::ReflectPoint( const VECTOR2I& aP ) const VECTOR2I d = B - A; VECTOR2I::extended_type l_squared = d.Dot( d ); VECTOR2I::extended_type t = d.Dot( aP - A ); - VECTOR2I c; + VECTOR2 c; if( !l_squared ) + { c = aP; + } else { c.x = A.x + rescale( t, static_cast( d.x ), l_squared ); c.y = A.y + rescale( t, static_cast( d.y ), l_squared ); } - return 2 * c - aP; + return VECTOR2( 2 * c.x - aP.x, 2 * c.y - aP.y ); } @@ -309,10 +319,10 @@ VECTOR2I SEG::LineProject( const VECTOR2I& aP ) const ecoord t = d.Dot( aP - A ); - int xp = rescale( t, ecoord{ d.x }, l_squared ); - int yp = rescale( t, ecoord{ d.y }, l_squared ); + ecoord xp = rescale( t, ecoord{ d.x }, l_squared ); + ecoord yp = rescale( t, ecoord{ d.y }, l_squared ); - return A + VECTOR2I( xp, yp ); + return VECTOR2( A.x + xp, A.y + yp ); }