Browse Source

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.
Gregor Jasny 9 years ago
parent
commit
ba39d7e9d0

+ 9 - 22
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
       {

+ 0 - 1
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,

+ 2 - 2
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;

+ 1 - 0
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)

+ 7 - 0
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()

+ 3 - 0
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)