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.)

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@226866 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Duncan P. N. Exon Smith 2015-01-22 21:36:45 +00:00
parent 40a218658a
commit 003346177c
4 changed files with 19 additions and 1 deletions

View 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(); }

View 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();
}

View File

@ -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}

View 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) {