From c8b1ebc2663fd332362c060898234fbdbb53320b Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Mon, 10 Aug 2026 15:23:21 +0200 Subject: [PATCH] #14505 caf: Defer group box deletion in PdmUiFormLayoutObjectEditor The group boxes were destroyed with a raw delete, which destroys the child widgets immediately and defeats the deleteLater() used by PdmUiFieldEditorHandle to keep field editor widgets alive. When the rebuild is triggered from fieldChangedByUi(), Qt is still using those widgets further up the stack, giving a use-after-free. Hide and detach the group box before scheduling a deferred delete, so it leaves the layout, the visual tree and the focus chain immediately. Detaching first is what plain deleteLater() did not do in issue 9719. --- .../cafPdmUiFormLayoutObjectEditor.cpp | 32 +++++++++++++++---- 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiFormLayoutObjectEditor.cpp b/Fwk/AppFwk/cafUserInterface/cafPdmUiFormLayoutObjectEditor.cpp index 4ee35adcb4..2078ed1ffa 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiFormLayoutObjectEditor.cpp +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiFormLayoutObjectEditor.cpp @@ -60,6 +60,30 @@ #include #include +namespace +{ +//-------------------------------------------------------------------------------------------------- +/// Schedule deletion of a group box without destroying the widgets inside it synchronously. +/// +/// A plain delete destroys the child widgets immediately, which defeats the deleteLater() used by +/// PdmUiFieldEditorHandle to keep field editor widgets alive. When the rebuild is triggered from inside a +/// widget event handler, Qt is still using those widgets further up the stack. +/// See https://github.com/OPM/ResInsight/issues/14505 +/// +/// The group box is hidden and detached from its parent before the deferred delete is scheduled, so it is +/// out of the layout, the visual tree and the focus chain immediately. This is what plain deleteLater() +/// failed to do in https://github.com/OPM/ResInsight/issues/9719 +//-------------------------------------------------------------------------------------------------- +auto scheduleGroupBoxDeletion = []( QMinimizePanel* groupBox ) +{ + if ( !groupBox ) return; + + groupBox->hide(); + groupBox->setParent( nullptr ); + groupBox->deleteLater(); +}; +} // namespace + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -626,11 +650,7 @@ void caf::PdmUiFormLayoutObjectEditor::cleanupBeforeSettingPdmObject() QMinimizePanel* groupBox = groupIt->second; if ( groupBox ) { - // https://github.com/OPM/ResInsight/issues/9719 - // When opening a summary file from the command line, it seems like the groupBoxes are not deleted when - // using groupBox->deleteLater() - - delete groupBox; + scheduleGroupBoxDeletion( groupBox ); } } @@ -721,7 +741,7 @@ void caf::PdmUiFormLayoutObjectEditor::configureAndUpdateUi( const QString& uiCo if ( itNew == m_newGroupBoxes.end() ) { // The old groupBox is not present anymore, get rid of it - if ( !itOld->second.isNull() ) delete itOld->second; + if ( !itOld->second.isNull() ) scheduleGroupBoxDeletion( itOld->second ); } } m_groupBoxes = m_newGroupBoxes;