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