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>
VECTOR2( const VECTOR2<CastingType>& aVec )
{
x = (T) aVec.x;
y = (T) aVec.y;
if( std::is_same<T, int>::value )
{
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
@ -114,7 +125,18 @@ public:
template <typename CastedType>
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 )
{
*aPt = VECTOR2I( aSeg.A.x + rescale( q, (ecoord) f.x, d ),
aSeg.A.y + rescale( q, (ecoord) f.y, d ) );
VECTOR2<ecoord> 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<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;
@ -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<ecoord>( 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<ecoord> c;
if( !l_squared )
{
c = aP;
}
else
{
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 );
}
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 );
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<ecoord>( A.x + xp, A.y + yp );
}