Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 25 additions & 7 deletions src/grt/src/cugr/src/GridGraph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,9 @@ GridGraph::GridGraph(const Design* design,
IntervalT GridGraph::rangeSearchGridlines(const int dimension,
const IntervalT& loc_interval) const
{
if (dimension < 0 || dimension > 1) {
return {0, 0};
}
IntervalT range;
range.Set(lower_bound(gridlines_[dimension].begin(),
gridlines_[dimension].end(),
Expand All @@ -270,13 +273,28 @@ IntervalT GridGraph::rangeSearchGridlines(const int dimension,
IntervalT GridGraph::rangeSearchRows(const int dimension,
const IntervalT& loc_interval) const
{
if (dimension < 0 || dimension > 1) {
return {0, 0};
}

// 1. Critical Empty Check: If the grid doesn't exist, exit early
if (gridlines_[dimension].empty()) {
return {0, 0};
}

const auto& lineRange = rangeSearchGridlines(dimension, loc_interval);
return {gridlines_[dimension][lineRange.low()] == loc_interval.low()
? lineRange.low()
: std::max(lineRange.low() - 1, 0),
gridlines_[dimension][lineRange.high()] == loc_interval.high()
? lineRange.high() - 1
: std::min(lineRange.high(), getSize(dimension) - 1)};

Comment on lines 274 to +286
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

While the clamping logic prevents out-of-bounds access for non-empty gridlines_, it doesn't handle the case where gridlines_[dimension] is empty. In this scenario, rangeSearchGridlines returns {0, 0}, max_idx becomes 0, and l and h are set to 0. The subsequent access gridlines_[dimension][l] will then cause a crash, which this pull request aims to prevent.

An early exit for an empty gridline vector is needed. With this check, the std::max in the max_idx calculation also becomes redundant and can be simplified.

  if (dimension < 0 || dimension > 1) return {0, 0};
  if (gridlines_[dimension].empty()) {
    return {0, 0};
  }
  const auto& lineRange = rangeSearchGridlines(dimension, loc_interval);
  
  // BOUNDARY SHIELD: Safely clamp to array boundaries
  const int max_idx = (int)gridlines_[dimension].size() - 1;
  const int l = std::min(lineRange.low(), max_idx);
  const int h = std::min(lineRange.high(), max_idx);

// 2. BOUNDARY SHIELD: Safely clamp to array boundaries
const int max_idx = (int) gridlines_[dimension].size() - 1;
const int l = std::min(lineRange.low(), max_idx);
const int h = std::min(lineRange.high(), max_idx);

// 3. Robust Return: Ensure we never return a negative index for either bound
return {
gridlines_[dimension][l] == loc_interval.low() ? l : std::max(l - 1, 0),
gridlines_[dimension][h] == loc_interval.high()
? std::max(0, h - 1)
: std::min(h, getSize(dimension) - 1)};
}

BoxT GridGraph::getCellBox(PointT point) const
Expand Down Expand Up @@ -908,4 +926,4 @@ void GridGraph::write(const std::string& heatmap_file) const
fout.close();
}

} // namespace grt
} // namespace grt
Loading