LLVM  8.0.1
WindowsManifestMerger.cpp
Go to the documentation of this file.
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 
15 #include "llvm/Config/config.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 
31 
32 WindowsManifestError::WindowsManifestError(const Twine &Msg) : Msg(Msg.str()) {}
33 
34 void WindowsManifestError::log(raw_ostream &OS) const { OS << Msg; }
35 
37 public:
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)) {
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);
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.
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.
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);
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 
619  for (auto &Doc : MergedDocs)
620  xmlFreeDoc(Doc);
621 }
622 
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>
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 
691 }
692 
694  const MemoryBuffer &Manifest) {
695  return make_error<WindowsManifestError>("no libxml2");
696 }
697 
698 std::unique_ptr<MemoryBuffer>
700  return nullptr;
701 }
702 
703 bool windows_manifest::isAvailable() { return false; }
704 
705 #endif
706 
709 
711 
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 }
This class represents lattice values for constants.
Definition: AllocatorList.h:24
size_t getBufferSize() const
Definition: MemoryBuffer.h:62
std::enable_if<!std::is_array< T >::value, std::unique_ptr< T > >::type make_unique(Args &&... args)
Constructs a new T() with the given args and returns a unique_ptr<T> which owns the object...
Definition: STLExtras.h:1349
Error takeError()
Take ownership of the stored error.
Definition: Error.h:553
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
Tagged union holding either a T or a Error.
Definition: CachePruning.h:23
void log(raw_ostream &OS) const override
Print an error message to an output stream.
#define TO_XML_CHAR(X)
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
R600 Vector Reg Merger
auto find_if(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range))
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly...
Definition: STLExtras.h:1214
static ErrorSuccess success()
Create a success value.
Definition: Error.h:327
reference get()
Returns a reference to the stored T value.
Definition: Error.h:533
This interface provides simple read-only access to a block of memory, and provides simple methods for...
Definition: MemoryBuffer.h:42
static std::unique_ptr< MemoryBuffer > getMemBufferCopy(StringRef InputData, const Twine &BufferName="")
Open the specified memory range as a MemoryBuffer, copying the contents and taking ownership of it...
std::unique_ptr< MemoryBuffer > getMergedManifest()
#define FROM_XML_CHAR(X)
const char * getBufferStart() const
Definition: MemoryBuffer.h:60
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Lightweight error class with error context and mandatory checking.
Definition: Error.h:158
std::error_code EC
Definition: Error.h:1083
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:46
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
bool is_contained(R &&Range, const E &Element)
Wrapper function around std::find to detect if an element exists in a container.
Definition: STLExtras.h:1245