WindowsManifestMerger.cpp 27 KB

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