Fix crash when deleting all wxTreeListCtrl items with wxGTK3

GTK+ 3 (but not the generic version nor even GTK+ 2, apparently) sends
"selection changed" event from gtk_tree_model_row_deleted() when
deleting the currently selected row, which resulted in sending of
wxEVT_TREELIST_SELECTION_CHANGED events with invalid wxTreeListItem,
containing a dangling pointer, and a crash in the treelist sample when
trying to dump it.

Avoid this by clearing the model (and hence generating these events)
first and deleting the items only afterwards.

Also add a trivial unit test for wxTreeListCtrl::DeleteAllItems(), which
doesn't even allow to reproduce this bug, but is still probably better
to have than not to.

Closes #18045.
This commit is contained in:
Vadim Zeitlin 2018-01-17 10:24:55 +01:00
parent 321c9d5f30
commit 1dd102d741
2 changed files with 15 additions and 2 deletions

View File

@ -572,12 +572,16 @@ void wxTreeListModel::DeleteItem(Node* item)
void wxTreeListModel::DeleteAllItems()
{
// Note that this must be called before actually deleting the items as
// clearing GTK+ wxDataViewCtrl results in SELECTION_CHANGED events being
// sent and these events contain pointers to the model items, so they must
// still be valid.
Cleared();
while ( m_root->GetChild() )
{
m_root->DeleteChild();
}
Cleared();
}
const wxString& wxTreeListModel::GetItemText(Node* item, unsigned col) const

View File

@ -39,6 +39,7 @@ private:
CPPUNIT_TEST( Traversal );
CPPUNIT_TEST( ItemText );
CPPUNIT_TEST( ItemCheck );
CPPUNIT_TEST( DeleteAll );
CPPUNIT_TEST_SUITE_END();
// Create the control with the given style.
@ -55,6 +56,7 @@ private:
void Traversal();
void ItemText();
void ItemCheck();
void DeleteAll();
// The control itself.
@ -231,4 +233,11 @@ void TreeListCtrlTestCase::ItemCheck()
m_treelist->GetCheckedState(m_code) );
}
void TreeListCtrlTestCase::DeleteAll()
{
m_treelist->DeleteAllItems();
CHECK( !m_treelist->GetFirstChild(m_treelist->GetRootItem()).IsOk() );
}
#endif // wxUSE_TREELISTCTRL