Overflow safety.

Potential fix for some or all of
https://gitlab.com/kicad/code/kicad/-/issues/13969

(cherry picked from commit 2f2a00c307)
This commit is contained in:
Jeff Young 2023-03-03 12:53:22 +00:00
parent adc7a3ba4a
commit 1bb6b7acdd
2 changed files with 45 additions and 13 deletions

View File

@ -99,8 +99,19 @@ public:
template <typename CastingType> template <typename CastingType>
VECTOR2( const VECTOR2<CastingType>& aVec ) VECTOR2( const VECTOR2<CastingType>& aVec )
{ {
x = (T) aVec.x; if( std::is_same<T, int>::value )
y = (T) aVec.y; {
CastingType minI = static_cast<CastingType>( std::numeric_limits<int>::min() );
CastingType maxI = static_cast<CastingType>( std::numeric_limits<int>::max() );
x = static_cast<int>( std::max( minI, std::min( aVec.x, maxI ) ) );
y = static_cast<int>( std::max( minI, std::min( aVec.y, maxI ) ) );
}
else
{
x = static_cast<T>( aVec.x );
y = static_cast<T>( aVec.y );
}
} }
/// Copy a vector /// Copy a vector
@ -114,7 +125,18 @@ public:
template <typename CastedType> template <typename CastedType>
VECTOR2<CastedType> operator()() const VECTOR2<CastedType> operator()() const
{ {
return VECTOR2<CastedType>( (CastedType) x, (CastedType) y ); if( std::is_same<CastedType, int>::value )
{
T minI = static_cast<T>( std::numeric_limits<int>::min() );
T maxI = static_cast<T>( std::numeric_limits<int>::max() );
return VECTOR2<int>( static_cast<int>( std::max( minI, std::min( x, maxI ) ) ),
static_cast<int>( std::max( minI, std::min( y, maxI ) ) ) );
}
else
{
return VECTOR2<CastedType>( static_cast<CastedType>( x ), static_cast<CastedType>( y ) );
}
} }
/** /**

View File

@ -171,8 +171,16 @@ bool SEG::intersects( const SEG& aSeg, bool aIgnoreEndpoints, bool aLines, VECTO
if( aPt ) if( aPt )
{ {
*aPt = VECTOR2I( aSeg.A.x + rescale( q, (ecoord) f.x, d ), VECTOR2<ecoord> result( aSeg.A.x + rescale( q, (ecoord) f.x, d ),
aSeg.A.y + rescale( q, (ecoord) f.y, d ) ); aSeg.A.y + rescale( q, (ecoord) f.y, d ) );
if( abs( result.x ) >= std::numeric_limits<VECTOR2I::coord_type>::max()
|| abs( result.y ) >= std::numeric_limits<VECTOR2I::coord_type>::max() )
{
return false;
}
*aPt = VECTOR2I( (int) result.x, (int) result.y );
} }
return true; return true;
@ -273,10 +281,10 @@ const VECTOR2I SEG::NearestPoint( const VECTOR2I& aP ) const
else if( t > l_squared ) else if( t > l_squared )
return B; return B;
int xp = rescale( t, (ecoord) d.x, l_squared ); ecoord xp = rescale( t, (ecoord) d.x, l_squared );
int yp = rescale( t, (ecoord) d.y, l_squared ); ecoord yp = rescale( t, (ecoord) d.y, l_squared );
return A + VECTOR2I( xp, yp ); return VECTOR2<ecoord>( A.x + xp, A.y + yp );
} }
@ -285,17 +293,19 @@ const VECTOR2I SEG::ReflectPoint( const VECTOR2I& aP ) const
VECTOR2I d = B - A; VECTOR2I d = B - A;
VECTOR2I::extended_type l_squared = d.Dot( d ); VECTOR2I::extended_type l_squared = d.Dot( d );
VECTOR2I::extended_type t = d.Dot( aP - A ); VECTOR2I::extended_type t = d.Dot( aP - A );
VECTOR2I c; VECTOR2<ecoord> c;
if( !l_squared ) if( !l_squared )
{
c = aP; c = aP;
}
else else
{ {
c.x = A.x + rescale( t, static_cast<VECTOR2I::extended_type>( d.x ), l_squared ); c.x = A.x + rescale( t, static_cast<VECTOR2I::extended_type>( d.x ), l_squared );
c.y = A.y + rescale( t, static_cast<VECTOR2I::extended_type>( d.y ), l_squared ); c.y = A.y + rescale( t, static_cast<VECTOR2I::extended_type>( d.y ), l_squared );
} }
return 2 * c - aP; return VECTOR2<ecoord>( 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 ); ecoord t = d.Dot( aP - A );
int xp = rescale( t, ecoord{ d.x }, l_squared ); ecoord xp = rescale( t, ecoord{ d.x }, l_squared );
int yp = rescale( t, ecoord{ d.y }, l_squared ); ecoord yp = rescale( t, ecoord{ d.y }, l_squared );
return A + VECTOR2I( xp, yp ); return VECTOR2<ecoord>( A.x + xp, A.y + yp );
} }