Skip to content

Commit c347ec4

Browse files
committed
WellConnections: bound the Cartesian->compressed lookup
WellConnections::init translates each well connection into a compressed cell index with cart_grid_idx = i + nx*(j + ny*k); compressed_idx = cartesian_to_compressed[cart_grid_idx]; and does the same for possibleFutureConnections. Neither lookup checked that the computed position is inside cartesian_to_compressed before indexing it. The map is sized by the level-zero Cartesian grid, and a connection is not obliged to carry a position in that grid -- a completion inside a local grid refinement, for instance, carries a position local to the refined grid. When that position lands past the end of the map the result is an out-of-bounds read during load balancing. Route both lookups through a helper that returns -1 for a position outside the map, which the existing "ignore inactive cells" test already handles. Nothing changes for a position that was in range, so grids whose connections all address level zero are unaffected.
1 parent e94a738 commit c347ec4

1 file changed

Lines changed: 18 additions & 2 deletions

File tree

opm/grid/common/WellConnections.cpp

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,22 @@ void WellConnections::init([[maybe_unused]] const std::vector<OpmWellType>& well
115115
#if HAVE_OPM_COMMON
116116
well_indices_.resize(wells.size());
117117

118+
// Both loops below index cartesian_to_compressed with a position derived
119+
// from the connection, and neither checked that the position is actually
120+
// inside the map. Bound the lookup against the container that is being
121+
// indexed, so that a position which is not a level-zero Cartesian index
122+
// cannot read past the end of it.
123+
const auto lookup = [&cartesian_to_compressed](const int cart_grid_idx)
124+
{
125+
if ((cart_grid_idx < 0) ||
126+
(static_cast<std::size_t>(cart_grid_idx) >= cartesian_to_compressed.size()))
127+
{
128+
return -1;
129+
}
130+
131+
return cartesian_to_compressed[cart_grid_idx];
132+
};
133+
118134
// We assume that we know all the wells.
119135
int index=0;
120136
for (const auto& well : wells) {
@@ -126,7 +142,7 @@ void WellConnections::init([[maybe_unused]] const std::vector<OpmWellType>& well
126142
int j = connection.getJ();
127143
int k = connection.getK();
128144
int cart_grid_idx = i + cartesianSize[0]*(j + cartesianSize[1]*k);
129-
int compressed_idx = cartesian_to_compressed[cart_grid_idx];
145+
int compressed_idx = lookup(cart_grid_idx);
130146
if ( compressed_idx >= 0 ) // Ignore connections in inactive cells.
131147
{
132148
well_indices.insert(compressed_idx);
@@ -135,7 +151,7 @@ void WellConnections::init([[maybe_unused]] const std::vector<OpmWellType>& well
135151
const auto possibleFutureConnectionSetIt = possibleFutureConnections.find(well.name());
136152
if (possibleFutureConnectionSetIt != possibleFutureConnections.end()) {
137153
for (auto& cart_grid_idx : possibleFutureConnectionSetIt->second) {
138-
int compressed_idx = cartesian_to_compressed[cart_grid_idx];
154+
int compressed_idx = lookup(cart_grid_idx);
139155
if ( compressed_idx >= 0 ) // Ignore connections in inactive cells.
140156
{
141157
well_indices.insert(compressed_idx);

0 commit comments

Comments
 (0)