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