summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDuncan P. N. Exon Smith <dexonsmith@apple.com>2015-01-22 21:36:45 +0000
committerDuncan P. N. Exon Smith <dexonsmith@apple.com>2015-01-22 21:36:45 +0000
commit8d536973a22ef1ad5c4ff1a120633cc028313f57 (patch)
treed00d040d337f45f0232b955d20d2966b7d3ceab7
parentc6ccc4fe91b8f1bc5251b454ac1f6c79a6177c8b (diff)
downloadbcm5719-llvm-8d536973a22ef1ad5c4ff1a120633cc028313f57.tar.gz
bcm5719-llvm-8d536973a22ef1ad5c4ff1a120633cc028313f57.zip
IR: Update references to temporaries before deleting
During `MDNode::deleteTemporary()`, call `replaceAllUsesWith(nullptr)` to update all tracking references to `nullptr`. This fixes PR22280, where inverted destruction order between tracking references and the temporaries themselves caused a use-after-free in `LLParser`. An alternative fix would be to add an assertion that there are no users, and continue to fix inverted destruction order in clients (like `LLParser`), but instead I decided to make getting-teardown-right easy. (If someone disagrees let me know.) llvm-svn: 226866
-rw-r--r--llvm/include/llvm/IR/Metadata.h3
-rw-r--r--llvm/lib/IR/Metadata.cpp1
-rw-r--r--llvm/test/Assembler/invalid-mdnode-badref.ll5
-rw-r--r--llvm/unittests/IR/MetadataTest.cpp11
4 files changed, 19 insertions, 1 deletions
diff --git a/llvm/include/llvm/IR/Metadata.h b/llvm/include/llvm/IR/Metadata.h
index 5590bc54881..5a2630b64e8 100644
--- a/llvm/include/llvm/IR/Metadata.h
+++ b/llvm/include/llvm/IR/Metadata.h
@@ -727,7 +727,8 @@ public:
/// \brief Deallocate a node created by getTemporary.
///
- /// The node must not have any users.
+ /// Calls \c replaceAllUsesWith(nullptr) before deleting, so any remaining
+ /// references will be reset.
static void deleteTemporary(MDNode *N);
LLVMContext &getContext() const { return Context.getContext(); }
diff --git a/llvm/lib/IR/Metadata.cpp b/llvm/lib/IR/Metadata.cpp
index 6c8f71ffa99..fac9268f786 100644
--- a/llvm/lib/IR/Metadata.cpp
+++ b/llvm/lib/IR/Metadata.cpp
@@ -788,6 +788,7 @@ GenericDwarfNode *GenericDwarfNode::getImpl(LLVMContext &Context, unsigned Tag,
void MDNode::deleteTemporary(MDNode *N) {
assert(N->isTemporary() && "Expected temporary node");
+ N->replaceAllUsesWith(nullptr);
N->deleteAsSubclass();
}
diff --git a/llvm/test/Assembler/invalid-mdnode-badref.ll b/llvm/test/Assembler/invalid-mdnode-badref.ll
new file mode 100644
index 00000000000..cfa03e0b3c6
--- /dev/null
+++ b/llvm/test/Assembler/invalid-mdnode-badref.ll
@@ -0,0 +1,5 @@
+; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s
+!named = !{!0}
+
+; CHECK: [[@LINE+1]]:14: error: use of undefined metadata '!1'
+!0 = !{!0, !1}
diff --git a/llvm/unittests/IR/MetadataTest.cpp b/llvm/unittests/IR/MetadataTest.cpp
index e2ed3d7946b..b2205776f64 100644
--- a/llvm/unittests/IR/MetadataTest.cpp
+++ b/llvm/unittests/IR/MetadataTest.cpp
@@ -517,6 +517,17 @@ TEST_F(MDNodeTest, replaceWithDistinct) {
}
}
+TEST_F(MDNodeTest, deleteTemporaryWithTrackingRef) {
+ TrackingMDRef Ref;
+ EXPECT_EQ(nullptr, Ref.get());
+ {
+ auto Temp = MDTuple::getTemporary(Context, None);
+ Ref.reset(Temp.get());
+ EXPECT_EQ(Temp.get(), Ref.get());
+ }
+ EXPECT_EQ(nullptr, Ref.get());
+}
+
typedef MetadataTest MDLocationTest;
TEST_F(MDLocationTest, Overflow) {
OpenPOWER on IntegriCloud