]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - opencl/llvm.git/commitdiff
IR: Update references to temporaries before deleting
authorDuncan P. N. Exon Smith <dexonsmith@apple.com>
Thu, 22 Jan 2015 21:36:45 +0000 (21:36 +0000)
committerDuncan P. N. Exon Smith <dexonsmith@apple.com>
Thu, 22 Jan 2015 21:36:45 +0000 (21:36 +0000)
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.)

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@226866 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/IR/Metadata.h
lib/IR/Metadata.cpp
test/Assembler/invalid-mdnode-badref.ll [new file with mode: 0644]
unittests/IR/MetadataTest.cpp

index 5590bc54881f9baa00a8dc507f66ff2fc36da330..5a2630b64e8027e50a5bf412a8e3de6e718ceb8b 100644 (file)
@@ -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(); }
index 6c8f71ffa99f60bb1cd79089c5af8744abd874e0..fac9268f786a13f501c0edeef26d75f24c3bf42e 100644 (file)
@@ -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/test/Assembler/invalid-mdnode-badref.ll b/test/Assembler/invalid-mdnode-badref.ll
new file mode 100644 (file)
index 0000000..cfa03e0
--- /dev/null
@@ -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}
index e2ed3d7946bb5900a6114f044867f4b6c1baeea5..b2205776f6420c870a22c9f33525d2104b1e81f3 100644 (file)
@@ -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) {