From 8e02975142bd111c838decac0a64a472f76c0e99 Mon Sep 17 00:00:00 2001
From: Gregor Jasny <gjasny@googlemail.com>
Date: Wed, 6 Dec 2017 18:12:55 +0100
Subject: [PATCH] SystemTools: Fix IsSubDirectory for subdirs of drive root

---
 SystemTools.cxx     | 13 +++++++++----
 testSystemTools.cxx | 35 +++++++++++++++++++++++++++++++++++
 2 files changed, 44 insertions(+), 4 deletions(-)

diff --git a/SystemTools.cxx b/SystemTools.cxx
index 50aa857b..649f30bd 100644
--- a/SystemTools.cxx
+++ b/SystemTools.cxx
@@ -4234,11 +4234,16 @@ bool SystemTools::IsSubDirectory(const std::string& cSubdir,
   std::string dir = cDir;
   SystemTools::ConvertToUnixSlashes(subdir);
   SystemTools::ConvertToUnixSlashes(dir);
-  if (subdir.size() > dir.size() && subdir[dir.size()] == '/') {
-    std::string s = subdir.substr(0, dir.size());
-    return SystemTools::ComparePath(s, dir);
+  if (subdir.size() <= dir.size() || dir.empty()) {
+    return false;
   }
-  return false;
+  bool isRootPath = *dir.rbegin() == '/'; // like "/" or "C:/"
+  size_t expectedSlashPosition = isRootPath ? dir.size() - 1u : dir.size();
+  if (subdir[expectedSlashPosition] != '/') {
+    return false;
+  }
+  std::string s = subdir.substr(0, dir.size());
+  return SystemTools::ComparePath(s, dir);
 }
 
 void SystemTools::Delay(unsigned int msec)
diff --git a/testSystemTools.cxx b/testSystemTools.cxx
index 3b694c90..a6af9cc9 100644
--- a/testSystemTools.cxx
+++ b/testSystemTools.cxx
@@ -813,6 +813,39 @@ static bool CheckFind()
   return res;
 }
 
+static bool CheckIsSubDirectory()
+{
+  bool res = true;
+
+  if (kwsys::SystemTools::IsSubDirectory("/foo", "/") == false) {
+    std::cerr << "Problem with IsSubDirectory (root - unix): " << std::endl;
+    res = false;
+  }
+  if (kwsys::SystemTools::IsSubDirectory("c:/foo", "c:/") == false) {
+    std::cerr << "Problem with IsSubDirectory (root - dos): " << std::endl;
+    res = false;
+  }
+  if (kwsys::SystemTools::IsSubDirectory("/foo/bar", "/foo") == false) {
+    std::cerr << "Problem with IsSubDirectory (deep): " << std::endl;
+    res = false;
+  }
+  if (kwsys::SystemTools::IsSubDirectory("/foo", "/foo") == true) {
+    std::cerr << "Problem with IsSubDirectory (identity): " << std::endl;
+    res = false;
+  }
+  if (kwsys::SystemTools::IsSubDirectory("/fooo", "/foo") == true) {
+    std::cerr << "Problem with IsSubDirectory (substring): " << std::endl;
+    res = false;
+  }
+  if (kwsys::SystemTools::IsSubDirectory("/foo/", "/foo") == true) {
+    std::cerr << "Problem with IsSubDirectory (prepended slash): "
+              << std::endl;
+    res = false;
+  }
+
+  return res;
+}
+
 static bool CheckGetLineFromStream()
 {
   const std::string fileWithFiveCharsOnFirstLine(TEST_SYSTEMTOOLS_SOURCE_DIR
@@ -897,6 +930,8 @@ int testSystemTools(int, char* [])
 
   res &= CheckFind();
 
+  res &= CheckIsSubDirectory();
+
   res &= CheckGetLineFromStream();
 
   res &= CheckGetFilenameName();
-- 
GitLab