[llvm] r226029 - IR: Fix a use-after-free in RAUW
Duncan P. N. Exon Smith
dexonsmith at apple.com
Wed Jan 14 11:56:10 PST 2015
Author: dexonsmith
Date: Wed Jan 14 13:56:10 2015
New Revision: 226029
URL: http://llvm.org/viewvc/llvm-project?rev=226029&view=rev
Log:
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).
Modified:
llvm/trunk/lib/IR/Metadata.cpp
llvm/trunk/unittests/IR/MetadataTest.cpp
Modified: llvm/trunk/lib/IR/Metadata.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Metadata.cpp?rev=226029&r1=226028&r2=226029&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Metadata.cpp (original)
+++ llvm/trunk/lib/IR/Metadata.cpp Wed Jan 14 13:56:10 2015
@@ -167,6 +167,11 @@ void ReplaceableMetadataImpl::replaceAll
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.
Modified: llvm/trunk/unittests/IR/MetadataTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/IR/MetadataTest.cpp?rev=226029&r1=226028&r2=226029&view=diff
==============================================================================
--- llvm/trunk/unittests/IR/MetadataTest.cpp (original)
+++ llvm/trunk/unittests/IR/MetadataTest.cpp Wed Jan 14 13:56:10 2015
@@ -484,6 +484,34 @@ TEST_F(ValueAsMetadataTest, UpdatesOnRAU
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) {
More information about the llvm-commits
mailing list