From 482833d95f8bc959f4ba999f9257bbf4e074c9b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Lucas=20Golini?= Date: Sun, 9 Aug 2026 01:02:46 -0300 Subject: [PATCH] =?UTF-8?q?*=20Fixed=20the=20crash=20in=20src/tools/ecode/?= =?UTF-8?q?globalsearchcontroller.cpp:603.=20Probable=20reproduction:=20?= =?UTF-8?q?=20=201.=20Open=20global=20search.=20=20=202.=20Enter=20a=20sea?= =?UTF-8?q?rch=20term.=20=20=203.=20Start=20=E2=80=9Creplace=20in=20files?= =?UTF-8?q?=E2=80=9D=20with=20Mod+R.=20=20=204.=20Before=20the=20asynchron?= =?UTF-8?q?ous=20search=20finishes,=20switch=20to=20document=20search.=20?= =?UTF-8?q?=20=205.=20Immediately=20reopen=20normal=20global=20search.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The replace tree becomes active as soon as the search starts, but its model is only assigned when the asynchronous result arrives. Reopening normal global search tried to reuse that still-null model and called rowCount() on it. The loader is also closed during this transition, explaining the SceneNode::checkClose() trace from another timing of the same sequence. The fix: - Only transfers replace results when the replace model exists. - Adds a defensive null check to updateGlobalSearchBarResults(). --- src/tools/ecode/globalsearchcontroller.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/tools/ecode/globalsearchcontroller.cpp b/src/tools/ecode/globalsearchcontroller.cpp index 9b4781856..76083621d 100644 --- a/src/tools/ecode/globalsearchcontroller.cpp +++ b/src/tools/ecode/globalsearchcontroller.cpp @@ -601,10 +601,13 @@ void GlobalSearchController::showGlobalSearch( bool searchReplace, mGlobalSearchLayout->findByClass( "replace_box" )->setVisible( searchReplace ); mGlobalSearchBarLayout->find( "buffer_only_mode" )->setVisible( searchReplace ); if ( wasReplaceTree ) { - updateGlobalSearchBarResults( mGlobalSearchTreeReplace->getSearchStr(), - std::static_pointer_cast( - mGlobalSearchTreeReplace->getModelShared() ), - searchReplace, escapeSequenceChk->isChecked() ); + // The replace tree has no model until its asynchronous search completes. + auto model = std::static_pointer_cast( + mGlobalSearchTreeReplace->getModelShared() ); + if ( model ) { + updateGlobalSearchBarResults( mGlobalSearchTreeReplace->getSearchStr(), model, + searchReplace, escapeSequenceChk->isChecked() ); + } } } if ( mGlobalSearchWhereInput && pathFilters ) @@ -697,6 +700,8 @@ void GlobalSearchController::toggleGlobalSearchBar() { void GlobalSearchController::updateGlobalSearchBarResults( const std::string& search, std::shared_ptr model, bool searchReplace, bool isEscaped ) { + if ( !model ) + return; updateGlobalSearchBar(); mGlobalSearchTree->hExtLanguageType = mApp->getProjectConfig().hExtLanguageType; mGlobalSearchTree->setSearchStr( search );