From b6b8182be1735ff0ab66a0ab0d4b5cd3768234d9 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Sat, 2 Sep 2017 03:15:13 +0000 Subject: [PATCH] llvm-mt: Fix memory management in WindowsManifestMergerImpl::getMergedManifest Summary: xmlDoc needs to be released with xmlFreeDoc. XML_PARSE_NODICT is needed for safe moving nodes between documents. Buffer returned from xmlDocDumpFormatMemoryEnc needs xmlFree, but it needs outlive users of getMergedManifest results. Reviewers: ecbeckmann, rnk, zturner, ruiu Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D37321 llvm-svn: 312406 --- lib/WindowsManifest/WindowsManifestMerger.cpp | 44 +++++++++++++------ 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/lib/WindowsManifest/WindowsManifestMerger.cpp b/lib/WindowsManifest/WindowsManifestMerger.cpp index 91547c98469..c1ace5065e6 100644 --- a/lib/WindowsManifest/WindowsManifestMerger.cpp +++ b/lib/WindowsManifest/WindowsManifestMerger.cpp @@ -44,6 +44,14 @@ private: #if LLVM_LIBXML2_ENABLED xmlDocPtr CombinedDoc = nullptr; std::vector MergedDocs; + + bool Merged = false; + struct XmlDeleter { + void operator()(xmlChar *Ptr) { xmlFree(Ptr); } + void operator()(xmlDoc *Ptr) { xmlFreeDoc(Ptr); } + }; + int BufferSize = 0; + std::unique_ptr Buffer; #endif bool ParseErrorOccurred = false; }; @@ -613,14 +621,17 @@ WindowsManifestMerger::WindowsManifestMergerImpl::~WindowsManifestMergerImpl() { Error WindowsManifestMerger::WindowsManifestMergerImpl::merge( const MemoryBuffer &Manifest) { + if (Merged) + return make_error( + "merge after getMergedManifest is not supported"); if (Manifest.getBufferSize() == 0) return make_error( "attempted to merge empty manifest"); xmlSetGenericErrorFunc((void *)this, WindowsManifestMergerImpl::errorCallback); - xmlDocPtr ManifestXML = - xmlReadMemory(Manifest.getBufferStart(), Manifest.getBufferSize(), - "manifest.xml", nullptr, XML_PARSE_NOBLANKS); + xmlDocPtr ManifestXML = xmlReadMemory( + Manifest.getBufferStart(), Manifest.getBufferSize(), "manifest.xml", + nullptr, XML_PARSE_NOBLANKS | XML_PARSE_NODICT); xmlSetGenericErrorFunc(nullptr, nullptr); if (auto E = getParseError()) return E; @@ -646,22 +657,29 @@ Error WindowsManifestMerger::WindowsManifestMergerImpl::merge( std::unique_ptr WindowsManifestMerger::WindowsManifestMergerImpl::getMergedManifest() { - unsigned char *XmlBuff; - int BufferSize = 0; - if (CombinedDoc) { + if (!Merged) { + Merged = true; + + if (!CombinedDoc) + return nullptr; + xmlNodePtr CombinedRoot = xmlDocGetRootElement(CombinedDoc); std::vector RequiredPrefixes; checkAndStripPrefixes(CombinedRoot, RequiredPrefixes); - std::unique_ptr OutputDoc(xmlNewDoc((const unsigned char *)"1.0")); + std::unique_ptr OutputDoc( + xmlNewDoc((const unsigned char *)"1.0")); xmlDocSetRootElement(OutputDoc.get(), CombinedRoot); + assert(0 == xmlDocGetRootElement(CombinedDoc)); + xmlKeepBlanksDefault(0); - xmlDocDumpFormatMemoryEnc(OutputDoc.get(), &XmlBuff, &BufferSize, "UTF-8", - 1); + xmlChar *Buff = nullptr; + xmlDocDumpFormatMemoryEnc(OutputDoc.get(), &Buff, &BufferSize, "UTF-8", 1); + Buffer.reset(Buff); } - if (BufferSize == 0) - return nullptr; - return MemoryBuffer::getMemBuffer( - StringRef(FROM_XML_CHAR(XmlBuff), (size_t)BufferSize)); + + return BufferSize ? MemoryBuffer::getMemBuffer(StringRef( + FROM_XML_CHAR(Buffer.get()), (size_t)BufferSize)) + : nullptr; } #else