WindowsManifestMerger.cpp 27 KB

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