From 02fa38344c1cf1f27d59da5c3358d19bbb752f01 Mon Sep 17 00:00:00 2001 From: Nick Kledzik Date: Tue, 8 Jan 2013 21:04:44 +0000 Subject: [PATCH] Fix memory leak in YAML I/O. Stop using BumpPtrAllocator for HNodes because they have fields (vector, map) which require HNode destructors to be run. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@171896 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Support/YAMLTraits.h | 15 ++++++++--- lib/Support/YAMLTraits.cpp | 41 ++++++++++++++++++++++++------- 2 files changed, 43 insertions(+), 13 deletions(-) diff --git a/include/llvm/Support/YAMLTraits.h b/include/llvm/Support/YAMLTraits.h index 821333bf2f7..186228624a2 100644 --- a/include/llvm/Support/YAMLTraits.h +++ b/include/llvm/Support/YAMLTraits.h @@ -685,7 +685,8 @@ class Input : public IO { public: // Construct a yaml Input object from a StringRef and optional user-data. Input(StringRef InputContent, void *Ctxt=NULL); - + ~Input(); + // Check if there was an syntax or semantic error during parsing. llvm::error_code error(); @@ -718,6 +719,7 @@ private: class HNode { public: HNode(Node *n) : _node(n) { } + virtual ~HNode() { } static inline bool classof(const HNode *) { return true; } Node *_node; @@ -726,6 +728,7 @@ private: class EmptyHNode : public HNode { public: EmptyHNode(Node *n) : HNode(n) { } + virtual ~EmptyHNode() {} static inline bool classof(const HNode *n) { return NullNode::classof(n->_node); } @@ -735,6 +738,7 @@ private: class ScalarHNode : public HNode { public: ScalarHNode(Node *n, StringRef s) : HNode(n), _value(s) { } + virtual ~ScalarHNode() { } StringRef value() const { return _value; } @@ -749,6 +753,7 @@ private: class MapHNode : public HNode { public: MapHNode(Node *n) : HNode(n) { } + virtual ~MapHNode(); static inline bool classof(const HNode *n) { return MappingNode::classof(n->_node); @@ -774,6 +779,7 @@ private: class SequenceHNode : public HNode { public: SequenceHNode(Node *n) : HNode(n) { } + virtual ~SequenceHNode(); static inline bool classof(const HNode *n) { return SequenceNode::classof(n->_node); @@ -795,10 +801,11 @@ public: void nextDocument(); private: - llvm::yaml::Stream *Strm; - llvm::SourceMgr SrcMgr; + llvm::SourceMgr SrcMgr; // must be before Strm + OwningPtr Strm; + OwningPtr TopNode; llvm::error_code EC; - llvm::BumpPtrAllocator Allocator; + llvm::BumpPtrAllocator StringAllocator; llvm::yaml::document_iterator DocIterator; std::vector BitValuesUsed; HNode *CurrentNode; diff --git a/lib/Support/YAMLTraits.cpp b/lib/Support/YAMLTraits.cpp index ef3948dfd3a..9da2aa7c841 100644 --- a/lib/Support/YAMLTraits.cpp +++ b/lib/Support/YAMLTraits.cpp @@ -40,11 +40,17 @@ void IO::setContext(void *Context) { // Input //===----------------------------------------------------------------------===// -Input::Input(StringRef InputContent, void *Ctxt) : IO(Ctxt), CurrentNode(NULL) { - Strm = new Stream(InputContent, SrcMgr); +Input::Input(StringRef InputContent, void *Ctxt) + : IO(Ctxt), + Strm(new Stream(InputContent, SrcMgr)), + CurrentNode(NULL) { DocIterator = Strm->begin(); } +Input::~Input() { + +} + error_code Input::error() { return EC; } @@ -65,7 +71,8 @@ bool Input::setCurrentDocument() { ++DocIterator; return setCurrentDocument(); } - CurrentNode = this->createHNodes(N); + TopNode.reset(this->createHNodes(N)); + CurrentNode = TopNode.get(); return true; } return false; @@ -271,13 +278,13 @@ Input::HNode *Input::createHNodes(Node *N) { if (!StringStorage.empty()) { // Copy string to permanent storage unsigned Len = StringStorage.size(); - char *Buf = Allocator.Allocate(Len); + char *Buf = StringAllocator.Allocate(Len); memcpy(Buf, &StringStorage[0], Len); KeyStr = StringRef(Buf, Len); } - return new (Allocator) ScalarHNode(N, KeyStr); + return new ScalarHNode(N, KeyStr); } else if (SequenceNode *SQ = dyn_cast(N)) { - SequenceHNode *SQHNode = new (Allocator) SequenceHNode(N); + SequenceHNode *SQHNode = new SequenceHNode(N); for (SequenceNode::iterator i = SQ->begin(), End = SQ->end(); i != End; ++i) { HNode *Entry = this->createHNodes(i); @@ -287,7 +294,7 @@ Input::HNode *Input::createHNodes(Node *N) { } return SQHNode; } else if (MappingNode *Map = dyn_cast(N)) { - MapHNode *mapHNode = new (Allocator) MapHNode(N); + MapHNode *mapHNode = new MapHNode(N); for (MappingNode::iterator i = Map->begin(), End = Map->end(); i != End; ++i) { ScalarNode *KeyScalar = dyn_cast(i->getKey()); @@ -296,7 +303,7 @@ Input::HNode *Input::createHNodes(Node *N) { if (!StringStorage.empty()) { // Copy string to permanent storage unsigned Len = StringStorage.size(); - char *Buf = Allocator.Allocate(Len); + char *Buf = StringAllocator.Allocate(Len); memcpy(Buf, &StringStorage[0], Len); KeyStr = StringRef(Buf, Len); } @@ -307,7 +314,7 @@ Input::HNode *Input::createHNodes(Node *N) { } return mapHNode; } else if (isa(N)) { - return new (Allocator) EmptyHNode(N); + return new EmptyHNode(N); } else { setError(N, "unknown node kind"); return NULL; @@ -327,6 +334,22 @@ void Input::setError(const Twine &Message) { this->setError(CurrentNode, Message); } +Input::MapHNode::~MapHNode() { + for (MapHNode::NameToNode::iterator i = Mapping.begin(), End = Mapping.end(); + i != End; ++i) { + delete i->second; + } +} + +Input::SequenceHNode::~SequenceHNode() { + for (std::vector::iterator i = Entries.begin(), End = Entries.end(); + i != End; ++i) { + delete *i; + } +} + + + //===----------------------------------------------------------------------===// // Output //===----------------------------------------------------------------------===// -- 2.34.1