From 86500efbdcc700c76aba2bcd6a2fae4dd3a8e6a3 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 30 Apr 2026 13:16:26 +0200 Subject: [PATCH] #13926 GeoMech well log: Guard against OOB indices when interpolating results Bounds-check every gridResultValues access in interpolateGridResultValue to prevent segfaults observed in interpolateInterfaceValues' OMP loop when a result vector was empty or sized for a different result position type. OOB now returns the infinity sentinel that matches the existing undefined-value path and the initializeResultValues pre-fill, so downstream invalid-value checks correctly skip these slots. interpolateInterfaceValues additionally short-circuits and logs a warning with the field/component name when the input result vector is empty, instead of failing silently. --- .../Well/RigGeoMechWellLogExtractor.cpp | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/ApplicationLibCode/ReservoirDataModel/Well/RigGeoMechWellLogExtractor.cpp b/ApplicationLibCode/ReservoirDataModel/Well/RigGeoMechWellLogExtractor.cpp index 7189f59a76..d159c19fdf 100644 --- a/ApplicationLibCode/ReservoirDataModel/Well/RigGeoMechWellLogExtractor.cpp +++ b/ApplicationLibCode/ReservoirDataModel/Well/RigGeoMechWellLogExtractor.cpp @@ -1040,6 +1040,7 @@ T RigGeoMechWellLogExtractor::interpolateGridResultValue( RigFemResultPosEnum if ( resultPosType == RIG_ELEMENT ) { + if ( elmIdx >= gridResultValues.size() ) return std::numeric_limits::infinity(); return gridResultValues[elmIdx]; } @@ -1055,11 +1056,13 @@ T RigGeoMechWellLogExtractor::interpolateGridResultValue( RigFemResultPosEnum // TODO: Should interpolate within the whole hexahedron. This requires converting to locals coordinates. // For now just pick the average value for the cell. size_t gridResultValueIdx = femPart->resultValueIdxFromResultPosType( resultPosType, static_cast( elmIdx ), 0 ); - T sumOfVertexValues = gridResultValues[gridResultValueIdx]; + if ( gridResultValueIdx >= gridResultValues.size() ) return std::numeric_limits::infinity(); + T sumOfVertexValues = gridResultValues[gridResultValueIdx]; for ( int i = 1; i < 8; ++i ) { gridResultValueIdx = femPart->resultValueIdxFromResultPosType( resultPosType, static_cast( elmIdx ), i ); - sumOfVertexValues = sumOfVertexValues + gridResultValues[gridResultValueIdx]; + if ( gridResultValueIdx >= gridResultValues.size() ) return std::numeric_limits::infinity(); + sumOfVertexValues = sumOfVertexValues + gridResultValues[gridResultValueIdx]; } return sumOfVertexValues * ( 1.0 / 8.0 ); } @@ -1092,6 +1095,7 @@ T RigGeoMechWellLogExtractor::interpolateGridResultValue( RigFemResultPosEnum nodeResultValues.reserve( 4 ); for ( size_t i = 0; i < nodeResIdx.size(); ++i ) { + if ( nodeResIdx[i] >= gridResultValues.size() ) return std::numeric_limits::infinity(); nodeResultValues.push_back( gridResultValues[nodeResIdx[i]] ); } T interpolatedValue = cvf::GeometryTools::interpolateQuad( v0, @@ -1399,6 +1403,17 @@ std::vector RigGeoMechWellLogExtractor::interpolateInterfaceValues( RigFemRes std::vector interpolatedInterfaceValues; initializeResultValues( interpolatedInterfaceValues, intersections().size() ); + if ( unscaledResultValues.empty() ) + { + RiaLogging::warning( QString( "No result values available for %1 / %2 (time step %3, frame %4). " + "Well log curve will be empty." ) + .arg( QString::fromStdString( nativeAddr.fieldName ) ) + .arg( QString::fromStdString( nativeAddr.componentName ) ) + .arg( timeStepIndex ) + .arg( frameIndex ) ); + return interpolatedInterfaceValues; + } + const RigFemPart* femPart = m_caseData->femParts()->part( m_partId ); #pragma omp parallel for