Commit 481bb249 authored by Hans Wennborg's avatar Hans Wennborg
Browse files

Merging r292133:

------------------------------------------------------------------------
r292133 | hfinkel | 2017-01-16 07:22:01 -0800 (Mon, 16 Jan 2017) | 10 lines

Fix use-after-free bug in AffectedValueCallbackVH::allUsesReplacedWith

When transferring affected values in the cache from an old value, identified by
the value of the current callback, to the specified new value we might need to
insert a new entry into the DenseMap which constitutes the cache. Doing so
might delete the current callback object. Move the copying logic into a new
function, a member of the assumption cache itself, so that we don't run into UB
should the callback handle itself be removed mid-copy.

Differential Revision: https://reviews.llvm.org/D28749
------------------------------------------------------------------------

llvm-svn: 292312
parent 57f962df
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -68,7 +68,10 @@ class AssumptionCache {
  AffectedValuesMap AffectedValues;

  /// Get the vector of assumptions which affect a value from the cache.
  SmallVector<WeakVH, 1> &getAffectedValues(Value *V);
  SmallVector<WeakVH, 1> &getOrInsertAffectedValues(Value *V);

  /// Copy affected values in the cache for OV to be affected values for NV.
  void copyAffectedValuesInCache(Value *OV, Value *NV);

  /// \brief Flag tracking whether we have scanned the function yet.
  ///
+17 −10
Original line number Diff line number Diff line
@@ -24,7 +24,7 @@
using namespace llvm;
using namespace llvm::PatternMatch;

SmallVector<WeakVH, 1> &AssumptionCache::getAffectedValues(Value *V) {
SmallVector<WeakVH, 1> &AssumptionCache::getOrInsertAffectedValues(Value *V) {
  // Try using find_as first to avoid creating extra value handles just for the
  // purpose of doing the lookup.
  auto AVI = AffectedValues.find_as(V);
@@ -98,7 +98,7 @@ void AssumptionCache::updateAffectedValues(CallInst *CI) {
  }

  for (auto &AV : Affected) {
    auto &AVV = getAffectedValues(AV);
    auto &AVV = getOrInsertAffectedValues(AV);
    if (std::find(AVV.begin(), AVV.end(), CI) == AVV.end())
      AVV.push_back(CI);
  }
@@ -111,20 +111,27 @@ void AssumptionCache::AffectedValueCallbackVH::deleted() {
  // 'this' now dangles!
}

void AssumptionCache::copyAffectedValuesInCache(Value *OV, Value *NV) {
  auto &NAVV = getOrInsertAffectedValues(NV);
  auto AVI = AffectedValues.find(OV);
  if (AVI == AffectedValues.end())
    return;

  for (auto &A : AVI->second)
    if (std::find(NAVV.begin(), NAVV.end(), A) == NAVV.end())
      NAVV.push_back(A);
}

void AssumptionCache::AffectedValueCallbackVH::allUsesReplacedWith(Value *NV) {
  if (!isa<Instruction>(NV) && !isa<Argument>(NV))
    return;

  // Any assumptions that affected this value now affect the new value.

  auto &NAVV = AC->getAffectedValues(NV);
  auto AVI = AC->AffectedValues.find(getValPtr());
  if (AVI == AC->AffectedValues.end())
    return;

  for (auto &A : AVI->second)
    if (std::find(NAVV.begin(), NAVV.end(), A) == NAVV.end())
      NAVV.push_back(A);
  AC->copyAffectedValuesInCache(getValPtr(), NV);
  // 'this' now might dangle! If the AffectedValues map was resized to add an
  // entry for NV then this object might have been destroyed in favor of some
  // copy in the grown map.
}

void AssumptionCache::scanFunction() {