]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/WindowsManifest/WindowsManifestMerger.cpp
Partial MFV r329753:
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / WindowsManifest / WindowsManifestMerger.cpp
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 }