Home | History | Annotate | Download | only in WindowsManifest
      1 //===-- WindowsManifestMerger.cpp ------------------------------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===---------------------------------------------------------------------===//
      9 //
     10 // This file implements the .manifest merger class.
     11 //
     12 //===---------------------------------------------------------------------===//
     13 
     14 #include "llvm/WindowsManifest/WindowsManifestMerger.h"
     15 #include "llvm/Config/config.h"
     16 #include "llvm/Support/MemoryBuffer.h"
     17 
     18 #include <map>
     19 
     20 #if LLVM_LIBXML2_ENABLED
     21 #include <libxml/xmlreader.h>
     22 #endif
     23 
     24 #define TO_XML_CHAR(X) reinterpret_cast<const unsigned char *>(X)
     25 #define FROM_XML_CHAR(X) reinterpret_cast<const char *>(X)
     26 
     27 using namespace llvm;
     28 using namespace windows_manifest;
     29 
     30 char WindowsManifestError::ID = 0;
     31 
     32 WindowsManifestError::WindowsManifestError(const Twine &Msg) : Msg(Msg.str()) {}
     33 
     34 void WindowsManifestError::log(raw_ostream &OS) const { OS << Msg; }
     35 
     36 class WindowsManifestMerger::WindowsManifestMergerImpl {
     37 public:
     38   ~WindowsManifestMergerImpl();
     39   Error merge(const MemoryBuffer &Manifest);
     40   std::unique_ptr<MemoryBuffer> getMergedManifest();
     41 
     42 private:
     43   static void errorCallback(void *Ctx, const char *Format, ...);
     44   Error getParseError();
     45 #if LLVM_LIBXML2_ENABLED
     46   xmlDocPtr CombinedDoc = nullptr;
     47   std::vector<xmlDocPtr> MergedDocs;
     48 
     49   bool Merged = false;
     50   struct XmlDeleter {
     51     void operator()(xmlChar *Ptr) { xmlFree(Ptr); }
     52     void operator()(xmlDoc *Ptr) { xmlFreeDoc(Ptr); }
     53   };
     54   int BufferSize = 0;
     55   std::unique_ptr<xmlChar, XmlDeleter> Buffer;
     56 #endif
     57   bool ParseErrorOccurred = false;
     58 };
     59 
     60 #if LLVM_LIBXML2_ENABLED
     61 
     62 static const std::pair<StringRef, StringRef> MtNsHrefsPrefixes[] = {
     63     {"urn:schemas-microsoft-com:asm.v1", "ms_asmv1"},
     64     {"urn:schemas-microsoft-com:asm.v2", "ms_asmv2"},
     65     {"urn:schemas-microsoft-com:asm.v3", "ms_asmv3"},
     66     {"http://schemas.microsoft.com/SMI/2005/WindowsSettings",
     67      "ms_windowsSettings"},
     68     {"urn:schemas-microsoft-com:compatibility.v1", "ms_compatibilityv1"}};
     69 
     70 static bool xmlStringsEqual(const unsigned char *A, const unsigned char *B) {
     71   // Handle null pointers.  Comparison of 2 null pointers returns true because
     72   // this indicates the prefix of a default namespace.
     73   if (!A || !B)
     74     return A == B;
     75   return strcmp(FROM_XML_CHAR(A), FROM_XML_CHAR(B)) == 0;
     76 }
     77 
     78 static bool isMergeableElement(const unsigned char *ElementName) {
     79   for (StringRef S : {"application", "assembly", "assemblyIdentity",
     80                       "compatibility", "noInherit", "requestedExecutionLevel",
     81                       "requestedPrivileges", "security", "trustInfo"}) {
     82     if (S == FROM_XML_CHAR(ElementName)) {
     83       return true;
     84     }
     85   }
     86   return false;
     87 }
     88 
     89 static xmlNodePtr getChildWithName(xmlNodePtr Parent,
     90                                    const unsigned char *ElementName) {
     91   for (xmlNodePtr Child = Parent->children; Child; Child = Child->next) {
     92     if (xmlStringsEqual(Child->name, ElementName)) {
     93       return Child;
     94     }
     95   }
     96   return nullptr;
     97 }
     98 
     99 static xmlAttrPtr getAttribute(xmlNodePtr Node,
    100                                const unsigned char *AttributeName) {
    101   for (xmlAttrPtr Attribute = Node->properties; Attribute != nullptr;
    102        Attribute = Attribute->next) {
    103     if (xmlStringsEqual(Attribute->name, AttributeName)) {
    104       return Attribute;
    105     }
    106   }
    107   return nullptr;
    108 }
    109 
    110 // Check if namespace specified by HRef1 overrides that of HRef2.
    111 static bool namespaceOverrides(const unsigned char *HRef1,
    112                                const unsigned char *HRef2) {
    113   auto HRef1Position = llvm::find_if(
    114       MtNsHrefsPrefixes, [=](const std::pair<StringRef, StringRef> &Element) {
    115         return xmlStringsEqual(HRef1, TO_XML_CHAR(Element.first.data()));
    116       });
    117   auto HRef2Position = llvm::find_if(
    118       MtNsHrefsPrefixes, [=](const std::pair<StringRef, StringRef> &Element) {
    119         return xmlStringsEqual(HRef2, TO_XML_CHAR(Element.first.data()));
    120       });
    121   return HRef1Position < HRef2Position;
    122 }
    123 
    124 // Search for prefix-defined namespace specified by HRef, starting on Node and
    125 // continuing recursively upwards.  Returns the namespace or nullptr if not
    126 // found.
    127 static xmlNsPtr search(const unsigned char *HRef, xmlNodePtr Node) {
    128   for (xmlNsPtr Def = Node->nsDef; Def; Def = Def->next) {
    129     if (Def->prefix && xmlStringsEqual(Def->href, HRef)) {
    130       return Def;
    131     }
    132   }
    133   if (Node->parent) {
    134     return search(HRef, Node->parent);
    135   }
    136   return nullptr;
    137 }
    138 
    139 // Return the prefix that corresponds to the HRef.  If HRef is not a recognized
    140 // URI, then just return the HRef itself to use as the prefix.
    141 static const unsigned char *getPrefixForHref(const unsigned char *HRef) {
    142   for (auto &Ns : MtNsHrefsPrefixes) {
    143     if (xmlStringsEqual(HRef, TO_XML_CHAR(Ns.first.data()))) {
    144       return TO_XML_CHAR(Ns.second.data());
    145     }
    146   }
    147   return HRef;
    148 }
    149 
    150 // Search for prefix-defined namespace specified by HRef, starting on Node and
    151 // continuing recursively upwards.  If it is found, then return it.  If it is
    152 // not found, then prefix-define that namespace on the node and return a
    153 // reference to it.
    154 static Expected<xmlNsPtr> searchOrDefine(const unsigned char *HRef,
    155                                          xmlNodePtr Node) {
    156   if (xmlNsPtr Def = search(HRef, Node))
    157     return Def;
    158   if (xmlNsPtr Def = xmlNewNs(Node, HRef, getPrefixForHref(HRef)))
    159     return Def;
    160   return make_error<WindowsManifestError>("failed to create new namespace");
    161 }
    162 
    163 // Set the namespace of OrigionalAttribute on OriginalNode to be that of
    164 // AdditionalAttribute's.
    165 static Error copyAttributeNamespace(xmlAttrPtr OriginalAttribute,
    166                                     xmlNodePtr OriginalNode,
    167                                     xmlAttrPtr AdditionalAttribute) {
    168 
    169   Expected<xmlNsPtr> ExplicitOrError =
    170       searchOrDefine(AdditionalAttribute->ns->href, OriginalNode);
    171   if (!ExplicitOrError)
    172     return ExplicitOrError.takeError();
    173   OriginalAttribute->ns = std::move(ExplicitOrError.get());
    174   return Error::success();
    175 }
    176 
    177 // Return the corresponding namespace definition for the prefix, defined on the
    178 // given Node.  Returns nullptr if there is no such definition.
    179 static xmlNsPtr getNamespaceWithPrefix(const unsigned char *Prefix,
    180                                        xmlNodePtr Node) {
    181   if (Node == nullptr)
    182     return nullptr;
    183   for (xmlNsPtr Def = Node->nsDef; Def; Def = Def->next) {
    184     if (xmlStringsEqual(Def->prefix, Prefix)) {
    185       return Def;
    186     }
    187   }
    188   return nullptr;
    189 }
    190 
    191 // Search for the closest inheritable default namespace, starting on (and
    192 // including) the Node and traveling upwards through parent nodes.  Returns
    193 // nullptr if there are no inheritable default namespaces.
    194 static xmlNsPtr getClosestDefault(xmlNodePtr Node) {
    195   if (xmlNsPtr Ret = getNamespaceWithPrefix(nullptr, Node))
    196     return Ret;
    197   if (Node->parent == nullptr)
    198     return nullptr;
    199   return getClosestDefault(Node->parent);
    200 }
    201 
    202 // Merge the attributes of AdditionalNode into OriginalNode.  If attributes
    203 // with identical types are present, they are not duplicated but rather if
    204 // their values are not consistent and error is thrown.  In addition, the
    205 // higher priority namespace is used for each attribute, EXCEPT in the case
    206 // of merging two default namespaces and the lower priority namespace
    207 // definition occurs closer than the higher priority one.
    208 static Error mergeAttributes(xmlNodePtr OriginalNode,
    209                              xmlNodePtr AdditionalNode) {
    210   xmlNsPtr ClosestDefault = getClosestDefault(OriginalNode);
    211   for (xmlAttrPtr Attribute = AdditionalNode->properties; Attribute;
    212        Attribute = Attribute->next) {
    213     if (xmlAttrPtr OriginalAttribute =
    214             getAttribute(OriginalNode, Attribute->name)) {
    215       if (!xmlStringsEqual(OriginalAttribute->children->content,
    216                            Attribute->children->content)) {
    217         return make_error<WindowsManifestError>(
    218             Twine("conflicting attributes for ") +
    219             FROM_XML_CHAR(OriginalNode->name));
    220       }
    221       if (!Attribute->ns) {
    222         continue;
    223       }
    224       if (!OriginalAttribute->ns) {
    225         if (auto E = copyAttributeNamespace(OriginalAttribute, OriginalNode,
    226                                             Attribute)) {
    227           return E;
    228         }
    229         continue;
    230       }
    231       if (namespaceOverrides(OriginalAttribute->ns->href,
    232                              Attribute->ns->href)) {
    233         // In this case, the original attribute has a higher priority namespace
    234         // than the incomiing attribute, however the namespace definition of
    235         // the lower priority namespace occurs first traveling upwards in the
    236         // tree.  Therefore the lower priority namespace is applied.
    237         if (!OriginalAttribute->ns->prefix && !Attribute->ns->prefix &&
    238             ClosestDefault &&
    239             xmlStringsEqual(Attribute->ns->href, ClosestDefault->href)) {
    240           if (auto E = copyAttributeNamespace(OriginalAttribute, OriginalNode,
    241                                               Attribute)) {
    242             return E;
    243           }
    244           continue;
    245         }
    246         continue;
    247         // This covers the case where the incoming attribute has the higher
    248         // priority.  The higher priority namespace is applied in all cases
    249         // EXCEPT when both of the namespaces are default inherited, and the
    250         // closest inherited default is the lower priority one.
    251       }
    252       if (Attribute->ns->prefix || OriginalAttribute->ns->prefix ||
    253           (ClosestDefault && !xmlStringsEqual(OriginalAttribute->ns->href,
    254                                               ClosestDefault->href))) {
    255         if (auto E = copyAttributeNamespace(OriginalAttribute, OriginalNode,
    256                                             Attribute)) {
    257           return E;
    258         }
    259         continue;
    260       }
    261       continue;
    262     }
    263     // If the incoming attribute is not already found on the node, append it
    264     // to the end of the properties list.  Also explicitly apply its
    265     // namespace as a prefix because it might be contained in a separate
    266     // namespace that doesn't use the attribute.
    267     xmlAttrPtr NewProp =
    268         xmlNewProp(OriginalNode, Attribute->name, Attribute->children->content);
    269     Expected<xmlNsPtr> ExplicitOrError =
    270         searchOrDefine(Attribute->ns->href, OriginalNode);
    271     if (!ExplicitOrError)
    272       return ExplicitOrError.takeError();
    273     NewProp->ns = std::move(ExplicitOrError.get());
    274   }
    275   return Error::success();
    276 }
    277 
    278 // Given two nodes, return the one with the higher priority namespace.
    279 static xmlNodePtr getDominantNode(xmlNodePtr Node1, xmlNodePtr Node2) {
    280 
    281   if (!Node1 || !Node1->ns)
    282     return Node2;
    283   if (!Node2 || !Node2->ns)
    284     return Node1;
    285   if (namespaceOverrides(Node1->ns->href, Node2->ns->href))
    286     return Node1;
    287   return Node2;
    288 }
    289 
    290 // Checks if this Node's namespace is inherited or one it defined itself.
    291 static bool hasInheritedNs(xmlNodePtr Node) {
    292   return Node->ns && Node->ns != getNamespaceWithPrefix(Node->ns->prefix, Node);
    293 }
    294 
    295 // Check if this Node's namespace is a default namespace that it inherited, as
    296 // opposed to defining itself.
    297 static bool hasInheritedDefaultNs(xmlNodePtr Node) {
    298   return hasInheritedNs(Node) && Node->ns->prefix == nullptr;
    299 }
    300 
    301 // Check if this Node's namespace is a default namespace it defined itself.
    302 static bool hasDefinedDefaultNamespace(xmlNodePtr Node) {
    303   return Node->ns && (Node->ns == getNamespaceWithPrefix(nullptr, Node));
    304 }
    305 
    306 // For the given explicit prefix-definition of a namespace, travel downwards
    307 // from a node recursively, and for every implicit, inherited default usage of
    308 // that namespace replace it with that explicit prefix use.  This is important
    309 // when namespace overriding occurs when merging, so that elements unique to a
    310 // namespace will still stay in that namespace.
    311 static void explicateNamespace(xmlNsPtr PrefixDef, xmlNodePtr Node) {
    312   // If a node as its own default namespace definition it clearly cannot have
    313   // inherited the given default namespace, and neither will any of its
    314   // children.
    315   if (hasDefinedDefaultNamespace(Node))
    316     return;
    317   if (Node->ns && xmlStringsEqual(Node->ns->href, PrefixDef->href) &&
    318       hasInheritedDefaultNs(Node))
    319     Node->ns = PrefixDef;
    320   for (xmlAttrPtr Attribute = Node->properties; Attribute;
    321        Attribute = Attribute->next) {
    322     if (Attribute->ns &&
    323         xmlStringsEqual(Attribute->ns->href, PrefixDef->href)) {
    324       Attribute->ns = PrefixDef;
    325     }
    326   }
    327   for (xmlNodePtr Child = Node->children; Child; Child = Child->next) {
    328     explicateNamespace(PrefixDef, Child);
    329   }
    330 }
    331 
    332 // Perform the namespace merge between two nodes.
    333 static Error mergeNamespaces(xmlNodePtr OriginalNode,
    334                              xmlNodePtr AdditionalNode) {
    335   // Save the original default namespace definition in case the incoming node
    336   // overrides it.
    337   const unsigned char *OriginalDefinedDefaultHref = nullptr;
    338   if (xmlNsPtr OriginalDefinedDefaultNs =
    339           getNamespaceWithPrefix(nullptr, OriginalNode)) {
    340     OriginalDefinedDefaultHref = xmlStrdup(OriginalDefinedDefaultNs->href);
    341   }
    342   const unsigned char *NewDefinedDefaultHref = nullptr;
    343   // Copy all namespace definitions.  There can only be one default namespace
    344   // definition per node, so the higher priority one takes precedence in the
    345   // case of collision.
    346   for (xmlNsPtr Def = AdditionalNode->nsDef; Def; Def = Def->next) {
    347     if (xmlNsPtr OriginalNsDef =
    348             getNamespaceWithPrefix(Def->prefix, OriginalNode)) {
    349       if (!Def->prefix) {
    350         if (namespaceOverrides(Def->href, OriginalNsDef->href)) {
    351           NewDefinedDefaultHref = TO_XML_CHAR(strdup(FROM_XML_CHAR(Def->href)));
    352         }
    353       } else if (!xmlStringsEqual(OriginalNsDef->href, Def->href)) {
    354         return make_error<WindowsManifestError>(
    355             Twine("conflicting namespace definitions for ") +
    356             FROM_XML_CHAR(Def->prefix));
    357       }
    358     } else {
    359       xmlNsPtr NewDef = xmlCopyNamespace(Def);
    360       NewDef->next = OriginalNode->nsDef;
    361       OriginalNode->nsDef = NewDef;
    362     }
    363   }
    364 
    365   // Check whether the original node or the incoming node has the higher
    366   // priority namespace.  Depending on which one is dominant, we will have
    367   // to recursively apply namespace changes down to children of the original
    368   // node.
    369   xmlNodePtr DominantNode = getDominantNode(OriginalNode, AdditionalNode);
    370   xmlNodePtr NonDominantNode =
    371       DominantNode == OriginalNode ? AdditionalNode : OriginalNode;
    372   if (DominantNode == OriginalNode) {
    373     if (OriginalDefinedDefaultHref) {
    374       xmlNsPtr NonDominantDefinedDefault =
    375           getNamespaceWithPrefix(nullptr, NonDominantNode);
    376       // In this case, both the nodes defined a default namespace.  However
    377       // the lower priority node ended up having a higher priority default
    378       // definition.  This can occur if the higher priority node is prefix
    379       // namespace defined.  In this case we have to define an explicit
    380       // prefix for the overridden definition and apply it to all children
    381       // who relied on that definition.
    382       if (NonDominantDefinedDefault &&
    383           namespaceOverrides(NonDominantDefinedDefault->href,
    384                              OriginalDefinedDefaultHref)) {
    385         Expected<xmlNsPtr> EC =
    386             searchOrDefine(OriginalDefinedDefaultHref, DominantNode);
    387         if (!EC) {
    388           return EC.takeError();
    389         }
    390         xmlNsPtr PrefixDominantDefinedDefault = std::move(EC.get());
    391         explicateNamespace(PrefixDominantDefinedDefault, DominantNode);
    392       }
    393       // In this case the node with a higher priority namespace did not have a
    394       // default namespace definition, but the lower priority node did.  In this
    395       // case the new default namespace definition is copied.  A side effect of
    396       // this is that all children will suddenly find themselves in a different
    397       // default namespace.  To maintain correctness we need to ensure that all
    398       // children now explicitly refer to the namespace that they had previously
    399       // implicitly inherited.
    400     } else if (getNamespaceWithPrefix(nullptr, NonDominantNode)) {
    401       if (DominantNode->parent) {
    402         xmlNsPtr ClosestDefault = getClosestDefault(DominantNode->parent);
    403         Expected<xmlNsPtr> EC =
    404             searchOrDefine(ClosestDefault->href, DominantNode);
    405         if (!EC) {
    406           return EC.takeError();
    407         }
    408         xmlNsPtr ExplicitDefault = std::move(EC.get());
    409         explicateNamespace(ExplicitDefault, DominantNode);
    410       }
    411     }
    412   } else {
    413     // Covers case where the incoming node has a default namespace definition
    414     // that overrides the original node's namespace.  This always leads to
    415     // the original node receiving that new default namespace.
    416     if (hasDefinedDefaultNamespace(DominantNode)) {
    417       NonDominantNode->ns = getNamespaceWithPrefix(nullptr, NonDominantNode);
    418     } else {
    419       // This covers the case where the incoming node either has a prefix
    420       // namespace, or an inherited default namespace.  Since the namespace
    421       // may not yet be defined in the original tree we do a searchOrDefine
    422       // for it, and then set the namespace equal to it.
    423       Expected<xmlNsPtr> EC =
    424           searchOrDefine(DominantNode->ns->href, NonDominantNode);
    425       if (!EC) {
    426         return EC.takeError();
    427       }
    428       xmlNsPtr Explicit = std::move(EC.get());
    429       NonDominantNode->ns = Explicit;
    430     }
    431     // This covers cases where the incoming dominant node HAS a default
    432     // namespace definition, but MIGHT NOT NECESSARILY be in that namespace.
    433     if (xmlNsPtr DominantDefaultDefined =
    434             getNamespaceWithPrefix(nullptr, DominantNode)) {
    435       if (OriginalDefinedDefaultHref) {
    436         if (namespaceOverrides(DominantDefaultDefined->href,
    437                                OriginalDefinedDefaultHref)) {
    438           // In this case, the incoming node's default definition overrides
    439           // the original default definition, all children who relied on that
    440           // definition must be updated accordingly.
    441           Expected<xmlNsPtr> EC =
    442               searchOrDefine(OriginalDefinedDefaultHref, NonDominantNode);
    443           if (!EC) {
    444             return EC.takeError();
    445           }
    446           xmlNsPtr ExplicitDefault = std::move(EC.get());
    447           explicateNamespace(ExplicitDefault, NonDominantNode);
    448         }
    449       } else {
    450         // The original did not define a default definition, however the new
    451         // default definition still applies to all children, so they must be
    452         // updated to explicitly refer to the namespace they had previously
    453         // been inheriting implicitly.
    454         xmlNsPtr ClosestDefault = getClosestDefault(NonDominantNode);
    455         Expected<xmlNsPtr> EC =
    456             searchOrDefine(ClosestDefault->href, NonDominantNode);
    457         if (!EC) {
    458           return EC.takeError();
    459         }
    460         xmlNsPtr ExplicitDefault = std::move(EC.get());
    461         explicateNamespace(ExplicitDefault, NonDominantNode);
    462       }
    463     }
    464   }
    465   if (NewDefinedDefaultHref) {
    466     xmlNsPtr OriginalNsDef = getNamespaceWithPrefix(nullptr, OriginalNode);
    467     xmlFree(const_cast<unsigned char *>(OriginalNsDef->href));
    468     OriginalNsDef->href = NewDefinedDefaultHref;
    469   }
    470   xmlFree(const_cast<unsigned char *>(OriginalDefinedDefaultHref));
    471   return Error::success();
    472 }
    473 
    474 static bool isRecognizedNamespace(const unsigned char *NsHref) {
    475   for (auto &Ns : MtNsHrefsPrefixes) {
    476     if (xmlStringsEqual(NsHref, TO_XML_CHAR(Ns.first.data()))) {
    477       return true;
    478     }
    479   }
    480   return false;
    481 }
    482 
    483 static bool hasRecognizedNamespace(xmlNodePtr Node) {
    484   return isRecognizedNamespace(Node->ns->href);
    485 }
    486 
    487 // Ensure a node's inherited namespace is actually defined in the tree it
    488 // resides in.
    489 static Error reconcileNamespaces(xmlNodePtr Node) {
    490   if (!Node) {
    491     return Error::success();
    492   }
    493   if (hasInheritedNs(Node)) {
    494     Expected<xmlNsPtr> ExplicitOrError = searchOrDefine(Node->ns->href, Node);
    495     if (!ExplicitOrError) {
    496       return ExplicitOrError.takeError();
    497     }
    498     xmlNsPtr Explicit = std::move(ExplicitOrError.get());
    499     Node->ns = Explicit;
    500   }
    501   for (xmlNodePtr Child = Node->children; Child; Child = Child->next) {
    502     if (auto E = reconcileNamespaces(Child)) {
    503       return E;
    504     }
    505   }
    506   return Error::success();
    507 }
    508 
    509 // Recursively merge the two given manifest trees, depending on which elements
    510 // are of a mergeable type, and choose namespaces according to which have
    511 // higher priority.
    512 static Error treeMerge(xmlNodePtr OriginalRoot, xmlNodePtr AdditionalRoot) {
    513   if (auto E = mergeAttributes(OriginalRoot, AdditionalRoot))
    514     return E;
    515   if (auto E = mergeNamespaces(OriginalRoot, AdditionalRoot))
    516     return E;
    517   xmlNodePtr AdditionalFirstChild = AdditionalRoot->children;
    518   xmlNode StoreNext;
    519   for (xmlNodePtr Child = AdditionalFirstChild; Child; Child = Child->next) {
    520     xmlNodePtr OriginalChildWithName;
    521     if (!isMergeableElement(Child->name) ||
    522         !(OriginalChildWithName =
    523               getChildWithName(OriginalRoot, Child->name)) ||
    524         !hasRecognizedNamespace(Child)) {
    525       StoreNext.next = Child->next;
    526       xmlUnlinkNode(Child);
    527       if (!xmlAddChild(OriginalRoot, Child)) {
    528         return make_error<WindowsManifestError>(Twine("could not merge ") +
    529                                                 FROM_XML_CHAR(Child->name));
    530       }
    531       if (auto E = reconcileNamespaces(Child)) {
    532         return E;
    533       }
    534       Child = &StoreNext;
    535     } else if (auto E = treeMerge(OriginalChildWithName, Child)) {
    536       return E;
    537     }
    538   }
    539   return Error::success();
    540 }
    541 
    542 static void stripComments(xmlNodePtr Root) {
    543   xmlNode StoreNext;
    544   for (xmlNodePtr Child = Root->children; Child; Child = Child->next) {
    545     if (!xmlStringsEqual(Child->name, TO_XML_CHAR("comment"))) {
    546       stripComments(Child);
    547       continue;
    548     }
    549     StoreNext.next = Child->next;
    550     xmlNodePtr Remove = Child;
    551     Child = &StoreNext;
    552     xmlUnlinkNode(Remove);
    553     xmlFreeNode(Remove);
    554   }
    555 }
    556 
    557 // libxml2 assumes that attributes do not inherit default namespaces, whereas
    558 // the original  mt.exe does make this assumption.  This function reconciles
    559 // this by setting all attributes to have the inherited default namespace.
    560 static void setAttributeNamespaces(xmlNodePtr Node) {
    561   for (xmlAttrPtr Attribute = Node->properties; Attribute;
    562        Attribute = Attribute->next) {
    563     if (!Attribute->ns) {
    564       Attribute->ns = getClosestDefault(Node);
    565     }
    566   }
    567   for (xmlNodePtr Child = Node->children; Child; Child = Child->next) {
    568     setAttributeNamespaces(Child);
    569   }
    570 }
    571 
    572 // The merging process may create too many prefix defined namespaces.  This
    573 // function removes all unnecessary ones from the tree.
    574 static void checkAndStripPrefixes(xmlNodePtr Node,
    575                                   std::vector<xmlNsPtr> &RequiredPrefixes) {
    576   for (xmlNodePtr Child = Node->children; Child; Child = Child->next) {
    577     checkAndStripPrefixes(Child, RequiredPrefixes);
    578   }
    579   if (Node->ns && Node->ns->prefix != nullptr) {
    580     xmlNsPtr ClosestDefault = getClosestDefault(Node);
    581     if (ClosestDefault &&
    582         xmlStringsEqual(ClosestDefault->href, Node->ns->href)) {
    583       Node->ns = ClosestDefault;
    584     } else if (!llvm::is_contained(RequiredPrefixes, Node->ns)) {
    585       RequiredPrefixes.push_back(Node->ns);
    586     }
    587   }
    588   for (xmlAttrPtr Attribute = Node->properties; Attribute;
    589        Attribute = Attribute->next) {
    590     if (Attribute->ns && Attribute->ns->prefix != nullptr) {
    591       xmlNsPtr ClosestDefault = getClosestDefault(Node);
    592       if (ClosestDefault &&
    593           xmlStringsEqual(ClosestDefault->href, Attribute->ns->href)) {
    594         Attribute->ns = ClosestDefault;
    595       } else if (!llvm::is_contained(RequiredPrefixes, Node->ns)) {
    596         RequiredPrefixes.push_back(Attribute->ns);
    597       }
    598     }
    599   }
    600   xmlNsPtr Prev;
    601   xmlNs Temp;
    602   for (xmlNsPtr Def = Node->nsDef; Def; Def = Def->next) {
    603     if (!Def->prefix || llvm::is_contained(RequiredPrefixes, Def)) {
    604       Prev = Def;
    605       continue;
    606     }
    607     if (Def == Node->nsDef) {
    608       Node->nsDef = Def->next;
    609     } else {
    610       Prev->next = Def->next;
    611     }
    612     Temp.next = Def->next;
    613     xmlFreeNs(Def);
    614     Def = &Temp;
    615   }
    616 }
    617 
    618 WindowsManifestMerger::WindowsManifestMergerImpl::~WindowsManifestMergerImpl() {
    619   for (auto &Doc : MergedDocs)
    620     xmlFreeDoc(Doc);
    621 }
    622 
    623 Error WindowsManifestMerger::WindowsManifestMergerImpl::merge(
    624     const MemoryBuffer &Manifest) {
    625   if (Merged)
    626     return make_error<WindowsManifestError>(
    627         "merge after getMergedManifest is not supported");
    628   if (Manifest.getBufferSize() == 0)
    629     return make_error<WindowsManifestError>(
    630         "attempted to merge empty manifest");
    631   xmlSetGenericErrorFunc((void *)this,
    632                          WindowsManifestMergerImpl::errorCallback);
    633   xmlDocPtr ManifestXML = xmlReadMemory(
    634       Manifest.getBufferStart(), Manifest.getBufferSize(), "manifest.xml",
    635       nullptr, XML_PARSE_NOBLANKS | XML_PARSE_NODICT);
    636   xmlSetGenericErrorFunc(nullptr, nullptr);
    637   if (auto E = getParseError())
    638     return E;
    639   xmlNodePtr AdditionalRoot = xmlDocGetRootElement(ManifestXML);
    640   stripComments(AdditionalRoot);
    641   setAttributeNamespaces(AdditionalRoot);
    642   if (CombinedDoc == nullptr) {
    643     CombinedDoc = ManifestXML;
    644   } else {
    645     xmlNodePtr CombinedRoot = xmlDocGetRootElement(CombinedDoc);
    646     if (!xmlStringsEqual(CombinedRoot->name, AdditionalRoot->name) ||
    647         !isMergeableElement(AdditionalRoot->name) ||
    648         !hasRecognizedNamespace(AdditionalRoot)) {
    649       return make_error<WindowsManifestError>("multiple root nodes");
    650     }
    651     if (auto E = treeMerge(CombinedRoot, AdditionalRoot)) {
    652       return E;
    653     }
    654   }
    655   MergedDocs.push_back(ManifestXML);
    656   return Error::success();
    657 }
    658 
    659 std::unique_ptr<MemoryBuffer>
    660 WindowsManifestMerger::WindowsManifestMergerImpl::getMergedManifest() {
    661   if (!Merged) {
    662     Merged = true;
    663 
    664     if (!CombinedDoc)
    665       return nullptr;
    666 
    667     xmlNodePtr CombinedRoot = xmlDocGetRootElement(CombinedDoc);
    668     std::vector<xmlNsPtr> RequiredPrefixes;
    669     checkAndStripPrefixes(CombinedRoot, RequiredPrefixes);
    670     std::unique_ptr<xmlDoc, XmlDeleter> OutputDoc(
    671         xmlNewDoc((const unsigned char *)"1.0"));
    672     xmlDocSetRootElement(OutputDoc.get(), CombinedRoot);
    673     assert(0 == xmlDocGetRootElement(CombinedDoc));
    674 
    675     xmlKeepBlanksDefault(0);
    676     xmlChar *Buff = nullptr;
    677     xmlDocDumpFormatMemoryEnc(OutputDoc.get(), &Buff, &BufferSize, "UTF-8", 1);
    678     Buffer.reset(Buff);
    679   }
    680 
    681   return BufferSize ? MemoryBuffer::getMemBufferCopy(StringRef(
    682                           FROM_XML_CHAR(Buffer.get()), (size_t)BufferSize))
    683                     : nullptr;
    684 }
    685 
    686 bool windows_manifest::isAvailable() { return true; }
    687 
    688 #else
    689 
    690 WindowsManifestMerger::WindowsManifestMergerImpl::~WindowsManifestMergerImpl() {
    691 }
    692 
    693 Error WindowsManifestMerger::WindowsManifestMergerImpl::merge(
    694     const MemoryBuffer &Manifest) {
    695   return make_error<WindowsManifestError>("no libxml2");
    696 }
    697 
    698 std::unique_ptr<MemoryBuffer>
    699 WindowsManifestMerger::WindowsManifestMergerImpl::getMergedManifest() {
    700   return nullptr;
    701 }
    702 
    703 bool windows_manifest::isAvailable() { return false; }
    704 
    705 #endif
    706 
    707 WindowsManifestMerger::WindowsManifestMerger()
    708     : Impl(make_unique<WindowsManifestMergerImpl>()) {}
    709 
    710 WindowsManifestMerger::~WindowsManifestMerger() {}
    711 
    712 Error WindowsManifestMerger::merge(const MemoryBuffer &Manifest) {
    713   return Impl->merge(Manifest);
    714 }
    715 
    716 std::unique_ptr<MemoryBuffer> WindowsManifestMerger::getMergedManifest() {
    717   return Impl->getMergedManifest();
    718 }
    719 
    720 void WindowsManifestMerger::WindowsManifestMergerImpl::errorCallback(
    721     void *Ctx, const char *Format, ...) {
    722   auto *Merger = (WindowsManifestMergerImpl *)Ctx;
    723   Merger->ParseErrorOccurred = true;
    724 }
    725 
    726 Error WindowsManifestMerger::WindowsManifestMergerImpl::getParseError() {
    727   if (!ParseErrorOccurred)
    728     return Error::success();
    729   return make_error<WindowsManifestError>("invalid xml document");
    730 }
    731