router: fix use-after-free crash in single trace shove routing when m_endItem's owning NODE is erased by the springback algorithm.
Fixes: https://gitlab.com/kicad/code/kicad/-/issues/9994
This commit is contained in:
parent
1ca90f31bf
commit
2ae3a83b54
|
@ -762,6 +762,12 @@ bool LINE_PLACER::rhShoveOnly( const VECTOR2I& aP, LINE& aNewHead )
|
|||
return false;
|
||||
}
|
||||
|
||||
if( m_endItem )
|
||||
{
|
||||
// Make sure the springback algorithm won't erase the NODE that owns m_endItem.
|
||||
m_shove->SetSpringbackDoNotTouchNode( m_endItem->Owner() );
|
||||
}
|
||||
|
||||
SHOVE::SHOVE_STATUS status = m_shove->ShoveLines( l );
|
||||
|
||||
m_currentNode = m_shove->CurrentNode();
|
||||
|
@ -1105,6 +1111,7 @@ bool LINE_PLACER::Start( const VECTOR2I& aP, ITEM* aStartItem )
|
|||
m_placingVia = false;
|
||||
m_chainedPlacement = false;
|
||||
m_fixedTail.Clear();
|
||||
m_endItem = nullptr;
|
||||
|
||||
setInitialDirection( Settings().InitialDirection() );
|
||||
|
||||
|
@ -1208,6 +1215,8 @@ bool LINE_PLACER::Move( const VECTOR2I& aP, ITEM* aEndItem )
|
|||
m_lastNode = nullptr;
|
||||
}
|
||||
|
||||
m_endItem = aEndItem;
|
||||
|
||||
bool reachesEnd = route( p );
|
||||
|
||||
current = Trace();
|
||||
|
|
|
@ -353,6 +353,7 @@ private:
|
|||
LINE m_currentTrace;
|
||||
|
||||
ITEM* m_startItem;
|
||||
ITEM* m_endItem;
|
||||
|
||||
bool m_idle;
|
||||
bool m_chainedPlacement;
|
||||
|
|
|
@ -170,6 +170,7 @@ SHOVE::SHOVE( NODE* aWorld, ROUTER* aRouter ) :
|
|||
m_iter = 0;
|
||||
m_multiLineMode = false;
|
||||
m_restrictSpringbackTagId = 0;
|
||||
m_springbackDoNotTouchNode = nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
@ -788,6 +789,11 @@ NODE* SHOVE::reduceSpringback( const ITEM_SET& aHeadSet, VIA_HANDLE& aDraggedVia
|
|||
{
|
||||
SPRINGBACK_TAG& spTag = m_nodeStack.back();
|
||||
|
||||
// Prevent the springback algo from erasing NODEs that might contain items used by the ROUTER_TOOL/LINE_PLACER.
|
||||
// I noticed this can happen for the endItem provided to LINE_PLACER::Move() and cause a nasty crash.
|
||||
if( spTag.m_node == m_springbackDoNotTouchNode )
|
||||
break;
|
||||
|
||||
OPT<OBSTACLE> obs = spTag.m_node->CheckColliding( aHeadSet );
|
||||
|
||||
if( !obs && !spTag.m_locked )
|
||||
|
@ -1881,5 +1887,11 @@ void SHOVE::DisablePostShoveOptimizations( int aMask )
|
|||
m_optFlagDisableMask = aMask;
|
||||
}
|
||||
|
||||
|
||||
void SHOVE::SetSpringbackDoNotTouchNode( NODE *aNode )
|
||||
{
|
||||
m_springbackDoNotTouchNode = aNode;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -90,6 +90,7 @@ public:
|
|||
bool RewindSpringbackTo( NODE* aNode );
|
||||
bool RewindToLastLockedNode();
|
||||
void DisablePostShoveOptimizations( int aMask );
|
||||
void SetSpringbackDoNotTouchNode( NODE *aNode );
|
||||
|
||||
private:
|
||||
typedef std::vector<SHAPE_LINE_CHAIN> HULL_SET;
|
||||
|
@ -171,6 +172,7 @@ private:
|
|||
|
||||
NODE* m_root;
|
||||
NODE* m_currentNode;
|
||||
NODE* m_springbackDoNotTouchNode;
|
||||
int m_restrictSpringbackTagId;
|
||||
|
||||
OPT_LINE m_newHead;
|
||||
|
|
Loading…
Reference in New Issue