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 13 #include "llvm/WindowsManifest/WindowsManifestMerger.h" 14 #include "llvm/Config/config.h" 15 #include "llvm/Support/MemoryBuffer.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 27 char WindowsManifestError::ID = 0; 28 29 WindowsManifestError::WindowsManifestError(const Twine &Msg) : Msg(Msg.str()) {} 30 31 void WindowsManifestError::log(raw_ostream &OS) const { OS << Msg; } 32 33 class WindowsManifestMerger::WindowsManifestMergerImpl { 34 public: 35 ~WindowsManifestMergerImpl(); 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)) { 382 Expected<xmlNsPtr> EC = 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); 400 Expected<xmlNsPtr> EC = 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. 420 Expected<xmlNsPtr> EC = 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. 438 Expected<xmlNsPtr> EC = 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); 452 Expected<xmlNsPtr> EC = 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 615 WindowsManifestMerger::WindowsManifestMergerImpl::~WindowsManifestMergerImpl() { 616 for (auto &Doc : MergedDocs) 617 xmlFreeDoc(Doc); 618 } 619 620 Error WindowsManifestMerger::WindowsManifestMergerImpl::merge( 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> 657 WindowsManifestMerger::WindowsManifestMergerImpl::getMergedManifest() { 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 687 WindowsManifestMerger::WindowsManifestMergerImpl::~WindowsManifestMergerImpl() { 688 } 689 690 Error WindowsManifestMerger::WindowsManifestMergerImpl::merge( 691 MemoryBufferRef Manifest) { 692 return make_error<WindowsManifestError>("no libxml2"); 693 } 694 695 std::unique_ptr<MemoryBuffer> 696 WindowsManifestMerger::WindowsManifestMergerImpl::getMergedManifest() { 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 707 WindowsManifestMerger::~WindowsManifestMerger() = default; 708 709 Error WindowsManifestMerger::merge(MemoryBufferRef Manifest) { 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 } 728