xref: /openbsd-src/gnu/llvm/llvm/lib/WindowsManifest/WindowsManifestMerger.cpp (revision d415bd752c734aee168c4ee86ff32e8cc249eb16)
109467b48Spatrick //===-- WindowsManifestMerger.cpp ------------------------------*- C++ -*-===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===---------------------------------------------------------------------===//
809467b48Spatrick //
909467b48Spatrick // This file implements the .manifest merger class.
1009467b48Spatrick //
1109467b48Spatrick //===---------------------------------------------------------------------===//
1209467b48Spatrick 
1309467b48Spatrick #include "llvm/WindowsManifest/WindowsManifestMerger.h"
1409467b48Spatrick #include "llvm/Config/config.h"
1509467b48Spatrick #include "llvm/Support/MemoryBuffer.h"
1609467b48Spatrick 
1773471bf0Spatrick #if LLVM_ENABLE_LIBXML2
1809467b48Spatrick #include <libxml/xmlreader.h>
1909467b48Spatrick #endif
2009467b48Spatrick 
2109467b48Spatrick #define TO_XML_CHAR(X) reinterpret_cast<const unsigned char *>(X)
2209467b48Spatrick #define FROM_XML_CHAR(X) reinterpret_cast<const char *>(X)
2309467b48Spatrick 
2409467b48Spatrick using namespace llvm;
2509467b48Spatrick using namespace windows_manifest;
2609467b48Spatrick 
2709467b48Spatrick char WindowsManifestError::ID = 0;
2809467b48Spatrick 
WindowsManifestError(const Twine & Msg)2909467b48Spatrick WindowsManifestError::WindowsManifestError(const Twine &Msg) : Msg(Msg.str()) {}
3009467b48Spatrick 
log(raw_ostream & OS) const3109467b48Spatrick void WindowsManifestError::log(raw_ostream &OS) const { OS << Msg; }
3209467b48Spatrick 
3309467b48Spatrick class WindowsManifestMerger::WindowsManifestMergerImpl {
3409467b48Spatrick public:
3509467b48Spatrick   ~WindowsManifestMergerImpl();
36*d415bd75Srobert   Error merge(MemoryBufferRef Manifest);
3709467b48Spatrick   std::unique_ptr<MemoryBuffer> getMergedManifest();
3809467b48Spatrick 
3909467b48Spatrick private:
4009467b48Spatrick   static void errorCallback(void *Ctx, const char *Format, ...);
4109467b48Spatrick   Error getParseError();
4273471bf0Spatrick #if LLVM_ENABLE_LIBXML2
4309467b48Spatrick   xmlDocPtr CombinedDoc = nullptr;
4409467b48Spatrick   std::vector<xmlDocPtr> MergedDocs;
4509467b48Spatrick 
4609467b48Spatrick   bool Merged = false;
4709467b48Spatrick   struct XmlDeleter {
operator ()WindowsManifestMerger::WindowsManifestMergerImpl::XmlDeleter4809467b48Spatrick     void operator()(xmlChar *Ptr) { xmlFree(Ptr); }
operator ()WindowsManifestMerger::WindowsManifestMergerImpl::XmlDeleter4909467b48Spatrick     void operator()(xmlDoc *Ptr) { xmlFreeDoc(Ptr); }
5009467b48Spatrick   };
5109467b48Spatrick   int BufferSize = 0;
5209467b48Spatrick   std::unique_ptr<xmlChar, XmlDeleter> Buffer;
5309467b48Spatrick #endif
5409467b48Spatrick   bool ParseErrorOccurred = false;
5509467b48Spatrick };
5609467b48Spatrick 
5773471bf0Spatrick #if LLVM_ENABLE_LIBXML2
5809467b48Spatrick 
5909467b48Spatrick static constexpr std::pair<StringLiteral, StringLiteral> MtNsHrefsPrefixes[] = {
6009467b48Spatrick     {"urn:schemas-microsoft-com:asm.v1", "ms_asmv1"},
6109467b48Spatrick     {"urn:schemas-microsoft-com:asm.v2", "ms_asmv2"},
6209467b48Spatrick     {"urn:schemas-microsoft-com:asm.v3", "ms_asmv3"},
6309467b48Spatrick     {"http://schemas.microsoft.com/SMI/2005/WindowsSettings",
6409467b48Spatrick      "ms_windowsSettings"},
6509467b48Spatrick     {"urn:schemas-microsoft-com:compatibility.v1", "ms_compatibilityv1"}};
6609467b48Spatrick 
xmlStringsEqual(const unsigned char * A,const unsigned char * B)6709467b48Spatrick static bool xmlStringsEqual(const unsigned char *A, const unsigned char *B) {
6809467b48Spatrick   // Handle null pointers.  Comparison of 2 null pointers returns true because
6909467b48Spatrick   // this indicates the prefix of a default namespace.
7009467b48Spatrick   if (!A || !B)
7109467b48Spatrick     return A == B;
7209467b48Spatrick   return strcmp(FROM_XML_CHAR(A), FROM_XML_CHAR(B)) == 0;
7309467b48Spatrick }
7409467b48Spatrick 
isMergeableElement(const unsigned char * ElementName)7509467b48Spatrick static bool isMergeableElement(const unsigned char *ElementName) {
7609467b48Spatrick   for (StringRef S : {"application", "assembly", "assemblyIdentity",
7709467b48Spatrick                       "compatibility", "noInherit", "requestedExecutionLevel",
7809467b48Spatrick                       "requestedPrivileges", "security", "trustInfo"}) {
7909467b48Spatrick     if (S == FROM_XML_CHAR(ElementName)) {
8009467b48Spatrick       return true;
8109467b48Spatrick     }
8209467b48Spatrick   }
8309467b48Spatrick   return false;
8409467b48Spatrick }
8509467b48Spatrick 
getChildWithName(xmlNodePtr Parent,const unsigned char * ElementName)8609467b48Spatrick static xmlNodePtr getChildWithName(xmlNodePtr Parent,
8709467b48Spatrick                                    const unsigned char *ElementName) {
8809467b48Spatrick   for (xmlNodePtr Child = Parent->children; Child; Child = Child->next) {
8909467b48Spatrick     if (xmlStringsEqual(Child->name, ElementName)) {
9009467b48Spatrick       return Child;
9109467b48Spatrick     }
9209467b48Spatrick   }
9309467b48Spatrick   return nullptr;
9409467b48Spatrick }
9509467b48Spatrick 
getAttribute(xmlNodePtr Node,const unsigned char * AttributeName)9609467b48Spatrick static xmlAttrPtr getAttribute(xmlNodePtr Node,
9709467b48Spatrick                                const unsigned char *AttributeName) {
9809467b48Spatrick   for (xmlAttrPtr Attribute = Node->properties; Attribute != nullptr;
9909467b48Spatrick        Attribute = Attribute->next) {
10009467b48Spatrick     if (xmlStringsEqual(Attribute->name, AttributeName)) {
10109467b48Spatrick       return Attribute;
10209467b48Spatrick     }
10309467b48Spatrick   }
10409467b48Spatrick   return nullptr;
10509467b48Spatrick }
10609467b48Spatrick 
10709467b48Spatrick // Check if namespace specified by HRef1 overrides that of HRef2.
namespaceOverrides(const unsigned char * HRef1,const unsigned char * HRef2)10809467b48Spatrick static bool namespaceOverrides(const unsigned char *HRef1,
10909467b48Spatrick                                const unsigned char *HRef2) {
11009467b48Spatrick   auto HRef1Position = llvm::find_if(
11109467b48Spatrick       MtNsHrefsPrefixes, [=](const std::pair<StringRef, StringRef> &Element) {
11209467b48Spatrick         return xmlStringsEqual(HRef1, TO_XML_CHAR(Element.first.data()));
11309467b48Spatrick       });
11409467b48Spatrick   auto HRef2Position = llvm::find_if(
11509467b48Spatrick       MtNsHrefsPrefixes, [=](const std::pair<StringRef, StringRef> &Element) {
11609467b48Spatrick         return xmlStringsEqual(HRef2, TO_XML_CHAR(Element.first.data()));
11709467b48Spatrick       });
11809467b48Spatrick   return HRef1Position < HRef2Position;
11909467b48Spatrick }
12009467b48Spatrick 
12109467b48Spatrick // Search for prefix-defined namespace specified by HRef, starting on Node and
12209467b48Spatrick // continuing recursively upwards.  Returns the namespace or nullptr if not
12309467b48Spatrick // found.
search(const unsigned char * HRef,xmlNodePtr Node)12409467b48Spatrick static xmlNsPtr search(const unsigned char *HRef, xmlNodePtr Node) {
12509467b48Spatrick   for (xmlNsPtr Def = Node->nsDef; Def; Def = Def->next) {
12609467b48Spatrick     if (Def->prefix && xmlStringsEqual(Def->href, HRef)) {
12709467b48Spatrick       return Def;
12809467b48Spatrick     }
12909467b48Spatrick   }
13009467b48Spatrick   if (Node->parent) {
13109467b48Spatrick     return search(HRef, Node->parent);
13209467b48Spatrick   }
13309467b48Spatrick   return nullptr;
13409467b48Spatrick }
13509467b48Spatrick 
13609467b48Spatrick // Return the prefix that corresponds to the HRef.  If HRef is not a recognized
13709467b48Spatrick // URI, then just return the HRef itself to use as the prefix.
getPrefixForHref(const unsigned char * HRef)13809467b48Spatrick static const unsigned char *getPrefixForHref(const unsigned char *HRef) {
13909467b48Spatrick   for (auto &Ns : MtNsHrefsPrefixes) {
14009467b48Spatrick     if (xmlStringsEqual(HRef, TO_XML_CHAR(Ns.first.data()))) {
14109467b48Spatrick       return TO_XML_CHAR(Ns.second.data());
14209467b48Spatrick     }
14309467b48Spatrick   }
14409467b48Spatrick   return HRef;
14509467b48Spatrick }
14609467b48Spatrick 
14709467b48Spatrick // Search for prefix-defined namespace specified by HRef, starting on Node and
14809467b48Spatrick // continuing recursively upwards.  If it is found, then return it.  If it is
14909467b48Spatrick // not found, then prefix-define that namespace on the node and return a
15009467b48Spatrick // reference to it.
searchOrDefine(const unsigned char * HRef,xmlNodePtr Node)15109467b48Spatrick static Expected<xmlNsPtr> searchOrDefine(const unsigned char *HRef,
15209467b48Spatrick                                          xmlNodePtr Node) {
15309467b48Spatrick   if (xmlNsPtr Def = search(HRef, Node))
15409467b48Spatrick     return Def;
15509467b48Spatrick   if (xmlNsPtr Def = xmlNewNs(Node, HRef, getPrefixForHref(HRef)))
15609467b48Spatrick     return Def;
15709467b48Spatrick   return make_error<WindowsManifestError>("failed to create new namespace");
15809467b48Spatrick }
15909467b48Spatrick 
16009467b48Spatrick // Set the namespace of OrigionalAttribute on OriginalNode to be that of
16109467b48Spatrick // AdditionalAttribute's.
copyAttributeNamespace(xmlAttrPtr OriginalAttribute,xmlNodePtr OriginalNode,xmlAttrPtr AdditionalAttribute)16209467b48Spatrick static Error copyAttributeNamespace(xmlAttrPtr OriginalAttribute,
16309467b48Spatrick                                     xmlNodePtr OriginalNode,
16409467b48Spatrick                                     xmlAttrPtr AdditionalAttribute) {
16509467b48Spatrick 
16609467b48Spatrick   Expected<xmlNsPtr> ExplicitOrError =
16709467b48Spatrick       searchOrDefine(AdditionalAttribute->ns->href, OriginalNode);
16809467b48Spatrick   if (!ExplicitOrError)
16909467b48Spatrick     return ExplicitOrError.takeError();
17009467b48Spatrick   OriginalAttribute->ns = std::move(ExplicitOrError.get());
17109467b48Spatrick   return Error::success();
17209467b48Spatrick }
17309467b48Spatrick 
17409467b48Spatrick // Return the corresponding namespace definition for the prefix, defined on the
17509467b48Spatrick // given Node.  Returns nullptr if there is no such definition.
getNamespaceWithPrefix(const unsigned char * Prefix,xmlNodePtr Node)17609467b48Spatrick static xmlNsPtr getNamespaceWithPrefix(const unsigned char *Prefix,
17709467b48Spatrick                                        xmlNodePtr Node) {
17809467b48Spatrick   if (Node == nullptr)
17909467b48Spatrick     return nullptr;
18009467b48Spatrick   for (xmlNsPtr Def = Node->nsDef; Def; Def = Def->next) {
18109467b48Spatrick     if (xmlStringsEqual(Def->prefix, Prefix)) {
18209467b48Spatrick       return Def;
18309467b48Spatrick     }
18409467b48Spatrick   }
18509467b48Spatrick   return nullptr;
18609467b48Spatrick }
18709467b48Spatrick 
18809467b48Spatrick // Search for the closest inheritable default namespace, starting on (and
18909467b48Spatrick // including) the Node and traveling upwards through parent nodes.  Returns
19009467b48Spatrick // nullptr if there are no inheritable default namespaces.
getClosestDefault(xmlNodePtr Node)19109467b48Spatrick static xmlNsPtr getClosestDefault(xmlNodePtr Node) {
19209467b48Spatrick   if (xmlNsPtr Ret = getNamespaceWithPrefix(nullptr, Node))
19309467b48Spatrick     return Ret;
19409467b48Spatrick   if (Node->parent == nullptr)
19509467b48Spatrick     return nullptr;
19609467b48Spatrick   return getClosestDefault(Node->parent);
19709467b48Spatrick }
19809467b48Spatrick 
19909467b48Spatrick // Merge the attributes of AdditionalNode into OriginalNode.  If attributes
20009467b48Spatrick // with identical types are present, they are not duplicated but rather if
20109467b48Spatrick // their values are not consistent and error is thrown.  In addition, the
20209467b48Spatrick // higher priority namespace is used for each attribute, EXCEPT in the case
20309467b48Spatrick // of merging two default namespaces and the lower priority namespace
20409467b48Spatrick // definition occurs closer than the higher priority one.
mergeAttributes(xmlNodePtr OriginalNode,xmlNodePtr AdditionalNode)20509467b48Spatrick static Error mergeAttributes(xmlNodePtr OriginalNode,
20609467b48Spatrick                              xmlNodePtr AdditionalNode) {
20709467b48Spatrick   xmlNsPtr ClosestDefault = getClosestDefault(OriginalNode);
20809467b48Spatrick   for (xmlAttrPtr Attribute = AdditionalNode->properties; Attribute;
20909467b48Spatrick        Attribute = Attribute->next) {
21009467b48Spatrick     if (xmlAttrPtr OriginalAttribute =
21109467b48Spatrick             getAttribute(OriginalNode, Attribute->name)) {
21209467b48Spatrick       if (!xmlStringsEqual(OriginalAttribute->children->content,
21309467b48Spatrick                            Attribute->children->content)) {
21409467b48Spatrick         return make_error<WindowsManifestError>(
21509467b48Spatrick             Twine("conflicting attributes for ") +
21609467b48Spatrick             FROM_XML_CHAR(OriginalNode->name));
21709467b48Spatrick       }
21809467b48Spatrick       if (!Attribute->ns) {
21909467b48Spatrick         continue;
22009467b48Spatrick       }
22109467b48Spatrick       if (!OriginalAttribute->ns) {
22209467b48Spatrick         if (auto E = copyAttributeNamespace(OriginalAttribute, OriginalNode,
22309467b48Spatrick                                             Attribute)) {
22409467b48Spatrick           return E;
22509467b48Spatrick         }
22609467b48Spatrick         continue;
22709467b48Spatrick       }
22809467b48Spatrick       if (namespaceOverrides(OriginalAttribute->ns->href,
22909467b48Spatrick                              Attribute->ns->href)) {
23009467b48Spatrick         // In this case, the original attribute has a higher priority namespace
23109467b48Spatrick         // than the incomiing attribute, however the namespace definition of
23209467b48Spatrick         // the lower priority namespace occurs first traveling upwards in the
23309467b48Spatrick         // tree.  Therefore the lower priority namespace is applied.
23409467b48Spatrick         if (!OriginalAttribute->ns->prefix && !Attribute->ns->prefix &&
23509467b48Spatrick             ClosestDefault &&
23609467b48Spatrick             xmlStringsEqual(Attribute->ns->href, ClosestDefault->href)) {
23709467b48Spatrick           if (auto E = copyAttributeNamespace(OriginalAttribute, OriginalNode,
23809467b48Spatrick                                               Attribute)) {
23909467b48Spatrick             return E;
24009467b48Spatrick           }
24109467b48Spatrick           continue;
24209467b48Spatrick         }
24309467b48Spatrick         continue;
24409467b48Spatrick         // This covers the case where the incoming attribute has the higher
24509467b48Spatrick         // priority.  The higher priority namespace is applied in all cases
24609467b48Spatrick         // EXCEPT when both of the namespaces are default inherited, and the
24709467b48Spatrick         // closest inherited default is the lower priority one.
24809467b48Spatrick       }
24909467b48Spatrick       if (Attribute->ns->prefix || OriginalAttribute->ns->prefix ||
25009467b48Spatrick           (ClosestDefault && !xmlStringsEqual(OriginalAttribute->ns->href,
25109467b48Spatrick                                               ClosestDefault->href))) {
25209467b48Spatrick         if (auto E = copyAttributeNamespace(OriginalAttribute, OriginalNode,
25309467b48Spatrick                                             Attribute)) {
25409467b48Spatrick           return E;
25509467b48Spatrick         }
25609467b48Spatrick         continue;
25709467b48Spatrick       }
25809467b48Spatrick       continue;
25909467b48Spatrick     }
26009467b48Spatrick     // If the incoming attribute is not already found on the node, append it
26109467b48Spatrick     // to the end of the properties list.  Also explicitly apply its
26209467b48Spatrick     // namespace as a prefix because it might be contained in a separate
26309467b48Spatrick     // namespace that doesn't use the attribute.
26409467b48Spatrick     xmlAttrPtr NewProp =
26509467b48Spatrick         xmlNewProp(OriginalNode, Attribute->name, Attribute->children->content);
26609467b48Spatrick     Expected<xmlNsPtr> ExplicitOrError =
26709467b48Spatrick         searchOrDefine(Attribute->ns->href, OriginalNode);
26809467b48Spatrick     if (!ExplicitOrError)
26909467b48Spatrick       return ExplicitOrError.takeError();
27009467b48Spatrick     NewProp->ns = std::move(ExplicitOrError.get());
27109467b48Spatrick   }
27209467b48Spatrick   return Error::success();
27309467b48Spatrick }
27409467b48Spatrick 
27509467b48Spatrick // Given two nodes, return the one with the higher priority namespace.
getDominantNode(xmlNodePtr Node1,xmlNodePtr Node2)27609467b48Spatrick static xmlNodePtr getDominantNode(xmlNodePtr Node1, xmlNodePtr Node2) {
27709467b48Spatrick 
27809467b48Spatrick   if (!Node1 || !Node1->ns)
27909467b48Spatrick     return Node2;
28009467b48Spatrick   if (!Node2 || !Node2->ns)
28109467b48Spatrick     return Node1;
28209467b48Spatrick   if (namespaceOverrides(Node1->ns->href, Node2->ns->href))
28309467b48Spatrick     return Node1;
28409467b48Spatrick   return Node2;
28509467b48Spatrick }
28609467b48Spatrick 
28709467b48Spatrick // Checks if this Node's namespace is inherited or one it defined itself.
hasInheritedNs(xmlNodePtr Node)28809467b48Spatrick static bool hasInheritedNs(xmlNodePtr Node) {
28909467b48Spatrick   return Node->ns && Node->ns != getNamespaceWithPrefix(Node->ns->prefix, Node);
29009467b48Spatrick }
29109467b48Spatrick 
29209467b48Spatrick // Check if this Node's namespace is a default namespace that it inherited, as
29309467b48Spatrick // opposed to defining itself.
hasInheritedDefaultNs(xmlNodePtr Node)29409467b48Spatrick static bool hasInheritedDefaultNs(xmlNodePtr Node) {
29509467b48Spatrick   return hasInheritedNs(Node) && Node->ns->prefix == nullptr;
29609467b48Spatrick }
29709467b48Spatrick 
29809467b48Spatrick // Check if this Node's namespace is a default namespace it defined itself.
hasDefinedDefaultNamespace(xmlNodePtr Node)29909467b48Spatrick static bool hasDefinedDefaultNamespace(xmlNodePtr Node) {
30009467b48Spatrick   return Node->ns && (Node->ns == getNamespaceWithPrefix(nullptr, Node));
30109467b48Spatrick }
30209467b48Spatrick 
30309467b48Spatrick // For the given explicit prefix-definition of a namespace, travel downwards
30409467b48Spatrick // from a node recursively, and for every implicit, inherited default usage of
30509467b48Spatrick // that namespace replace it with that explicit prefix use.  This is important
30609467b48Spatrick // when namespace overriding occurs when merging, so that elements unique to a
30709467b48Spatrick // namespace will still stay in that namespace.
explicateNamespace(xmlNsPtr PrefixDef,xmlNodePtr Node)30809467b48Spatrick static void explicateNamespace(xmlNsPtr PrefixDef, xmlNodePtr Node) {
30909467b48Spatrick   // If a node as its own default namespace definition it clearly cannot have
31009467b48Spatrick   // inherited the given default namespace, and neither will any of its
31109467b48Spatrick   // children.
31209467b48Spatrick   if (hasDefinedDefaultNamespace(Node))
31309467b48Spatrick     return;
31409467b48Spatrick   if (Node->ns && xmlStringsEqual(Node->ns->href, PrefixDef->href) &&
31509467b48Spatrick       hasInheritedDefaultNs(Node))
31609467b48Spatrick     Node->ns = PrefixDef;
31709467b48Spatrick   for (xmlAttrPtr Attribute = Node->properties; Attribute;
31809467b48Spatrick        Attribute = Attribute->next) {
31909467b48Spatrick     if (Attribute->ns &&
32009467b48Spatrick         xmlStringsEqual(Attribute->ns->href, PrefixDef->href)) {
32109467b48Spatrick       Attribute->ns = PrefixDef;
32209467b48Spatrick     }
32309467b48Spatrick   }
32409467b48Spatrick   for (xmlNodePtr Child = Node->children; Child; Child = Child->next) {
32509467b48Spatrick     explicateNamespace(PrefixDef, Child);
32609467b48Spatrick   }
32709467b48Spatrick }
32809467b48Spatrick 
32909467b48Spatrick // Perform the namespace merge between two nodes.
mergeNamespaces(xmlNodePtr OriginalNode,xmlNodePtr AdditionalNode)33009467b48Spatrick static Error mergeNamespaces(xmlNodePtr OriginalNode,
33109467b48Spatrick                              xmlNodePtr AdditionalNode) {
33209467b48Spatrick   // Save the original default namespace definition in case the incoming node
33309467b48Spatrick   // overrides it.
33409467b48Spatrick   const unsigned char *OriginalDefinedDefaultHref = nullptr;
33509467b48Spatrick   if (xmlNsPtr OriginalDefinedDefaultNs =
33609467b48Spatrick           getNamespaceWithPrefix(nullptr, OriginalNode)) {
33709467b48Spatrick     OriginalDefinedDefaultHref = xmlStrdup(OriginalDefinedDefaultNs->href);
33809467b48Spatrick   }
33909467b48Spatrick   const unsigned char *NewDefinedDefaultHref = nullptr;
34009467b48Spatrick   // Copy all namespace definitions.  There can only be one default namespace
34109467b48Spatrick   // definition per node, so the higher priority one takes precedence in the
34209467b48Spatrick   // case of collision.
34309467b48Spatrick   for (xmlNsPtr Def = AdditionalNode->nsDef; Def; Def = Def->next) {
34409467b48Spatrick     if (xmlNsPtr OriginalNsDef =
34509467b48Spatrick             getNamespaceWithPrefix(Def->prefix, OriginalNode)) {
34609467b48Spatrick       if (!Def->prefix) {
34709467b48Spatrick         if (namespaceOverrides(Def->href, OriginalNsDef->href)) {
34809467b48Spatrick           NewDefinedDefaultHref = TO_XML_CHAR(strdup(FROM_XML_CHAR(Def->href)));
34909467b48Spatrick         }
35009467b48Spatrick       } else if (!xmlStringsEqual(OriginalNsDef->href, Def->href)) {
35109467b48Spatrick         return make_error<WindowsManifestError>(
35209467b48Spatrick             Twine("conflicting namespace definitions for ") +
35309467b48Spatrick             FROM_XML_CHAR(Def->prefix));
35409467b48Spatrick       }
35509467b48Spatrick     } else {
35609467b48Spatrick       xmlNsPtr NewDef = xmlCopyNamespace(Def);
35709467b48Spatrick       NewDef->next = OriginalNode->nsDef;
35809467b48Spatrick       OriginalNode->nsDef = NewDef;
35909467b48Spatrick     }
36009467b48Spatrick   }
36109467b48Spatrick 
36209467b48Spatrick   // Check whether the original node or the incoming node has the higher
36309467b48Spatrick   // priority namespace.  Depending on which one is dominant, we will have
36409467b48Spatrick   // to recursively apply namespace changes down to children of the original
36509467b48Spatrick   // node.
36609467b48Spatrick   xmlNodePtr DominantNode = getDominantNode(OriginalNode, AdditionalNode);
36709467b48Spatrick   xmlNodePtr NonDominantNode =
36809467b48Spatrick       DominantNode == OriginalNode ? AdditionalNode : OriginalNode;
36909467b48Spatrick   if (DominantNode == OriginalNode) {
37009467b48Spatrick     if (OriginalDefinedDefaultHref) {
37109467b48Spatrick       xmlNsPtr NonDominantDefinedDefault =
37209467b48Spatrick           getNamespaceWithPrefix(nullptr, NonDominantNode);
37309467b48Spatrick       // In this case, both the nodes defined a default namespace.  However
37409467b48Spatrick       // the lower priority node ended up having a higher priority default
37509467b48Spatrick       // definition.  This can occur if the higher priority node is prefix
37609467b48Spatrick       // namespace defined.  In this case we have to define an explicit
37709467b48Spatrick       // prefix for the overridden definition and apply it to all children
37809467b48Spatrick       // who relied on that definition.
37909467b48Spatrick       if (NonDominantDefinedDefault &&
38009467b48Spatrick           namespaceOverrides(NonDominantDefinedDefault->href,
38109467b48Spatrick                              OriginalDefinedDefaultHref)) {
38209467b48Spatrick         Expected<xmlNsPtr> EC =
38309467b48Spatrick             searchOrDefine(OriginalDefinedDefaultHref, DominantNode);
38409467b48Spatrick         if (!EC) {
38509467b48Spatrick           return EC.takeError();
38609467b48Spatrick         }
38709467b48Spatrick         xmlNsPtr PrefixDominantDefinedDefault = std::move(EC.get());
38809467b48Spatrick         explicateNamespace(PrefixDominantDefinedDefault, DominantNode);
38909467b48Spatrick       }
39009467b48Spatrick       // In this case the node with a higher priority namespace did not have a
39109467b48Spatrick       // default namespace definition, but the lower priority node did.  In this
39209467b48Spatrick       // case the new default namespace definition is copied.  A side effect of
39309467b48Spatrick       // this is that all children will suddenly find themselves in a different
39409467b48Spatrick       // default namespace.  To maintain correctness we need to ensure that all
39509467b48Spatrick       // children now explicitly refer to the namespace that they had previously
39609467b48Spatrick       // implicitly inherited.
39709467b48Spatrick     } else if (getNamespaceWithPrefix(nullptr, NonDominantNode)) {
39809467b48Spatrick       if (DominantNode->parent) {
39909467b48Spatrick         xmlNsPtr ClosestDefault = getClosestDefault(DominantNode->parent);
40009467b48Spatrick         Expected<xmlNsPtr> EC =
40109467b48Spatrick             searchOrDefine(ClosestDefault->href, DominantNode);
40209467b48Spatrick         if (!EC) {
40309467b48Spatrick           return EC.takeError();
40409467b48Spatrick         }
40509467b48Spatrick         xmlNsPtr ExplicitDefault = std::move(EC.get());
40609467b48Spatrick         explicateNamespace(ExplicitDefault, DominantNode);
40709467b48Spatrick       }
40809467b48Spatrick     }
40909467b48Spatrick   } else {
41009467b48Spatrick     // Covers case where the incoming node has a default namespace definition
41109467b48Spatrick     // that overrides the original node's namespace.  This always leads to
41209467b48Spatrick     // the original node receiving that new default namespace.
41309467b48Spatrick     if (hasDefinedDefaultNamespace(DominantNode)) {
41409467b48Spatrick       NonDominantNode->ns = getNamespaceWithPrefix(nullptr, NonDominantNode);
41509467b48Spatrick     } else {
41609467b48Spatrick       // This covers the case where the incoming node either has a prefix
41709467b48Spatrick       // namespace, or an inherited default namespace.  Since the namespace
41809467b48Spatrick       // may not yet be defined in the original tree we do a searchOrDefine
41909467b48Spatrick       // for it, and then set the namespace equal to it.
42009467b48Spatrick       Expected<xmlNsPtr> EC =
42109467b48Spatrick           searchOrDefine(DominantNode->ns->href, NonDominantNode);
42209467b48Spatrick       if (!EC) {
42309467b48Spatrick         return EC.takeError();
42409467b48Spatrick       }
42509467b48Spatrick       xmlNsPtr Explicit = std::move(EC.get());
42609467b48Spatrick       NonDominantNode->ns = Explicit;
42709467b48Spatrick     }
42809467b48Spatrick     // This covers cases where the incoming dominant node HAS a default
42909467b48Spatrick     // namespace definition, but MIGHT NOT NECESSARILY be in that namespace.
43009467b48Spatrick     if (xmlNsPtr DominantDefaultDefined =
43109467b48Spatrick             getNamespaceWithPrefix(nullptr, DominantNode)) {
43209467b48Spatrick       if (OriginalDefinedDefaultHref) {
43309467b48Spatrick         if (namespaceOverrides(DominantDefaultDefined->href,
43409467b48Spatrick                                OriginalDefinedDefaultHref)) {
43509467b48Spatrick           // In this case, the incoming node's default definition overrides
43609467b48Spatrick           // the original default definition, all children who relied on that
43709467b48Spatrick           // definition must be updated accordingly.
43809467b48Spatrick           Expected<xmlNsPtr> EC =
43909467b48Spatrick               searchOrDefine(OriginalDefinedDefaultHref, NonDominantNode);
44009467b48Spatrick           if (!EC) {
44109467b48Spatrick             return EC.takeError();
44209467b48Spatrick           }
44309467b48Spatrick           xmlNsPtr ExplicitDefault = std::move(EC.get());
44409467b48Spatrick           explicateNamespace(ExplicitDefault, NonDominantNode);
44509467b48Spatrick         }
44609467b48Spatrick       } else {
44709467b48Spatrick         // The original did not define a default definition, however the new
44809467b48Spatrick         // default definition still applies to all children, so they must be
44909467b48Spatrick         // updated to explicitly refer to the namespace they had previously
45009467b48Spatrick         // been inheriting implicitly.
45109467b48Spatrick         xmlNsPtr ClosestDefault = getClosestDefault(NonDominantNode);
45209467b48Spatrick         Expected<xmlNsPtr> EC =
45309467b48Spatrick             searchOrDefine(ClosestDefault->href, NonDominantNode);
45409467b48Spatrick         if (!EC) {
45509467b48Spatrick           return EC.takeError();
45609467b48Spatrick         }
45709467b48Spatrick         xmlNsPtr ExplicitDefault = std::move(EC.get());
45809467b48Spatrick         explicateNamespace(ExplicitDefault, NonDominantNode);
45909467b48Spatrick       }
46009467b48Spatrick     }
46109467b48Spatrick   }
46209467b48Spatrick   if (NewDefinedDefaultHref) {
46309467b48Spatrick     xmlNsPtr OriginalNsDef = getNamespaceWithPrefix(nullptr, OriginalNode);
46409467b48Spatrick     xmlFree(const_cast<unsigned char *>(OriginalNsDef->href));
46509467b48Spatrick     OriginalNsDef->href = NewDefinedDefaultHref;
46609467b48Spatrick   }
46709467b48Spatrick   xmlFree(const_cast<unsigned char *>(OriginalDefinedDefaultHref));
46809467b48Spatrick   return Error::success();
46909467b48Spatrick }
47009467b48Spatrick 
isRecognizedNamespace(const unsigned char * NsHref)47109467b48Spatrick static bool isRecognizedNamespace(const unsigned char *NsHref) {
47209467b48Spatrick   for (auto &Ns : MtNsHrefsPrefixes) {
47309467b48Spatrick     if (xmlStringsEqual(NsHref, TO_XML_CHAR(Ns.first.data()))) {
47409467b48Spatrick       return true;
47509467b48Spatrick     }
47609467b48Spatrick   }
47709467b48Spatrick   return false;
47809467b48Spatrick }
47909467b48Spatrick 
hasRecognizedNamespace(xmlNodePtr Node)48009467b48Spatrick static bool hasRecognizedNamespace(xmlNodePtr Node) {
48109467b48Spatrick   return isRecognizedNamespace(Node->ns->href);
48209467b48Spatrick }
48309467b48Spatrick 
48409467b48Spatrick // Ensure a node's inherited namespace is actually defined in the tree it
48509467b48Spatrick // resides in.
reconcileNamespaces(xmlNodePtr Node)48609467b48Spatrick static Error reconcileNamespaces(xmlNodePtr Node) {
48709467b48Spatrick   if (!Node) {
48809467b48Spatrick     return Error::success();
48909467b48Spatrick   }
49009467b48Spatrick   if (hasInheritedNs(Node)) {
49109467b48Spatrick     Expected<xmlNsPtr> ExplicitOrError = searchOrDefine(Node->ns->href, Node);
49209467b48Spatrick     if (!ExplicitOrError) {
49309467b48Spatrick       return ExplicitOrError.takeError();
49409467b48Spatrick     }
49509467b48Spatrick     xmlNsPtr Explicit = std::move(ExplicitOrError.get());
49609467b48Spatrick     Node->ns = Explicit;
49709467b48Spatrick   }
49809467b48Spatrick   for (xmlNodePtr Child = Node->children; Child; Child = Child->next) {
49909467b48Spatrick     if (auto E = reconcileNamespaces(Child)) {
50009467b48Spatrick       return E;
50109467b48Spatrick     }
50209467b48Spatrick   }
50309467b48Spatrick   return Error::success();
50409467b48Spatrick }
50509467b48Spatrick 
50609467b48Spatrick // Recursively merge the two given manifest trees, depending on which elements
50709467b48Spatrick // are of a mergeable type, and choose namespaces according to which have
50809467b48Spatrick // higher priority.
treeMerge(xmlNodePtr OriginalRoot,xmlNodePtr AdditionalRoot)50909467b48Spatrick static Error treeMerge(xmlNodePtr OriginalRoot, xmlNodePtr AdditionalRoot) {
51009467b48Spatrick   if (auto E = mergeAttributes(OriginalRoot, AdditionalRoot))
51109467b48Spatrick     return E;
51209467b48Spatrick   if (auto E = mergeNamespaces(OriginalRoot, AdditionalRoot))
51309467b48Spatrick     return E;
51409467b48Spatrick   xmlNodePtr AdditionalFirstChild = AdditionalRoot->children;
51509467b48Spatrick   xmlNode StoreNext;
51609467b48Spatrick   for (xmlNodePtr Child = AdditionalFirstChild; Child; Child = Child->next) {
51709467b48Spatrick     xmlNodePtr OriginalChildWithName;
51809467b48Spatrick     if (!isMergeableElement(Child->name) ||
51909467b48Spatrick         !(OriginalChildWithName =
52009467b48Spatrick               getChildWithName(OriginalRoot, Child->name)) ||
52109467b48Spatrick         !hasRecognizedNamespace(Child)) {
52209467b48Spatrick       StoreNext.next = Child->next;
52309467b48Spatrick       xmlUnlinkNode(Child);
52409467b48Spatrick       if (!xmlAddChild(OriginalRoot, Child)) {
52509467b48Spatrick         return make_error<WindowsManifestError>(Twine("could not merge ") +
52609467b48Spatrick                                                 FROM_XML_CHAR(Child->name));
52709467b48Spatrick       }
52809467b48Spatrick       if (auto E = reconcileNamespaces(Child)) {
52909467b48Spatrick         return E;
53009467b48Spatrick       }
53109467b48Spatrick       Child = &StoreNext;
53209467b48Spatrick     } else if (auto E = treeMerge(OriginalChildWithName, Child)) {
53309467b48Spatrick       return E;
53409467b48Spatrick     }
53509467b48Spatrick   }
53609467b48Spatrick   return Error::success();
53709467b48Spatrick }
53809467b48Spatrick 
stripComments(xmlNodePtr Root)53909467b48Spatrick static void stripComments(xmlNodePtr Root) {
54009467b48Spatrick   xmlNode StoreNext;
54109467b48Spatrick   for (xmlNodePtr Child = Root->children; Child; Child = Child->next) {
54209467b48Spatrick     if (!xmlStringsEqual(Child->name, TO_XML_CHAR("comment"))) {
54309467b48Spatrick       stripComments(Child);
54409467b48Spatrick       continue;
54509467b48Spatrick     }
54609467b48Spatrick     StoreNext.next = Child->next;
54709467b48Spatrick     xmlNodePtr Remove = Child;
54809467b48Spatrick     Child = &StoreNext;
54909467b48Spatrick     xmlUnlinkNode(Remove);
55009467b48Spatrick     xmlFreeNode(Remove);
55109467b48Spatrick   }
55209467b48Spatrick }
55309467b48Spatrick 
55409467b48Spatrick // libxml2 assumes that attributes do not inherit default namespaces, whereas
55509467b48Spatrick // the original  mt.exe does make this assumption.  This function reconciles
55609467b48Spatrick // this by setting all attributes to have the inherited default namespace.
setAttributeNamespaces(xmlNodePtr Node)55709467b48Spatrick static void setAttributeNamespaces(xmlNodePtr Node) {
55809467b48Spatrick   for (xmlAttrPtr Attribute = Node->properties; Attribute;
55909467b48Spatrick        Attribute = Attribute->next) {
56009467b48Spatrick     if (!Attribute->ns) {
56109467b48Spatrick       Attribute->ns = getClosestDefault(Node);
56209467b48Spatrick     }
56309467b48Spatrick   }
56409467b48Spatrick   for (xmlNodePtr Child = Node->children; Child; Child = Child->next) {
56509467b48Spatrick     setAttributeNamespaces(Child);
56609467b48Spatrick   }
56709467b48Spatrick }
56809467b48Spatrick 
56909467b48Spatrick // The merging process may create too many prefix defined namespaces.  This
57009467b48Spatrick // function removes all unnecessary ones from the tree.
checkAndStripPrefixes(xmlNodePtr Node,std::vector<xmlNsPtr> & RequiredPrefixes)57109467b48Spatrick static void checkAndStripPrefixes(xmlNodePtr Node,
57209467b48Spatrick                                   std::vector<xmlNsPtr> &RequiredPrefixes) {
57309467b48Spatrick   for (xmlNodePtr Child = Node->children; Child; Child = Child->next) {
57409467b48Spatrick     checkAndStripPrefixes(Child, RequiredPrefixes);
57509467b48Spatrick   }
57609467b48Spatrick   if (Node->ns && Node->ns->prefix != nullptr) {
57709467b48Spatrick     xmlNsPtr ClosestDefault = getClosestDefault(Node);
57809467b48Spatrick     if (ClosestDefault &&
57909467b48Spatrick         xmlStringsEqual(ClosestDefault->href, Node->ns->href)) {
58009467b48Spatrick       Node->ns = ClosestDefault;
58109467b48Spatrick     } else if (!llvm::is_contained(RequiredPrefixes, Node->ns)) {
58209467b48Spatrick       RequiredPrefixes.push_back(Node->ns);
58309467b48Spatrick     }
58409467b48Spatrick   }
58509467b48Spatrick   for (xmlAttrPtr Attribute = Node->properties; Attribute;
58609467b48Spatrick        Attribute = Attribute->next) {
58709467b48Spatrick     if (Attribute->ns && Attribute->ns->prefix != nullptr) {
58809467b48Spatrick       xmlNsPtr ClosestDefault = getClosestDefault(Node);
58909467b48Spatrick       if (ClosestDefault &&
59009467b48Spatrick           xmlStringsEqual(ClosestDefault->href, Attribute->ns->href)) {
59109467b48Spatrick         Attribute->ns = ClosestDefault;
59209467b48Spatrick       } else if (!llvm::is_contained(RequiredPrefixes, Node->ns)) {
59309467b48Spatrick         RequiredPrefixes.push_back(Attribute->ns);
59409467b48Spatrick       }
59509467b48Spatrick     }
59609467b48Spatrick   }
59709467b48Spatrick   xmlNsPtr Prev;
59809467b48Spatrick   xmlNs Temp;
59909467b48Spatrick   for (xmlNsPtr Def = Node->nsDef; Def; Def = Def->next) {
60009467b48Spatrick     if (!Def->prefix || llvm::is_contained(RequiredPrefixes, Def)) {
60109467b48Spatrick       Prev = Def;
60209467b48Spatrick       continue;
60309467b48Spatrick     }
60409467b48Spatrick     if (Def == Node->nsDef) {
60509467b48Spatrick       Node->nsDef = Def->next;
60609467b48Spatrick     } else {
60709467b48Spatrick       Prev->next = Def->next;
60809467b48Spatrick     }
60909467b48Spatrick     Temp.next = Def->next;
61009467b48Spatrick     xmlFreeNs(Def);
61109467b48Spatrick     Def = &Temp;
61209467b48Spatrick   }
61309467b48Spatrick }
61409467b48Spatrick 
~WindowsManifestMergerImpl()61509467b48Spatrick WindowsManifestMerger::WindowsManifestMergerImpl::~WindowsManifestMergerImpl() {
61609467b48Spatrick   for (auto &Doc : MergedDocs)
61709467b48Spatrick     xmlFreeDoc(Doc);
61809467b48Spatrick }
61909467b48Spatrick 
merge(MemoryBufferRef Manifest)62009467b48Spatrick Error WindowsManifestMerger::WindowsManifestMergerImpl::merge(
621*d415bd75Srobert     MemoryBufferRef Manifest) {
62209467b48Spatrick   if (Merged)
62309467b48Spatrick     return make_error<WindowsManifestError>(
62409467b48Spatrick         "merge after getMergedManifest is not supported");
62509467b48Spatrick   if (Manifest.getBufferSize() == 0)
62609467b48Spatrick     return make_error<WindowsManifestError>(
62709467b48Spatrick         "attempted to merge empty manifest");
62809467b48Spatrick   xmlSetGenericErrorFunc((void *)this,
62909467b48Spatrick                          WindowsManifestMergerImpl::errorCallback);
63009467b48Spatrick   xmlDocPtr ManifestXML = xmlReadMemory(
63109467b48Spatrick       Manifest.getBufferStart(), Manifest.getBufferSize(), "manifest.xml",
63209467b48Spatrick       nullptr, XML_PARSE_NOBLANKS | XML_PARSE_NODICT);
63309467b48Spatrick   xmlSetGenericErrorFunc(nullptr, nullptr);
63409467b48Spatrick   if (auto E = getParseError())
63509467b48Spatrick     return E;
63609467b48Spatrick   xmlNodePtr AdditionalRoot = xmlDocGetRootElement(ManifestXML);
63709467b48Spatrick   stripComments(AdditionalRoot);
63809467b48Spatrick   setAttributeNamespaces(AdditionalRoot);
63909467b48Spatrick   if (CombinedDoc == nullptr) {
64009467b48Spatrick     CombinedDoc = ManifestXML;
64109467b48Spatrick   } else {
64209467b48Spatrick     xmlNodePtr CombinedRoot = xmlDocGetRootElement(CombinedDoc);
64309467b48Spatrick     if (!xmlStringsEqual(CombinedRoot->name, AdditionalRoot->name) ||
64409467b48Spatrick         !isMergeableElement(AdditionalRoot->name) ||
64509467b48Spatrick         !hasRecognizedNamespace(AdditionalRoot)) {
64609467b48Spatrick       return make_error<WindowsManifestError>("multiple root nodes");
64709467b48Spatrick     }
64809467b48Spatrick     if (auto E = treeMerge(CombinedRoot, AdditionalRoot)) {
64909467b48Spatrick       return E;
65009467b48Spatrick     }
65109467b48Spatrick   }
65209467b48Spatrick   MergedDocs.push_back(ManifestXML);
65309467b48Spatrick   return Error::success();
65409467b48Spatrick }
65509467b48Spatrick 
65609467b48Spatrick std::unique_ptr<MemoryBuffer>
getMergedManifest()65709467b48Spatrick WindowsManifestMerger::WindowsManifestMergerImpl::getMergedManifest() {
65809467b48Spatrick   if (!Merged) {
65909467b48Spatrick     Merged = true;
66009467b48Spatrick 
66109467b48Spatrick     if (!CombinedDoc)
66209467b48Spatrick       return nullptr;
66309467b48Spatrick 
66409467b48Spatrick     xmlNodePtr CombinedRoot = xmlDocGetRootElement(CombinedDoc);
66509467b48Spatrick     std::vector<xmlNsPtr> RequiredPrefixes;
66609467b48Spatrick     checkAndStripPrefixes(CombinedRoot, RequiredPrefixes);
66709467b48Spatrick     std::unique_ptr<xmlDoc, XmlDeleter> OutputDoc(
66809467b48Spatrick         xmlNewDoc((const unsigned char *)"1.0"));
66909467b48Spatrick     xmlDocSetRootElement(OutputDoc.get(), CombinedRoot);
670*d415bd75Srobert     assert(nullptr == xmlDocGetRootElement(CombinedDoc));
67109467b48Spatrick 
67209467b48Spatrick     xmlKeepBlanksDefault(0);
67309467b48Spatrick     xmlChar *Buff = nullptr;
67409467b48Spatrick     xmlDocDumpFormatMemoryEnc(OutputDoc.get(), &Buff, &BufferSize, "UTF-8", 1);
67509467b48Spatrick     Buffer.reset(Buff);
67609467b48Spatrick   }
67709467b48Spatrick 
67809467b48Spatrick   return BufferSize ? MemoryBuffer::getMemBufferCopy(StringRef(
67909467b48Spatrick                           FROM_XML_CHAR(Buffer.get()), (size_t)BufferSize))
68009467b48Spatrick                     : nullptr;
68109467b48Spatrick }
68209467b48Spatrick 
isAvailable()68309467b48Spatrick bool windows_manifest::isAvailable() { return true; }
68409467b48Spatrick 
68509467b48Spatrick #else
68609467b48Spatrick 
~WindowsManifestMergerImpl()68709467b48Spatrick WindowsManifestMerger::WindowsManifestMergerImpl::~WindowsManifestMergerImpl() {
68809467b48Spatrick }
68909467b48Spatrick 
merge(MemoryBufferRef Manifest)69009467b48Spatrick Error WindowsManifestMerger::WindowsManifestMergerImpl::merge(
691*d415bd75Srobert     MemoryBufferRef Manifest) {
69209467b48Spatrick   return make_error<WindowsManifestError>("no libxml2");
69309467b48Spatrick }
69409467b48Spatrick 
69509467b48Spatrick std::unique_ptr<MemoryBuffer>
getMergedManifest()69609467b48Spatrick WindowsManifestMerger::WindowsManifestMergerImpl::getMergedManifest() {
69709467b48Spatrick   return nullptr;
69809467b48Spatrick }
69909467b48Spatrick 
isAvailable()70009467b48Spatrick bool windows_manifest::isAvailable() { return false; }
70109467b48Spatrick 
70209467b48Spatrick #endif
70309467b48Spatrick 
WindowsManifestMerger()70409467b48Spatrick WindowsManifestMerger::WindowsManifestMerger()
70509467b48Spatrick     : Impl(std::make_unique<WindowsManifestMergerImpl>()) {}
70609467b48Spatrick 
707*d415bd75Srobert WindowsManifestMerger::~WindowsManifestMerger() = default;
70809467b48Spatrick 
merge(MemoryBufferRef Manifest)709*d415bd75Srobert Error WindowsManifestMerger::merge(MemoryBufferRef Manifest) {
71009467b48Spatrick   return Impl->merge(Manifest);
71109467b48Spatrick }
71209467b48Spatrick 
getMergedManifest()71309467b48Spatrick std::unique_ptr<MemoryBuffer> WindowsManifestMerger::getMergedManifest() {
71409467b48Spatrick   return Impl->getMergedManifest();
71509467b48Spatrick }
71609467b48Spatrick 
errorCallback(void * Ctx,const char * Format,...)71709467b48Spatrick void WindowsManifestMerger::WindowsManifestMergerImpl::errorCallback(
71809467b48Spatrick     void *Ctx, const char *Format, ...) {
71909467b48Spatrick   auto *Merger = (WindowsManifestMergerImpl *)Ctx;
72009467b48Spatrick   Merger->ParseErrorOccurred = true;
72109467b48Spatrick }
72209467b48Spatrick 
getParseError()72309467b48Spatrick Error WindowsManifestMerger::WindowsManifestMergerImpl::getParseError() {
72409467b48Spatrick   if (!ParseErrorOccurred)
72509467b48Spatrick     return Error::success();
72609467b48Spatrick   return make_error<WindowsManifestError>("invalid xml document");
72709467b48Spatrick }
728