From f22e96b2f593021ea81074a64edd553cde9c6f55 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Sun, 11 Oct 2026 18:43:35 +0200 Subject: [PATCH] Guard contour map projection against missing eclipse case RimEclipseContourMapProjection::updateGridInformation() dereferences eclipseCase() unchecked. It is null when the contour map view has no case, e.g. when a grid calculation triggers updateAll3dViews. updateGridInformation() resets the grid and projection and returns when the case or its data is missing. generateResultsIfNecessary() returns when there is no projection, and computeMinMaxValuesAllTimeSteps() handles a missing case. New test RimEclipseContourMapProjection.GenerateResultsWithoutEclipseCase. Call stack: [3] RimEclipseCase::eclipseCaseData() at ResInsight/ApplicationLibCode/ProjectDataModel/RimEclipseCase.cpp:196 [4] RimEclipseContourMapProjection::updateGridInformation() at ResInsight/ApplicationLibCode/ProjectDataModel/ContourMap/RimEclipseContourMapProjection.cpp:250 [5] RimContourMapProjection::generateResultsIfNecessary(int) at ResInsight/ApplicationLibCode/ProjectDataModel/ContourMap/RimContourMapProjection.cpp:138 [6] RimEclipseContourMapProjection::clearGridMappingAndRedraw() at ResInsight/ApplicationLibCode/ProjectDataModel/ContourMap/RimEclipseContourMapProjection.cpp:167 [7] RimReloadCaseTools::updateAll3dViews(RimEclipseCase*) at ResInsight/ApplicationLibCode/ProjectDataModel/RimReloadCaseTools.cpp:157 [8] RimGridCalculation::updateDependentObjects() at ResInsight/ApplicationLibCode/ProjectDataModel/RimGridCalculation.cpp:762 [9] RicUserDefinedCalculatorUi::calculate() const at ResInsight/ApplicationLibCode/Commands/RicUserDefinedCalculatorUi.cpp:178 [10] RicCalculatorWidgetCreator::slotCalculate() at ResInsight/ApplicationLibCode/Commands/RicCalculatorWidgetCreator.cpp:205 --- .../ContourMap/RimContourMapProjection.cpp | 1 + .../RimEclipseContourMapProjection.cpp | 11 ++++++- ApplicationLibCode/UnitTests/CMakeLists.txt | 1 + .../RimEclipseContourMapProjection-Test.cpp | 33 +++++++++++++++++++ 4 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 ApplicationLibCode/UnitTests/RimEclipseContourMapProjection-Test.cpp diff --git a/ApplicationLibCode/ProjectDataModel/ContourMap/RimContourMapProjection.cpp b/ApplicationLibCode/ProjectDataModel/ContourMap/RimContourMapProjection.cpp index 23aa9b54c8..a92a44498e 100644 --- a/ApplicationLibCode/ProjectDataModel/ContourMap/RimContourMapProjection.cpp +++ b/ApplicationLibCode/ProjectDataModel/ContourMap/RimContourMapProjection.cpp @@ -140,6 +140,7 @@ void RimContourMapProjection::generateResultsIfNecessary( int timeStep ) caf::ProgressInfo progress( 100, "Generate Results", true ); if ( !m_contourMapGrid || !m_contourMapProjection || gridInformationIsStale() ) updateGridInformation(); + if ( !m_contourMapGrid || !m_contourMapProjection ) return; progress.setProgress( 10 ); diff --git a/ApplicationLibCode/ProjectDataModel/ContourMap/RimEclipseContourMapProjection.cpp b/ApplicationLibCode/ProjectDataModel/ContourMap/RimEclipseContourMapProjection.cpp index 3601725c97..6196f4eb55 100644 --- a/ApplicationLibCode/ProjectDataModel/ContourMap/RimEclipseContourMapProjection.cpp +++ b/ApplicationLibCode/ProjectDataModel/ContourMap/RimEclipseContourMapProjection.cpp @@ -246,7 +246,14 @@ void RimEclipseContourMapProjection::clearResultVariable() //-------------------------------------------------------------------------------------------------- void RimEclipseContourMapProjection::updateGridInformation() { - auto eclipseCase = this->eclipseCase(); + auto eclipseCase = this->eclipseCase(); + if ( !eclipseCase || !eclipseCase->eclipseCaseData() ) + { + m_contourMapGrid.reset(); + m_contourMapProjection.reset(); + return; + } + auto eclipseCaseData = eclipseCase->eclipseCaseData(); auto resultData = eclipseCaseData->results( RiaDefines::PorosityModelType::MATRIX_MODEL ); @@ -390,6 +397,8 @@ std::pair RimEclipseContourMapProjection::computeMinMaxValuesAll double minimum = std::numeric_limits::infinity(); double maximum = -std::numeric_limits::infinity(); + if ( !eclipseCase() ) return std::make_pair( minimum, maximum ); + int timeStepCount = std::max( static_cast( eclipseCase()->timeStepStrings().size() ), 1 ); for ( int i = 0; i < (int)timeStepCount; ++i ) { diff --git a/ApplicationLibCode/UnitTests/CMakeLists.txt b/ApplicationLibCode/UnitTests/CMakeLists.txt index 98333276f0..3b3ea5573e 100644 --- a/ApplicationLibCode/UnitTests/CMakeLists.txt +++ b/ApplicationLibCode/UnitTests/CMakeLists.txt @@ -102,6 +102,7 @@ set(SOURCE_UNITTEST_FILES ${CMAKE_CURRENT_LIST_DIR}/RimWorkflowDescribeTools-Test.cpp ${CMAKE_CURRENT_LIST_DIR}/RimWorkflowVec3Binding-Test.cpp ${CMAKE_CURRENT_LIST_DIR}/RimDataFilterCollection-Test.cpp + ${CMAKE_CURRENT_LIST_DIR}/RimEclipseContourMapProjection-Test.cpp ${CMAKE_CURRENT_LIST_DIR}/RimIntersectionCollection-Test.cpp ${CMAKE_CURRENT_LIST_DIR}/RimDockWindowController-Test.cpp ${CMAKE_CURRENT_LIST_DIR}/RimFilterInViewCollection-Test.cpp diff --git a/ApplicationLibCode/UnitTests/RimEclipseContourMapProjection-Test.cpp b/ApplicationLibCode/UnitTests/RimEclipseContourMapProjection-Test.cpp new file mode 100644 index 0000000000..d399e04595 --- /dev/null +++ b/ApplicationLibCode/UnitTests/RimEclipseContourMapProjection-Test.cpp @@ -0,0 +1,33 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2026 Equinor ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "gtest/gtest.h" + +#include "ContourMap/RimContourMapProjection.h" +#include "ContourMap/RimEclipseContourMapView.h" + +//-------------------------------------------------------------------------------------------------- +/// A contour map view without an eclipse case must not crash when results are generated. +//-------------------------------------------------------------------------------------------------- +TEST( RimEclipseContourMapProjection, GenerateResultsWithoutEclipseCase ) +{ + RimEclipseContourMapView view; + ASSERT_NE( nullptr, view.contourMapProjection() ); + + view.contourMapProjection()->generateResultsIfNecessary( 0 ); +}