#14121 Well Path: guard remaining null wellPathGeometry() dereferences

A file-based well path whose source file is missing has a null wellPathGeometry(). Add null checks at the remaining call sites that dereferenced it without one, so operations on such a well path no longer crash:

- RimWellPathGroup: skip geometry merging for a child with no geometry (grouping runs on import and project load).
- RimWellPathFracture::computeFractureDirectionNormal: return undefined when geometry is missing.
- RivWellPathPartMgr: extend the existing well path null checks to also require geometry in the attribute, well measurement, and valve append paths.
- RimCompletionCellIntersectionCalc, RicExportLgrFeature, RicCreateMultipleWellPathLaterals, RigLasFileExporter, RiuWellPathComponentPlotItem: guard the geometry before use.

Sites that were already guarded or only reachable through guarded paths were left unchanged.
This commit is contained in:
Kristian Bendiksen authored and Magne Sjaastad committed 2026-06-08 08:46:40 +02:00
1 parent 253d57f1a5
commit 2a158dce58
8 files changed
+27 -6

No files matched your search

@@ -752,6 +752,8 @@ std::vector<RigCompletionDataGridCell> RicExportLgrFeature::allIntersectedCells(
{
std::vector<RigCompletionDataGridCell> cells;
if ( !wellPath || !wellPath->wellPathGeometry() ) return cells;
const RigMainGrid* mainGrid = eclipseCase->mainGrid();
auto globalCellIndices = RigWellPathIntersectionTools::findIntersectedGlobalCellIndices( eclipseCase->eclipseCaseData(),
@@ -71,7 +71,7 @@ void RicCreateMultipleWellPathLaterals::onActionTriggered( bool isChecked )
if ( auto parentWell = tieIn->parentWell() )
{
if ( !parentWell->wellPathGeometry()->measuredDepths().empty() )
if ( parentWell->wellPathGeometry() && !parentWell->wellPathGeometry()->measuredDepths().empty() )
{
double candidate = parentWell->wellPathGeometry()->measuredDepths().back() - 50.0;
@@ -212,7 +212,7 @@ void RivWellPathPartMgr::appendWellPathAttributesToModel( cvf::ModelBasicList*
const caf::DisplayCoordTransform* displayCoordTransform,
double characteristicCellSize )
{
if ( !m_rimWellPath ) return;
if ( !m_rimWellPath || !m_rimWellPath->wellPathGeometry() ) return;
RivPipeGeometryGenerator geoGenerator;
std::vector<RimWellPathAttribute*> attributes = m_rimWellPath->attributeCollection()->attributes();
@@ -300,7 +300,7 @@ void RivWellPathPartMgr::appendWellMeasurementsToModel( cvf::ModelBasicList*
const caf::DisplayCoordTransform* displayCoordTransform,
double characteristicCellSize )
{
if ( !m_rimWellPath ) return;
if ( !m_rimWellPath || !m_rimWellPath->wellPathGeometry() ) return;
RimGridView* gridView = dynamic_cast<RimGridView*>( m_rimView.p() );
if ( !gridView ) return;
@@ -483,6 +483,8 @@ void RivWellPathPartMgr::appendValvesToModel( cvf::ModelBasicList*
double wellPathRadius,
const caf::DisplayCoordTransform* displayCoordTransform )
{
if ( !m_rimWellPath || !m_rimWellPath->wellPathGeometry() ) return;
for ( auto valve : valves )
{
if ( valve == nullptr ) continue;
@@ -90,6 +90,7 @@ void RimCompletionCellIntersectionCalc::calculateCompletionTypeResult( RimEclips
// types
for ( const RimWellPath* wellPath : visibleWells )
{
if ( !wellPath || !wellPath->wellPathGeometry() ) continue;
auto intersectedCells =
RigWellPathIntersectionTools::findIntersectedGlobalCellIndices( eclipseCaseData, wellPath->wellPathGeometry()->wellPathPoints() );
@@ -141,6 +141,7 @@ cvf::Vec3d RimWellPathFracture::computeFractureDirectionNormal() const
if ( !wellPath ) return cvf::Vec3d::UNDEFINED;
RigWellPath* wellPathGeometry = wellPath->wellPathGeometry();
if ( !wellPathGeometry ) return cvf::Vec3d::UNDEFINED;
// Find the well path points closest to the anchor position
cvf::Vec3d p1;
@@ -77,6 +77,16 @@ void RimWellPathGroup::addChildWellPath( RimWellPath* wellPath )
RimWellPath::copyCompletionSettings( wellPath, this );
}
if ( !wellPath->wellPathGeometry() )
{
// The child has no geometry (e.g. the source well path file is missing). Keep it as a child, but skip
// all geometry merging to avoid dereferencing a null geometry.
m_childWellPaths.push_back( wellPath );
wellPath->nameChanged.connect( this, &RimWellPathGroup::onChildNameChanged );
updateAllRequiredEditors();
return;
}
if ( !wellPathGeometry()->wellPathPoints().empty() )
{
m_childWellPaths.push_back( wellPath );
@@ -184,7 +194,10 @@ void RimWellPathGroup::createWellPathGeometry()
{
lateral->createWellPathGeometry();
}
wellPath->wellPathGeometry()->setUniqueStartAndEndIndex( childStartIndex, std::numeric_limits<size_t>::max() );
if ( auto geometry = wellPath->wellPathGeometry(); geometry )
{
geometry->setUniqueStartAndEndIndex( childStartIndex, std::numeric_limits<size_t>::max() );
}
}
}
@@ -383,6 +396,7 @@ void RimWellPathGroup::makeMoreLevelsIfNecessary()
for ( auto wellPath : m_childWellPaths )
{
if ( !wellPath->wellPathGeometry() ) continue;
auto childWellPathPoints = wellPath->wellPathGeometry()->wellPathPoints();
if ( childWellPathPoints.size() > wellPathPoints.size() )
{
@@ -545,7 +545,7 @@ QString RigLasFileExporter::caseNameFromCurve( RimWellLogCurve* curve )
double RigLasFileExporter::rkbDiff( RimWellLogCurve* curve )
{
RimWellLogExtractionCurve* extractionCurve = dynamic_cast<RimWellLogExtractionCurve*>( curve );
if ( extractionCurve && extractionCurve->wellPath() )
if ( extractionCurve && extractionCurve->wellPath() && extractionCurve->wellPath()->wellPathGeometry() )
{
return extractionCurve->wellPath()->wellPathGeometry()->rkbDiff();
}
@@ -298,7 +298,8 @@ std::pair<double, double> RiuWellPathComponentPlotItem::depthsOfDepthType() cons
double startDepth = m_startMD;
double endDepth = m_endMD;
if ( m_depthType == RiaDefines::DepthType::TRUE_VERTICAL_DEPTH || m_depthType == RiaDefines::DepthType::TRUE_VERTICAL_DEPTH_RKB )
if ( ( m_depthType == RiaDefines::DepthType::TRUE_VERTICAL_DEPTH || m_depthType == RiaDefines::DepthType::TRUE_VERTICAL_DEPTH_RKB ) &&
m_wellPath && m_wellPath->wellPathGeometry() )
{
endDepth = -m_wellPath->wellPathGeometry()->interpolatedPointAlongWellPath( m_endMD ).z();
double rkbDiff = m_wellPath->wellPathGeometry()->rkbDiff();