pcbnew: Fix STL blunder when deleting

Deleting objects from a container will invalidate the iterator that
contains the object.  Correct deleting requires capturing the iterator
returned by the erase function.

Fixes: lp:1832331
* https://bugs.launchpad.net/kicad/+bug/1832331
This commit is contained in:
Seth Hillbrand 2019-06-11 07:47:54 -07:00
parent 7726b039b2
commit 32052d953f
3 changed files with 51 additions and 34 deletions

View File

@ -8,7 +8,7 @@
*
* Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr
* Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 1992-2019 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -128,7 +128,7 @@ void BOARD_ITEM::DeleteStructure()
{
auto parent = GetParent();
if( parent && GetList() )
if( parent )
parent->Remove( this );
delete this;

View File

@ -271,18 +271,34 @@ void MODULE::Remove( BOARD_ITEM* aBoardItem )
{
case PCB_MODULE_TEXT_T:
// Only user texts can be removed this way. Reference and value are not hold in the DLIST.
assert( static_cast<TEXTE_MODULE*>( aBoardItem )->GetType() == TEXTE_MODULE::TEXT_is_DIVERS );
wxCHECK_RET(
static_cast<TEXTE_MODULE*>( aBoardItem )->GetType() == TEXTE_MODULE::TEXT_is_DIVERS,
"Please report this bug: Invalid remove operation on required text" );
// no break
case PCB_MODULE_EDGE_T:
m_drawings.erase( std::remove_if( m_drawings.begin(), m_drawings.end(),
[aBoardItem]( BOARD_ITEM* aItem ) { return aItem == aBoardItem; } ) );
for( auto it = m_drawings.begin(); it != m_drawings.end(); ++it )
{
if( *it == aBoardItem )
{
m_drawings.erase( it );
break;
}
}
break;
case PCB_PAD_T:
m_pads.erase( std::remove_if( m_pads.begin(), m_pads.end(),
[aBoardItem]( BOARD_ITEM* aItem ) { return aItem == aBoardItem; } ) );
for( auto it = m_pads.begin(); it != m_pads.end(); ++it )
{
if( *it == static_cast<D_PAD*>( aBoardItem ) )
{
m_pads.erase( it );
break;
}
}
break;
default:

View File

@ -2,6 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2014-2016 CERN
* Copyright (C) 2019 KiCad Developers, see AUTHORS.txt for contributors.
* @author Maciej Suminski <maciej.suminski@cern.ch>
*
* This program is free software; you can redistribute it and/or
@ -24,36 +25,37 @@
#include <cstdint>
#include "pcbnew_control.h"
#include "pcb_actions.h"
#include "selection_tool.h"
#include "edit_tool.h"
#include "pcbnew_picker_tool.h"
#include "pcb_editor_control.h"
#include "grid_helper.h"
#include <kiway.h>
#include "pcb_actions.h"
#include "pcb_editor_control.h"
#include "pcbnew_control.h"
#include "pcbnew_picker_tool.h"
#include "selection_tool.h"
#include <3d_viewer/eda_3d_viewer.h>
#include <bitmaps.h>
#include <board_commit.h>
#include <class_board.h>
#include <class_board_item.h>
#include <class_module.h>
#include <class_track.h>
#include <class_zone.h>
#include <pcb_screen.h>
#include <confirm.h>
#include <properties.h>
#include <io_mgr.h>
#include <kicad_plugin.h>
#include <kicad_clipboard.h>
#include <3d_viewer/eda_3d_viewer.h>
#include <pcbnew_id.h>
#include <pcb_edit_frame.h>
#include <pcb_draw_panel_gal.h>
#include <connectivity/connectivity_data.h>
#include <tool/tool_manager.h>
#include <gal/graphics_abstraction_layer.h>
#include <view/view_controls.h>
#include <pcb_painter.h>
#include <io_mgr.h>
#include <kicad_clipboard.h>
#include <kicad_plugin.h>
#include <kiway.h>
#include <origin_viewitem.h>
#include <board_commit.h>
#include <bitmaps.h>
#include <pcb_draw_panel_gal.h>
#include <pcb_edit_frame.h>
#include <pcb_painter.h>
#include <pcb_screen.h>
#include <pcbnew_id.h>
#include <properties.h>
#include <tool/tool_manager.h>
#include <view/view_controls.h>
#include <functional>
#include <footprint_viewer_frame.h>
@ -709,22 +711,21 @@ int PCBNEW_CONTROL::Paste( const TOOL_EVENT& aEvent )
auto oldModule = static_cast<MODULE*>( clipItem );
auto newModule = board()->GetFirstModule();
for( auto it = oldModule->Pads().begin(); it != oldModule->Pads().end(); it++ )
for( auto pad : oldModule->Pads() )
{
auto pad = *it;
oldModule->Remove( pad );
pad->SetParent( newModule );
items.push_back( pad );
}
for( auto it = oldModule->GraphicalItems().begin();
it != oldModule->GraphicalItems().end(); it++ )
oldModule->Pads().clear();
for( auto item : oldModule->GraphicalItems() )
{
auto item = *it;
oldModule->Remove( item );
item->SetParent( newModule );
items.push_back( item );
}
oldModule->GraphicalItems().clear();
}
else
{