From ea614a50253ab17cf140fe0ce46d5bb169f45989 Mon Sep 17 00:00:00 2001 From: "Duncan P. N. Exon Smith" Date: Tue, 9 Dec 2014 23:56:39 +0000 Subject: [PATCH] IR: Fix memory corruption in MDNode new/delete There were two major problems with `MDNode` memory management. 1. `MDNode::operator new()` called a placement array constructor for `MDOperand`. What? Each operand needs to be placed individually. 2. `MDNode::operator delete()` failed to destruct the `MDOperand`s at all. Frankly it's hard to understand how this worked locally, how this survived an LTO bootstrap, or how it worked on most of the bots. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@223858 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/IR/Metadata.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/IR/Metadata.cpp b/lib/IR/Metadata.cpp index 7a354c42c4c..0f748495261 100644 --- a/lib/IR/Metadata.cpp +++ b/lib/IR/Metadata.cpp @@ -378,14 +378,18 @@ StringRef MDString::getString() const { void *MDNode::operator new(size_t Size, unsigned NumOps) { void *Ptr = ::operator new(Size + NumOps * sizeof(MDOperand)); - MDOperand *First = new (Ptr) MDOperand[NumOps]; - return First + NumOps; + MDOperand *O = static_cast(Ptr); + for (MDOperand *E = O + NumOps; O != E; ++O) + (void)new (O) MDOperand; + return O; } void MDNode::operator delete(void *Mem) { MDNode *N = static_cast(Mem); - MDOperand *Last = static_cast(Mem); - ::operator delete(Last - N->NumOperands); + MDOperand *O = static_cast(Mem); + for (MDOperand *E = O - N->NumOperands; O != E; --O) + (O - 1)->~MDOperand(); + ::operator delete(O); } MDNode::MDNode(LLVMContext &Context, unsigned ID, ArrayRef MDs) -- 2.34.1