xref: /freebsd/contrib/llvm-project/llvm/lib/WindowsManifest/WindowsManifestMerger.cpp (revision dd41de95a84d979615a2ef11df6850622bf6184e)
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 
26 using namespace llvm;
27 using namespace windows_manifest;
28 
29 char WindowsManifestError::ID = 0;
30 
31 WindowsManifestError::WindowsManifestError(const Twine &Msg) : Msg(Msg.str()) {}
32 
33 void WindowsManifestError::log(raw_ostream &OS) const { OS << Msg; }
34 
35 class WindowsManifestMerger::WindowsManifestMergerImpl {
36 public:
37   ~WindowsManifestMergerImpl();
38   Error merge(const MemoryBuffer &Manifest);
39   std::unique_ptr<MemoryBuffer> getMergedManifest();
40 
41 private:
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 
61 static 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 
69 static 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 
77 static 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 
88 static 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 
98 static 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.
110 static 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.
126 static 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.
140 static 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.
153 static 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.
164 static 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.
178 static 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.
193 static 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.
207 static 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.
278 static 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.
290 static 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.
296 static 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.
301 static 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.
310 static 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.
332 static 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 
473 static 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 
482 static 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.
488 static 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.
511 static 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 
541 static 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.
559 static 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.
573 static 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 
617 WindowsManifestMerger::WindowsManifestMergerImpl::~WindowsManifestMergerImpl() {
618   for (auto &Doc : MergedDocs)
619     xmlFreeDoc(Doc);
620 }
621 
622 Error 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 
658 std::unique_ptr<MemoryBuffer>
659 WindowsManifestMerger::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 
685 bool windows_manifest::isAvailable() { return true; }
686 
687 #else
688 
689 WindowsManifestMerger::WindowsManifestMergerImpl::~WindowsManifestMergerImpl() {
690 }
691 
692 Error WindowsManifestMerger::WindowsManifestMergerImpl::merge(
693     const MemoryBuffer &Manifest) {
694   return make_error<WindowsManifestError>("no libxml2");
695 }
696 
697 std::unique_ptr<MemoryBuffer>
698 WindowsManifestMerger::WindowsManifestMergerImpl::getMergedManifest() {
699   return nullptr;
700 }
701 
702 bool windows_manifest::isAvailable() { return false; }
703 
704 #endif
705 
706 WindowsManifestMerger::WindowsManifestMerger()
707     : Impl(std::make_unique<WindowsManifestMergerImpl>()) {}
708 
709 WindowsManifestMerger::~WindowsManifestMerger() {}
710 
711 Error WindowsManifestMerger::merge(const MemoryBuffer &Manifest) {
712   return Impl->merge(Manifest);
713 }
714 
715 std::unique_ptr<MemoryBuffer> WindowsManifestMerger::getMergedManifest() {
716   return Impl->getMergedManifest();
717 }
718 
719 void WindowsManifestMerger::WindowsManifestMergerImpl::errorCallback(
720     void *Ctx, const char *Format, ...) {
721   auto *Merger = (WindowsManifestMergerImpl *)Ctx;
722   Merger->ParseErrorOccurred = true;
723 }
724 
725 Error WindowsManifestMerger::WindowsManifestMergerImpl::getParseError() {
726   if (!ParseErrorOccurred)
727     return Error::success();
728   return make_error<WindowsManifestError>("invalid xml document");
729 }
730