[vm, compiler] Avoid undefined behavior when tracking induction variables wraps around.

TEST=ubsan
Bug: https://github.com/dart-lang/sdk/issues/45511
Change-Id: Iaa5733dc048a811c87f479fa54fdb89bf64a0373
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/193443
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Ryan Macnak <rmacnak@google.com>
This commit is contained in:
Ryan Macnak
2021-03-30 17:06:16 +00:00
committed by commit-bot@chromium.org
parent 7b022a7f2f
commit fbc25f3dff
2 changed files with 21 additions and 7 deletions
+7
View File
@@ -292,6 +292,13 @@ class Utils {
return static_cast<T>(static_cast<Unsigned>(a) * static_cast<Unsigned>(b));
}
template <typename T = int64_t>
static inline T NegWithWrapAround(T a) {
// Avoid undefined behavior by doing arithmetic in the unsigned type.
using Unsigned = typename std::make_unsigned<T>::type;
return static_cast<T>(-static_cast<Unsigned>(a));
}
// Shifts int64_t value left. Supports any non-negative number of bits and
// silently discards shifted out bits.
static inline int64_t ShiftLeftWithTruncation(int64_t a, int64_t b) {
+14 -7
View File
@@ -723,13 +723,16 @@ InductionVar* InductionVarAnalysis::Add(InductionVar* x, InductionVar* y) {
// Invariant + Invariant : only for same or just one instruction.
if (x->def_ == y->def_) {
return new (zone_)
InductionVar(x->offset_ + y->offset_, x->mult_ + y->mult_, x->def_);
InductionVar(Utils::AddWithWrapAround(x->offset_, y->offset_),
Utils::AddWithWrapAround(x->mult_, y->mult_), x->def_);
} else if (y->mult_ == 0) {
return new (zone_)
InductionVar(x->offset_ + y->offset_, x->mult_, x->def_);
InductionVar(Utils::AddWithWrapAround(x->offset_, y->offset_),
x->mult_, x->def_);
} else if (x->mult_ == 0) {
return new (zone_)
InductionVar(x->offset_ + y->offset_, y->mult_, y->def_);
InductionVar(Utils::AddWithWrapAround(x->offset_, y->offset_),
y->mult_, y->def_);
}
} else if (y != nullptr) {
// Invariant + Induction.
@@ -768,13 +771,16 @@ InductionVar* InductionVarAnalysis::Sub(InductionVar* x, InductionVar* y) {
// Invariant + Invariant : only for same or just one instruction.
if (x->def_ == y->def_) {
return new (zone_)
InductionVar(x->offset_ - y->offset_, x->mult_ - y->mult_, x->def_);
InductionVar(Utils::SubWithWrapAround(x->offset_, y->offset_),
Utils::SubWithWrapAround(x->mult_, y->mult_), x->def_);
} else if (y->mult_ == 0) {
return new (zone_)
InductionVar(x->offset_ - y->offset_, x->mult_, x->def_);
InductionVar(Utils::SubWithWrapAround(x->offset_, y->offset_),
x->mult_, x->def_);
} else if (x->mult_ == 0) {
return new (zone_)
InductionVar(x->offset_ - y->offset_, -y->mult_, y->def_);
InductionVar(Utils::SubWithWrapAround(x->offset_, y->offset_),
Utils::NegWithWrapAround(y->mult_), y->def_);
}
} else if (y != nullptr) {
// Invariant - Induction.
@@ -823,7 +829,8 @@ InductionVar* InductionVarAnalysis::Mul(InductionVar* x, InductionVar* y) {
if (InductionVar::IsConstant(x) && y != nullptr) {
if (y->kind_ == InductionVar::kInvariant) {
return new (zone_)
InductionVar(x->offset_ * y->offset_, x->offset_ * y->mult_, y->def_);
InductionVar(Utils::MulWithWrapAround(x->offset_, y->offset_),
Utils::MulWithWrapAround(x->offset_, y->mult_), y->def_);
}
return new (zone_)
InductionVar(y->kind_, Mul(x, y->initial_), Mul(x, y->next_));