Prevent segfault when undoing or resetting non-hotkey rows

This is caused by:

* Not checking the hotkey data is not null when performing a
  hotkey action
* Allowing hotkey actions on non-hotkey rows.

This fixes both of these, and adds an assert to warn if someone
does manage to fire a hotkey action on a non-hotkey row (but it
won't crash).

This is a ported version of commit 704615721 on the master branch.

Fixes: lp:1794756
* https://bugs.launchpad.net/kicad/+bug/1794756
This commit is contained in:
John Beard 2018-09-27 14:44:03 +01:00 committed by Wayne Stambaugh
parent f56ea6bf3c
commit f591f8741a
2 changed files with 43 additions and 11 deletions

View File

@ -253,6 +253,18 @@ WIDGET_HOTKEY_CLIENT_DATA* WIDGET_HOTKEY_LIST::GetSelHKClientData()
}
WIDGET_HOTKEY_CLIENT_DATA* WIDGET_HOTKEY_LIST::getExpectedHkClientData( wxTreeListItem aItem )
{
const auto hkdata = GetHKClientData( aItem );
// This probably means a hotkey-only action is being attempted on
// a row that is not a hotkey (like a section heading)
wxASSERT_MSG( hkdata != nullptr, "No hotkey data found for list item" );
return hkdata;
}
void WIDGET_HOTKEY_LIST::UpdateFromClientData()
{
for( wxTreeListItem i = GetFirstItem(); i.IsOk(); i = GetNextItem( i ) )
@ -285,13 +297,10 @@ void WIDGET_HOTKEY_LIST::LoadSection( EDA_HOTKEY_CONFIG* aSection )
void WIDGET_HOTKEY_LIST::EditItem( wxTreeListItem aItem )
{
WIDGET_HOTKEY_CLIENT_DATA* hkdata = GetHKClientData( aItem );
WIDGET_HOTKEY_CLIENT_DATA* hkdata = getExpectedHkClientData( aItem );
if( !hkdata )
{
// Activated item was not a hotkey row
return;
}
wxString name = GetItemText( aItem, 0 );
wxString current_key = GetItemText( aItem, 1 );
@ -299,7 +308,7 @@ void WIDGET_HOTKEY_LIST::EditItem( wxTreeListItem aItem )
wxKeyEvent key_event = HK_PROMPT_DIALOG::PromptForKey( GetParent(), name, current_key );
long key = MapKeypressToKeycode( key_event );
if( hkdata && key )
if( key )
{
// See if this key code is handled in hotkeys names list
bool exists;
@ -327,7 +336,11 @@ void WIDGET_HOTKEY_LIST::EditItem( wxTreeListItem aItem )
void WIDGET_HOTKEY_LIST::ResetItem( wxTreeListItem aItem )
{
WIDGET_HOTKEY_CLIENT_DATA* hkdata = GetHKClientData( aItem );
WIDGET_HOTKEY_CLIENT_DATA* hkdata = getExpectedHkClientData( aItem );
if( !hkdata )
return;
EDA_HOTKEY* hk = &hkdata->GetHotkey();
for( size_t sec_index = 0; sec_index < m_sections.size(); ++sec_index )
@ -356,9 +369,14 @@ void WIDGET_HOTKEY_LIST::ResetItem( wxTreeListItem aItem )
void WIDGET_HOTKEY_LIST::ResetItemToDefault( wxTreeListItem aItem )
{
WIDGET_HOTKEY_CLIENT_DATA* hkdata = GetHKClientData( aItem );
WIDGET_HOTKEY_CLIENT_DATA* hkdata = getExpectedHkClientData( aItem );
if( !hkdata )
return;
EDA_HOTKEY* hk = &hkdata->GetHotkey();
hk->ResetKeyCodeToDefault();
UpdateFromClientData();
}
@ -376,10 +394,17 @@ void WIDGET_HOTKEY_LIST::OnContextMenu( wxTreeListEvent& aEvent )
wxMenu menu;
menu.Append( ID_EDIT, _( "Edit..." ) );
menu.Append( ID_RESET, _( "Undo Changes" ) );
menu.Append( ID_DEFAULT, _( "Restore Default" ) );
menu.Append( wxID_SEPARATOR );
WIDGET_HOTKEY_CLIENT_DATA* hkdata = GetHKClientData( m_context_menu_item );
// Some actions only apply if the row is hotkey data
if( hkdata )
{
menu.Append( ID_EDIT, _( "Edit..." ) );
menu.Append( ID_RESET, _( "Undo Changes" ) );
menu.Append( ID_DEFAULT, _( "Restore Default" ) );
menu.Append( wxID_SEPARATOR );
}
menu.Append( ID_RESET_ALL, _( "Undo All Changes" ) );
menu.Append( ID_DEFAULT_ALL, _( "Restore All to Default" ) );

View File

@ -72,6 +72,13 @@ class WIDGET_HOTKEY_LIST : public TWO_COLUMN_TREE_LIST
*/
WIDGET_HOTKEY_CLIENT_DATA* GetSelHKClientData();
/**
* Get the WIDGET_HOTKEY_CLIENT_DATA form an item and assert if it isn't
* found. This is for use when the data not being present indicates an
* error.
*/
WIDGET_HOTKEY_CLIENT_DATA* getExpectedHkClientData( wxTreeListItem aItem );
/**
* Method UpdateFromClientData
* Refresh the visible text on the widget from the rows' client data objects.