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

View File

@ -271,18 +271,34 @@ void MODULE::Remove( BOARD_ITEM* aBoardItem )
{ {
case PCB_MODULE_TEXT_T: case PCB_MODULE_TEXT_T:
// Only user texts can be removed this way. Reference and value are not hold in the DLIST. // 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 // no break
case PCB_MODULE_EDGE_T: case PCB_MODULE_EDGE_T:
m_drawings.erase( std::remove_if( m_drawings.begin(), m_drawings.end(), for( auto it = m_drawings.begin(); it != m_drawings.end(); ++it )
[aBoardItem]( BOARD_ITEM* aItem ) { return aItem == aBoardItem; } ) ); {
if( *it == aBoardItem )
{
m_drawings.erase( it );
break;
}
}
break; break;
case PCB_PAD_T: case PCB_PAD_T:
m_pads.erase( std::remove_if( m_pads.begin(), m_pads.end(), for( auto it = m_pads.begin(); it != m_pads.end(); ++it )
[aBoardItem]( BOARD_ITEM* aItem ) { return aItem == aBoardItem; } ) ); {
if( *it == static_cast<D_PAD*>( aBoardItem ) )
{
m_pads.erase( it );
break;
}
}
break; break;
default: default:

View File

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