Fix possible use of dangling window pointer in wxSizer::Insert()
Add the sizer item to the sizers items list only after calling of wxWindowBase::SetContainingSizer() because it can throw (if it asserts and the assert handler throws an exception, as happens in our own unit tests) and then the sizer item would be kept in the sizers items list but m_containingSizer wouldn't be set for the window.
This commit is contained in:
committed by
Vadim Zeitlin
parent
035fc5eb37
commit
18d56818f5
@@ -321,6 +321,10 @@ public:
|
|||||||
// Enable deleting the SizerItem without destroying the contained sizer.
|
// Enable deleting the SizerItem without destroying the contained sizer.
|
||||||
void DetachSizer() { m_sizer = NULL; }
|
void DetachSizer() { m_sizer = NULL; }
|
||||||
|
|
||||||
|
// Enable deleting the SizerItem without resetting the sizer in the
|
||||||
|
// contained window.
|
||||||
|
void DetachWindow() { m_window = NULL; m_kind = Item_None; }
|
||||||
|
|
||||||
virtual wxSize GetSize() const;
|
virtual wxSize GetSize() const;
|
||||||
virtual wxSize CalcMin();
|
virtual wxSize CalcMin();
|
||||||
virtual void SetDimension( const wxPoint& pos, const wxSize& size );
|
virtual void SetDimension( const wxPoint& pos, const wxSize& size );
|
||||||
|
@@ -673,7 +673,35 @@ wxSizer::~wxSizer()
|
|||||||
|
|
||||||
wxSizerItem* wxSizer::DoInsert( size_t index, wxSizerItem *item )
|
wxSizerItem* wxSizer::DoInsert( size_t index, wxSizerItem *item )
|
||||||
{
|
{
|
||||||
m_children.Insert( index, item );
|
// The helper class that solves two problems when
|
||||||
|
// wxWindowBase::SetContainingSizer() throws:
|
||||||
|
// 1. Avoid leaking memory using the scoped pointer to the sizer item.
|
||||||
|
// 2. Disassociate the window from the sizer item to not reset the
|
||||||
|
// containing sizer for the window in the items destructor.
|
||||||
|
class ContainingSizerGuard
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit ContainingSizerGuard( wxSizerItem *item )
|
||||||
|
: m_item(item)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~ContainingSizerGuard()
|
||||||
|
{
|
||||||
|
if ( m_item )
|
||||||
|
m_item->DetachWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
wxSizerItem* Release()
|
||||||
|
{
|
||||||
|
return m_item.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
wxScopedPtr<wxSizerItem> m_item;
|
||||||
|
};
|
||||||
|
|
||||||
|
ContainingSizerGuard guard( item );
|
||||||
|
|
||||||
if ( item->GetWindow() )
|
if ( item->GetWindow() )
|
||||||
item->GetWindow()->SetContainingSizer( this );
|
item->GetWindow()->SetContainingSizer( this );
|
||||||
@@ -681,7 +709,9 @@ wxSizerItem* wxSizer::DoInsert( size_t index, wxSizerItem *item )
|
|||||||
if ( item->GetSizer() )
|
if ( item->GetSizer() )
|
||||||
item->GetSizer()->SetContainingWindow( m_containingWindow );
|
item->GetSizer()->SetContainingWindow( m_containingWindow );
|
||||||
|
|
||||||
return item;
|
m_children.Insert( index, item );
|
||||||
|
|
||||||
|
return guard.Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxSizer::SetContainingWindow(wxWindow *win)
|
void wxSizer::SetContainingWindow(wxWindow *win)
|
||||||
|
Reference in New Issue
Block a user