Fix data transfer to wxFileDialogCustomizeHook in non-wxMSW ports

Calling TransferDataFromCustomControls() in custom panel destructor
suffered from two fatal flaws:

1. It happened whether the dialog was accepted or cancelled, while
   we're only supposed to call this function when it's accepted.
2. It was done too late, when the customization hook itself could
   have been already destroyed, as it only has to live until ShowModal()
   returns but doesn't have (and typically doesn't) survive wxFileDialog
   itself.

Fix this by adding TransferDataFromExtraControl() and calling it
explicitly when, and only if, the dialog is accepted.

This fixes accessing invalid stack memory (thanks ASAN!) under GTK and
Mac and allows to remove the ugly workaround from wxMSW code, which can
now also just call TransferDataFromExtraControl().
This commit is contained in:
Vadim Zeitlin 2022-06-16 21:56:03 +02:00
parent a68f8653d9
commit a0ea9ba631
7 changed files with 21 additions and 29 deletions

View file

@ -206,6 +206,9 @@ protected:
// Helper function for native file dialog usage where no wx events
// are processed.
void UpdateExtraControlUI();
// Helper function simply transferring data from custom controls if they
// are used -- must be called if the dialog was accepted.
void TransferDataFromExtraControl();
private:
ExtraControlCreatorFunction m_extraControlCreator;

View file

@ -617,7 +617,6 @@ public:
Panel(wxWindow* parent, wxFileDialogCustomizeHook& customizeHook)
: wxPanel(parent),
wxFileDialogCustomize(this),
m_customizeHook(customizeHook),
m_lastWasRadio(false)
{
// Use a simple horizontal sizer to layout all the controls for now.
@ -628,18 +627,13 @@ public:
sizer->AddSpacer(wxSizerFlags::GetDefaultBorder());
// This will call our own AddXXX().
m_customizeHook.AddCustomControls(*this);
customizeHook.AddCustomControls(*this);
// Now that everything was created, resize and layout.
SetClientSize(sizer->ComputeFittingClientSize(this));
sizer->Layout();
}
virtual ~Panel()
{
m_customizeHook.TransferDataFromCustomControls();
}
// Implement wxFileDialogCustomizeImpl pure virtual methods.
wxFileDialogButtonImpl* AddButton(const wxString& label) wxOVERRIDE
@ -720,8 +714,6 @@ private:
}
wxFileDialogCustomizeHook& m_customizeHook;
bool m_lastWasRadio;
wxDECLARE_NO_COPY_CLASS(Panel);
@ -921,6 +913,12 @@ void wxFileDialogBase::UpdateExtraControlUI()
m_extraControl->UpdateWindowUI(wxUPDATE_UI_RECURSE);
}
void wxFileDialogBase::TransferDataFromExtraControl()
{
if ( m_customizeHook )
m_customizeHook->TransferDataFromCustomControls();
}
void wxFileDialogBase::SetPath(const wxString& path)
{
wxString ext;

View file

@ -366,6 +366,8 @@ void wxGenericFileDialog::OnOk( wxCommandEvent &WXUNUSED(event) )
return;
}
TransferDataFromExtraControl();
EndModal(wxID_OK);
}

View file

@ -370,6 +370,8 @@ void wxFileDialog::OnFakeOk(wxCommandEvent& WXUNUSED(event))
str(gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(m_widget)));
m_dir = wxString::FromUTF8(str);
TransferDataFromExtraControl();
EndDialog(wxID_OK);
}

View file

@ -333,6 +333,8 @@ int wxFileDialog::ShowModal()
if (m_fileName.empty())
return wxID_CANCEL;
else
return wxID_OK;
TransferDataFromExtraControl();
return wxID_OK;
}

View file

@ -1144,24 +1144,7 @@ void wxFileDialog::MSWOnTypeChange(int nFilterIndex)
void wxFileDialog::MSWOnFileOK()
{
if ( m_customizeHook )
{
if ( m_extraControl )
{
// If we've created the old style extra controls even though we're
// using the customize hook, we must delete them now, to ensure
// that TransferDataFromCustomControls() called from the extra
// controls panel destructor is called while the controls still
// exist.
DestroyExtraControl();
}
else // This is the normal case, when using IFileDialog.
{
// Just call TransferDataFromCustomControls() directly, it won't be
// called from anywhere else.
m_customizeHook->TransferDataFromCustomControls();
}
}
TransferDataFromExtraControl();
}
// helper used below in ShowCommFileDialog(): style is used to determine

View file

@ -675,6 +675,8 @@ void wxFileDialog::ModalFinishedCallback(void* panel, int returnCode)
m_filterIndex = m_filterChoice->GetSelection();
else
m_filterIndex = GetMatchingFilterExtension(m_fileName);
TransferDataFromExtraControl();
}
SetReturnCode(wasAccepted ? wxID_OK : wxID_CANCEL);