Defer template list refresh after duplication to prevent use-after-free

Duplicating a template copies files that trigger OnFileSystemEvent,
which starts a 500ms refresh timer. The subsequent DisplayInfoMessage
runs a modal event loop during which the timer fires, calling
RefreshTemplateList which destroys all TEMPLATE_WIDGETs including the
one whose onDuplicateTemplate is still on the call stack. When the
modal dialog closes, any further member access is undefined behavior.

Defer both the info message and the refresh via CallAfter so they
execute after the event handler has returned and the call stack is
clean.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/22931
This commit is contained in:
Seth Hillbrand
2026-02-03 14:49:18 -08:00
parent e63087e288
commit f22dba503c
+13 -3
View File
@@ -480,10 +480,20 @@ void TEMPLATE_WIDGET::onDuplicateTemplate( wxCommandEvent& event )
}
}
DisplayInfoMessage( m_dialog, wxString::Format( _( "Template duplicated successfully to '%s'." ),
newTemplatePath ) );
// The file copy triggers OnFileSystemEvent which starts a refresh timer. If we show a
// modal info dialog here, the timer fires during the modal event loop and destroys this
// TEMPLATE_WIDGET while we're still on its call stack. Defer both the message and the
// refresh to run after the current event handler returns.
DIALOG_TEMPLATE_SELECTOR* dlg = m_dialog;
m_dialog->RefreshTemplateList();
dlg->CallAfter(
[dlg, newTemplatePath]()
{
DisplayInfoMessage( dlg, wxString::Format( _( "Template duplicated successfully"
" to '%s'." ),
newTemplatePath ) );
dlg->RefreshTemplateList();
} );
}