[llvm] r223858 - IR: Fix memory corruption in MDNode new/delete

Duncan P. N. Exon Smith dexonsmith at apple.com
Tue Dec 9 15:56:39 PST 2014


Author: dexonsmith
Date: Tue Dec  9 17:56:39 2014
New Revision: 223858

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

Modified:
    llvm/trunk/lib/IR/Metadata.cpp

Modified: llvm/trunk/lib/IR/Metadata.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Metadata.cpp?rev=223858&r1=223857&r2=223858&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Metadata.cpp (original)
+++ llvm/trunk/lib/IR/Metadata.cpp Tue Dec  9 17:56:39 2014
@@ -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<MDOperand *>(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<MDNode *>(Mem);
-  MDOperand *Last = static_cast<MDOperand *>(Mem);
-  ::operator delete(Last - N->NumOperands);
+  MDOperand *O = static_cast<MDOperand *>(Mem);
+  for (MDOperand *E = O - N->NumOperands; O != E; --O)
+    (O - 1)->~MDOperand();
+  ::operator delete(O);
 }
 
 MDNode::MDNode(LLVMContext &Context, unsigned ID, ArrayRef<Metadata *> MDs)





More information about the llvm-commits mailing list