[llvm] r226866 - IR: Update references to temporaries before deleting

Duncan P. N. Exon Smith dexonsmith at apple.com
Thu Jan 22 13:36:46 PST 2015


Author: dexonsmith
Date: Thu Jan 22 15:36:45 2015
New Revision: 226866

URL: http://llvm.org/viewvc/llvm-project?rev=226866&view=rev
Log:
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.)

Added:
    llvm/trunk/test/Assembler/invalid-mdnode-badref.ll
Modified:
    llvm/trunk/include/llvm/IR/Metadata.h
    llvm/trunk/lib/IR/Metadata.cpp
    llvm/trunk/unittests/IR/MetadataTest.cpp

Modified: llvm/trunk/include/llvm/IR/Metadata.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Metadata.h?rev=226866&r1=226865&r2=226866&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/Metadata.h (original)
+++ llvm/trunk/include/llvm/IR/Metadata.h Thu Jan 22 15:36:45 2015
@@ -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(); }

Modified: llvm/trunk/lib/IR/Metadata.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Metadata.cpp?rev=226866&r1=226865&r2=226866&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Metadata.cpp (original)
+++ llvm/trunk/lib/IR/Metadata.cpp Thu Jan 22 15:36:45 2015
@@ -788,6 +788,7 @@ GenericDwarfNode *GenericDwarfNode::getI
 
 void MDNode::deleteTemporary(MDNode *N) {
   assert(N->isTemporary() && "Expected temporary node");
+  N->replaceAllUsesWith(nullptr);
   N->deleteAsSubclass();
 }
 

Added: llvm/trunk/test/Assembler/invalid-mdnode-badref.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Assembler/invalid-mdnode-badref.ll?rev=226866&view=auto
==============================================================================
--- llvm/trunk/test/Assembler/invalid-mdnode-badref.ll (added)
+++ llvm/trunk/test/Assembler/invalid-mdnode-badref.ll Thu Jan 22 15:36:45 2015
@@ -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}

Modified: llvm/trunk/unittests/IR/MetadataTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/IR/MetadataTest.cpp?rev=226866&r1=226865&r2=226866&view=diff
==============================================================================
--- llvm/trunk/unittests/IR/MetadataTest.cpp (original)
+++ llvm/trunk/unittests/IR/MetadataTest.cpp Thu Jan 22 15:36:45 2015
@@ -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) {





More information about the llvm-commits mailing list