From 2089567a85b751481f5f733ff4b3f051f0a1f0ea Mon Sep 17 00:00:00 2001
From: Vitaly Baranov <kerrax@mail.ru>
Date: Sat, 26 Sep 2015 22:49:19 +0300
Subject: [PATCH] SystemTools: Fix GetPath to not affect existing output vector
 entries

The GetPath method appends paths to an output vector and also converts
paths to forward slashes.  However, the method should not modify entries
in the output vector that existed prior to the call.  Fix it to only fix
slashes in the entries it added to the vector.  Also add a test case
covering this behavior.

Change-Id: Ie098c3eddbe63ed59f0d393aa6c43ea6c395011d
---
 SystemTools.cxx     |  3 ++-
 testSystemTools.cxx | 63 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 65 insertions(+), 1 deletion(-)

diff --git a/SystemTools.cxx b/SystemTools.cxx
index 80289b8..262af27 100644
--- a/SystemTools.cxx
+++ b/SystemTools.cxx
@@ -408,6 +408,7 @@ class SystemToolsPathCaseMap:
 // adds the elements of the env variable path to the arg passed in
 void SystemTools::GetPath(std::vector<std::string>& path, const char* env)
 {
+  size_t const old_size = path.size();
 #if defined(_WIN32) && !defined(__CYGWIN__)
   const char pathSep = ';';
 #else
@@ -445,7 +446,7 @@ void SystemTools::GetPath(std::vector<std::string>& path, const char* env)
       done = true;
       }
     }
-  for(std::vector<std::string>::iterator i = path.begin();
+  for(std::vector<std::string>::iterator i = path.begin() + old_size;
       i != path.end(); ++i)
     {
     SystemTools::ConvertToUnixSlashes(*i);
diff --git a/testSystemTools.cxx b/testSystemTools.cxx
index e14d2fc..a0f904f 100644
--- a/testSystemTools.cxx
+++ b/testSystemTools.cxx
@@ -28,6 +28,7 @@
 #include <testSystemTools.h>
 
 #include <iostream>
+#include <sstream>
 #include <string.h> /* strcmp */
 #if defined(_WIN32) && !defined(__CYGWIN__)
 # include <io.h> /* _umask (MSVC) / umask (Borland) */
@@ -790,6 +791,66 @@ static bool CheckCollapsePath()
   return res;
 }
 
+static std::string StringVectorToString(const std::vector<std::string>& vec)
+{
+  std::stringstream ss;
+  ss << "vector(";
+  for (std::vector<std::string>::const_iterator i = vec.begin();
+       i != vec.end(); ++i)
+    {
+    if (i != vec.begin())
+      {
+      ss << ", ";
+      }
+    ss << *i;
+    }
+  ss << ")";
+  return ss.str();
+}
+
+static bool CheckGetPath()
+{
+  const char* envName = "S";
+#ifdef _WIN32
+  const char* envValue = "C:\\Somewhere\\something;D:\\Temp";
+#else
+  const char* envValue = "/Somewhere/something:/tmp";
+#endif
+  const char* registryPath = "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MyApp; MyKey]";
+
+  std::vector<std::string> originalPathes;
+  originalPathes.push_back(registryPath);
+
+  std::vector<std::string> expectedPathes;
+  expectedPathes.push_back(registryPath);
+#ifdef _WIN32
+  expectedPathes.push_back("C:/Somewhere/something");
+  expectedPathes.push_back("D:/Temp");
+#else
+  expectedPathes.push_back("/Somewhere/something");
+  expectedPathes.push_back("/tmp");
+#endif
+
+  bool res = true;
+  res &= CheckPutEnv(std::string(envName) + "=" + envValue, envName, envValue);
+
+  std::vector<std::string> pathes = originalPathes;
+  kwsys::SystemTools::GetPath(pathes, envName);
+
+  if (pathes != expectedPathes)
+    {
+    std::cerr <<
+      "GetPath(" << StringVectorToString(originalPathes) <<
+      ", " << envName << ")  yielded " << StringVectorToString(pathes) <<
+      " instead of " << StringVectorToString(expectedPathes) <<
+      std::endl;
+    res = false;
+    }
+
+  res &= CheckUnPutEnv(envName, envName);
+  return res;
+}
+
 //----------------------------------------------------------------------------
 int testSystemTools(int, char*[])
 {
@@ -825,5 +886,7 @@ int testSystemTools(int, char*[])
 
   res &= CheckCollapsePath();
 
+  res &= CheckGetPath();
+
   return res ? 0 : 1;
 }
-- 
GitLab