From ba39d7e9d04b6a8d3d9bccdf07b69cd2d959a083 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sun, 27 Dec 2015 16:33:46 +0100 Subject: [PATCH] Xcode: Escape all backslashes in strings (#15328) Before this change backslashes in strings were escaped during compile flags adds via AppendFlag(). But global flags like OTHER_CPLUSPLUSFLAGS are not added as flags but as plain strings so they were not escaped properly. Now the escaping is performed within cmXCodeObject::PrintString() which ensures that strings are always encoded. --- Source/cmGlobalXCodeGenerator.cxx | 31 ++++++------------- Source/cmGlobalXCodeGenerator.h | 1 - Source/cmXCodeObject.cxx | 4 +-- .../RunCMake/XcodeProject/RunCMakeTest.cmake | 1 + .../XcodeObjectNeedsEscape-check.cmake | 7 +++++ .../XcodeProject/XcodeObjectNeedsEscape.cmake | 3 ++ 6 files changed, 22 insertions(+), 25 deletions(-) create mode 100644 Tests/RunCMake/XcodeProject/XcodeObjectNeedsEscape-check.cmake create mode 100644 Tests/RunCMake/XcodeProject/XcodeObjectNeedsEscape.cmake diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 475efa8b6..344964825 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -1686,14 +1686,13 @@ cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase, } std::string cdir = this->CurrentLocalGenerator->GetCurrentBinaryDirectory(); - cdir = this->ConvertToRelativeForXCode(cdir.c_str()); + cdir = this->ConvertToRelativeForMake(cdir.c_str()); std::string makecmd = "make -C "; makecmd += cdir; makecmd += " -f "; makecmd += this->ConvertToRelativeForMake( (makefile+"$CONFIGURATION").c_str()); makecmd += " all"; - cmSystemTools::ReplaceString(makecmd, "\\ ", "\\\\ "); buildphase->AddAttribute("shellScript", this->CreateString(makecmd.c_str())); buildphase->AddAttribute("showEnvVarsInLog", @@ -2108,10 +2107,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, this->CurrentLocalGenerator ->GenerateAppleInfoPList(gtgt, "$(EXECUTABLE_NAME)", plist.c_str()); - std::string path = - this->ConvertToRelativeForXCode(plist.c_str()); buildSettings->AddAttribute("INFOPLIST_FILE", - this->CreateString(path.c_str())); + this->CreateString(plist)); } else if(this->XcodeVersion >= 22) { @@ -2157,10 +2154,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, this->CurrentLocalGenerator ->GenerateFrameworkInfoPList(gtgt, "$(EXECUTABLE_NAME)", plist.c_str()); - std::string path = - this->ConvertToRelativeForXCode(plist.c_str()); buildSettings->AddAttribute("INFOPLIST_FILE", - this->CreateString(path.c_str())); + this->CreateString(plist)); } else { @@ -2200,10 +2195,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, this->CurrentLocalGenerator ->GenerateAppleInfoPList(gtgt, "$(EXECUTABLE_NAME)", plist.c_str()); - std::string path = - this->ConvertToRelativeForXCode(plist.c_str()); buildSettings->AddAttribute("INFOPLIST_FILE", - this->CreateString(path.c_str())); + this->CreateString(plist)); } } @@ -3880,12 +3873,6 @@ std::string cmGlobalXCodeGenerator::ConvertToRelativeForMake(const char* p) return cmSystemTools::ConvertToOutputPath(p); } -//---------------------------------------------------------------------------- -std::string cmGlobalXCodeGenerator::ConvertToRelativeForXCode(const char* p) -{ - return cmSystemTools::ConvertToOutputPath(p); -} - //---------------------------------------------------------------------------- std::string cmGlobalXCodeGenerator::RelativeToSource(const char* p) { @@ -4022,8 +4009,8 @@ void cmGlobalXCodeGenerator::AppendFlag(std::string& flags, // We escape a flag as follows: // - Place each flag in single quotes '' - // - Escape a single quote as \\' - // - Escape a backslash as \\\\ since it itself is an escape + // - Escape a single quote as \' + // - Escape a backslash as \\ since it itself is an escape // Note that in the code below we need one more level of escapes for // C string syntax in this source file. // @@ -4043,16 +4030,16 @@ void cmGlobalXCodeGenerator::AppendFlag(std::string& flags, { if (this->XcodeVersion >= 40) { - flags += "'\\\\''"; + flags += "'\\''"; } else { - flags += "\\\\'"; + flags += "\\'"; } } else if(*c == '\\') { - flags += "\\\\\\\\"; + flags += "\\\\"; } else { diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index c8a39dfa2..b5fd13ca4 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h @@ -99,7 +99,6 @@ private: std::string XCodeEscapePath(const char* p); std::string RelativeToSource(const char* p); std::string RelativeToBinary(const char* p); - std::string ConvertToRelativeForXCode(const char* p); std::string ConvertToRelativeForMake(const char* p); void CreateCustomCommands(cmXCodeObject* buildPhases, cmXCodeObject* sourceBuildPhase, diff --git a/Source/cmXCodeObject.cxx b/Source/cmXCodeObject.cxx index c59c3609f..5bc34c136 100644 --- a/Source/cmXCodeObject.cxx +++ b/Source/cmXCodeObject.cxx @@ -255,9 +255,9 @@ void cmXCodeObject::PrintString(std::ostream& os,std::string String) for(std::string::const_iterator i = String.begin(); i != String.end(); ++i) { - if(*i == '"') + if(*i == '"' || *i == '\\') { - // Escape double-quotes. + // Escape double-quotes and backslashes. os << '\\'; } os << *i; diff --git a/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake b/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake index acc007580..395c74b30 100644 --- a/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake +++ b/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake @@ -3,6 +3,7 @@ include(RunCMake) run_cmake(XcodeFileType) run_cmake(XcodeAttributeGenex) run_cmake(XcodeAttributeGenexError) +run_cmake(XcodeObjectNeedsEscape) run_cmake(XcodeObjectNeedsQuote) run_cmake(XcodeOptimizationFlags) run_cmake(XcodePreserveNonOptimizationFlags) diff --git a/Tests/RunCMake/XcodeProject/XcodeObjectNeedsEscape-check.cmake b/Tests/RunCMake/XcodeProject/XcodeObjectNeedsEscape-check.cmake new file mode 100644 index 000000000..c34e3feb6 --- /dev/null +++ b/Tests/RunCMake/XcodeProject/XcodeObjectNeedsEscape-check.cmake @@ -0,0 +1,7 @@ +set(expect "-DKDESRCDIR=\\\\\\\\\\\\\"foo\\\\\\\\\\\\\"") +file(STRINGS ${RunCMake_TEST_BINARY_DIR}/XcodeObjectNeedsEscape.xcodeproj/project.pbxproj actual + REGEX "OTHER_CPLUSPLUSFLAGS = [^;]*;" LIMIT_COUNT 1) +if(NOT "${actual}" MATCHES "${expect}") + message(SEND_ERROR "The actual project contains the line:\n ${actual}\n" + "which does not match expected regex:\n ${expect}\n") +endif() diff --git a/Tests/RunCMake/XcodeProject/XcodeObjectNeedsEscape.cmake b/Tests/RunCMake/XcodeProject/XcodeObjectNeedsEscape.cmake new file mode 100644 index 000000000..7606a1906 --- /dev/null +++ b/Tests/RunCMake/XcodeProject/XcodeObjectNeedsEscape.cmake @@ -0,0 +1,3 @@ +enable_language(CXX) +string(APPEND CMAKE_CXX_FLAGS " -DKDESRCDIR=\\\"foo\\\"") +add_library(foo STATIC foo.cpp)