[dsymutil] Escape HTML special characters in plist.

When printing string in the Plist, we weren't escaping the characters
which lead to invalid XML. This patch adds the escape logic to
StringExtras.

rdar://39785334

llvm-svn: 333565
This commit is contained in:
Jonas Devlieghere 2018-05-30 17:47:11 +00:00
parent a1e354b5c2
commit 562ffd5cb3
4 changed files with 40 additions and 10 deletions

View File

@ -255,6 +255,10 @@ inline StringRef getOrdinalSuffix(unsigned Val) {
/// it if it is not printable or if it is an escape char. /// it if it is not printable or if it is an escape char.
void PrintEscapedString(StringRef Name, raw_ostream &Out); void PrintEscapedString(StringRef Name, raw_ostream &Out);
/// Print each character of the specified string, escaping HTML special
/// characters.
void PrintHTMLEscaped(StringRef String, raw_ostream &Out);
/// printLowerCase - Print each character as lowercase if it is uppercase. /// printLowerCase - Print each character as lowercase if it is uppercase.
void printLowerCase(StringRef String, raw_ostream &Out); void printLowerCase(StringRef String, raw_ostream &Out);

View File

@ -68,6 +68,23 @@ void llvm::PrintEscapedString(StringRef Name, raw_ostream &Out) {
} }
} }
void llvm::PrintHTMLEscaped(StringRef String, raw_ostream &Out) {
for (char C : String) {
if (C == '&')
Out << "&amp;";
else if (C == '<')
Out << "&lt;";
else if (C == '>')
Out << "&gt;";
else if (C == '\"')
Out << "&quot;";
else if (C == '\'')
Out << "&apos;";
else
Out << C;
}
}
void llvm::printLowerCase(StringRef String, raw_ostream &Out) { void llvm::printLowerCase(StringRef String, raw_ostream &Out) {
for (const char C : String) for (const char C : String)
Out << toLower(C); Out << toLower(C);

View File

@ -8,7 +8,7 @@ RUN: cat %p/../Inputs/Info.plist > %t/Info.plist
RUN: dsymutil -oso-prepend-path=%p/.. %t/basic.macho.x86_64 -o %t/dsymdest/basic.macho.x86_64.dSYM RUN: dsymutil -oso-prepend-path=%p/.. %t/basic.macho.x86_64 -o %t/dsymdest/basic.macho.x86_64.dSYM
RUN: FileCheck %s --input-file %t/dsymdest/basic.macho.x86_64.dSYM/Contents/Info.plist RUN: FileCheck %s --input-file %t/dsymdest/basic.macho.x86_64.dSYM/Contents/Info.plist
RUN: dsymutil -oso-prepend-path=%p/.. %t/basic.macho.x86_64 -toolchain "toolchain" -o %t/dsymdest/basic.macho.x86_64.dSYM RUN: dsymutil -oso-prepend-path=%p/.. %t/basic.macho.x86_64 -toolchain "toolchain&and'some<symbols" -o %t/dsymdest/basic.macho.x86_64.dSYM
RUN: FileCheck %s --input-file %t/dsymdest/basic.macho.x86_64.dSYM/Contents/Info.plist --check-prefix=CHECK --check-prefix=TOOLCHAIN RUN: FileCheck %s --input-file %t/dsymdest/basic.macho.x86_64.dSYM/Contents/Info.plist --check-prefix=CHECK --check-prefix=TOOLCHAIN
CHECK: <?xml version="1.0" encoding="UTF-8"?> CHECK: <?xml version="1.0" encoding="UTF-8"?>
@ -30,6 +30,6 @@ CHECK-NEXT: <string>2.0</string>
CHECK-NEXT: <key>CFBundleVersion</key> CHECK-NEXT: <key>CFBundleVersion</key>
CHECK-NEXT: <string>2</string> CHECK-NEXT: <string>2</string>
TOOLCHAIN: <key>Toolchain</key> TOOLCHAIN: <key>Toolchain</key>
TOOLCHAIN-NEXT: <string>toolchain</string> TOOLCHAIN-NEXT: <string>toolchain&amp;and&apos;some&lt;symbols</string>
CHECK: </dict> CHECK: </dict>
CHECK-NEXT: </plist> CHECK-NEXT: </plist>

View File

@ -18,6 +18,7 @@
#include "MachOUtils.h" #include "MachOUtils.h"
#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h" #include "llvm/ADT/Triple.h"
#include "llvm/DebugInfo/DIContext.h" #include "llvm/DebugInfo/DIContext.h"
@ -193,16 +194,24 @@ static bool createPlistFile(llvm::StringRef Bin, llvm::StringRef BundleRoot) {
<< "\t\t<key>CFBundleSignature</key>\n" << "\t\t<key>CFBundleSignature</key>\n"
<< "\t\t<string>\?\?\?\?</string>\n"; << "\t\t<string>\?\?\?\?</string>\n";
if (!BI.OmitShortVersion()) if (!BI.OmitShortVersion()) {
PL << "\t\t<key>CFBundleShortVersionString</key>\n" PL << "\t\t<key>CFBundleShortVersionString</key>\n";
<< "\t\t<string>" << BI.ShortVersionStr << "</string>\n"; PL << "\t\t<string>";
PrintHTMLEscaped(BI.ShortVersionStr, PL);
PL << "</string>\n";
}
PL << "\t\t<key>CFBundleVersion</key>\n" PL << "\t\t<key>CFBundleVersion</key>\n";
<< "\t\t<string>" << BI.VersionStr << "</string>\n"; PL << "\t\t<string>";
PrintHTMLEscaped(BI.VersionStr, PL);
PL << "</string>\n";
if (!Toolchain.empty()) if (!Toolchain.empty()) {
PL << "\t\t<key>Toolchain</key>\n" PL << "\t\t<key>Toolchain</key>\n";
<< "\t\t<string>" << Toolchain << "</string>\n"; PL << "\t\t<string>";
PrintHTMLEscaped(Toolchain, PL);
PL << "</string>\n";
}
PL << "\t</dict>\n" PL << "\t</dict>\n"
<< "</plist>\n"; << "</plist>\n";