Commit aa90c32d authored by Duncan P. N. Exon Smith's avatar Duncan P. N. Exon Smith
Browse files

Merging r226029:

------------------------------------------------------------------------
r226029 | dexonsmith | 2015-01-14 11:56:10 -0800 (Wed, 14 Jan 2015) | 7 lines

IR: Fix a use-after-free in RAUW

Happened pretty commonly during `LLVMContext` teardown when `clang -g`
hit an error.  This fixes the use-after-free.  Next I'll clean up
teardown so that it's not RAUW'ing when metadata-tracked values are
deleted (only really causes a problem if the graph is mid-construction
when teardown starts, but it's still unnecessary work).
------------------------------------------------------------------------

llvm-svn: 226090
parent 95a46333
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -167,6 +167,11 @@ void ReplaceableMetadataImpl::replaceAllUsesWith(Metadata *MD) {
    return L.second.second < R.second.second;
  });
  for (const auto &Pair : Uses) {
    // Check that this Ref hasn't disappeared after RAUW (when updating a
    // previous Ref).
    if (!UseMap.count(Pair.first))
      continue;

    OwnerTy Owner = Pair.second.first;
    if (!Owner) {
      // Update unowned tracking references directly.
+28 −0
Original line number Diff line number Diff line
@@ -484,6 +484,34 @@ TEST_F(ValueAsMetadataTest, UpdatesOnRAUW) {
  EXPECT_TRUE(MD->getValue() == GV1.get());
}

TEST_F(ValueAsMetadataTest, CollidingDoubleUpdates) {
  // Create a constant.
  ConstantAsMetadata *CI = ConstantAsMetadata::get(
      ConstantInt::get(getGlobalContext(), APInt(8, 0)));

  // Create a temporary to prevent nodes from resolving.
  std::unique_ptr<MDNodeFwdDecl> Temp(MDNode::getTemporary(Context, None));

  // When the first operand of N1 gets reset to nullptr, it'll collide with N2.
  Metadata *Ops1[] = {CI, CI, Temp.get()};
  Metadata *Ops2[] = {nullptr, CI, Temp.get()};

  auto *N1 = MDTuple::get(Context, Ops1);
  auto *N2 = MDTuple::get(Context, Ops2);
  ASSERT_NE(N1, N2);

  // Tell metadata that the constant is getting deleted.
  //
  // After this, N1 will be invalid, so don't touch it.
  ValueAsMetadata::handleDeletion(CI->getValue());
  EXPECT_EQ(nullptr, N2->getOperand(0));
  EXPECT_EQ(nullptr, N2->getOperand(1));
  EXPECT_EQ(Temp.get(), N2->getOperand(2));

  // Clean up Temp for teardown.
  Temp->replaceAllUsesWith(nullptr);
}

typedef MetadataTest TrackingMDRefTest;

TEST_F(TrackingMDRefTest, UpdatesOnRAUW) {