Skip to content

Commit

Permalink
8323688: C2: Fix UB of jlong overflow in PhaseIdealLoop::is_counted_l…
Browse files Browse the repository at this point in the history
…oop()
  • Loading branch information
chhagedorn committed Mar 26, 2024
1 parent af15c68 commit e472833
Showing 1 changed file with 21 additions and 1 deletion.
22 changes: 21 additions & 1 deletion src/hotspot/share/opto/loopnode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1917,12 +1917,28 @@ bool PhaseIdealLoop::is_counted_loop(Node* x, IdealLoopTree*&loop, BasicType iv_
// Since stride > 0 and limit_correction <= stride + 1, we can restate this with no over- or underflow into:
// max_int - canonicalized_correction - limit_correction >= limit
// Since canonicalized_correction and limit_correction are both constants, we can replace them with a new constant:
// final_correction = canonicalized_correction + limit_correction
// (v) final_correction = canonicalized_correction + limit_correction
//
// which gives us:
//
// Final predicate condition:
// max_int - final_correction >= limit
//
// However, we need to be careful that (v) does not over- or underflow.
// We know that:
// canonicalized_correction = stride - 1
// and
// limit_correction <= stride + 1
// and thus
// canonicalized_correction + limit_correction <= 2 * stride
// To prevent an over- or underflow of (v), we must ensure that
// 2 * stride <= max_int
// which can safely be checked without over- or underflow with
// (vi) stride != min_int AND abs(stride) <= max_int / 2
//
// We could try to further optimize the cases where (vi) does not hold but given that such large strides are
// very uncommon and the loop would only run for a very few iterations anyway, we simply bail out if (vi) fails.
//
// (2) Loop Limit Check Predicate for (ii):
// Using (ii): init < limit
//
Expand Down Expand Up @@ -1953,6 +1969,10 @@ bool PhaseIdealLoop::is_counted_loop(Node* x, IdealLoopTree*&loop, BasicType iv_
// there is no overflow of the iv phi after the first iteration. In this case, we don't need to check (ii)
// again and can skip the predicate.

// Check (vi) and bail out if the stride is too big.
if (stride_con == min_signed_integer(iv_bt) || ABS(stride_con) > max_signed_integer(iv_bt) / 2) {
return false;
}

// Accounting for (LE3) and (LE4) where we use pre-incremented phis in the loop exit check.
const jlong limit_correction_for_pre_iv_exit_check = (phi_incr != nullptr) ? stride_con : 0;
Expand Down

0 comments on commit e472833

Please sign in to comment.