]> granicus.if.org Git - clang/commitdiff
VirtualFileSystem: Fix false positives in YAMLVFSWriter::containedIn
authorJustin Bogner <mail@justinbogner.com>
Tue, 20 May 2014 22:12:58 +0000 (22:12 +0000)
committerJustin Bogner <mail@justinbogner.com>
Tue, 20 May 2014 22:12:58 +0000 (22:12 +0000)
Checking if a path starts with another path isn't sufficient for
determining if one is contained within the heirarchy of the other.
We need to ensure that the substring ends at a directory boundary.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@209250 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Basic/VirtualFileSystem.cpp
unittests/libclang/LibclangTest.cpp

index 24454b0192c16562fbac4a58ea637978b2669db7..077370dcf424299185651fad451ec34d39e044d4 100644 (file)
@@ -928,7 +928,16 @@ YAMLVFSWriter::printContents(llvm::raw_ostream &OS, ArrayRef<MapEntry> Entries,
 }
 
 bool YAMLVFSWriter::containedIn(StringRef Parent, StringRef Path) {
-  return Path.startswith(Parent);
+  using namespace llvm::sys;
+  // Compare each path component.
+  auto IParent = path::begin(Parent), EParent = path::end(Parent);
+  for (auto IChild = path::begin(Path), EChild = path::end(Path);
+       IParent != EParent && IChild != EChild; ++IParent, ++IChild) {
+    if (*IParent != *IChild)
+      return false;
+  }
+  // Have we exhausted the parent path?
+  return IParent == EParent;
 }
 
 StringRef YAMLVFSWriter::containedPart(StringRef Parent, StringRef Path) {
index 50d4c489f23ceaf4d964fd1e3984919331713c18..61578a4801ca538b883e9afd7fe04e6ea6867440 100644 (file)
@@ -184,6 +184,57 @@ TEST(libclang, VirtualFileOverlay) {
     T.map("/path/virtual/foo.h", "/real/foo.h");
     clang_VirtualFileOverlay_setCaseSensitivity(T.VFO, false);
   }
+  {
+    const char *contents =
+    "{\n"
+    "  'version': 0,\n"
+    "  'roots': [\n"
+    "    {\n"
+    "      'type': 'directory',\n"
+    "      'name': \"/path/foo\",\n"
+    "      'contents': [\n"
+    "        {\n"
+    "          'type': 'file',\n"
+    "          'name': \"bar\",\n"
+    "          'external-contents': \"/real/bar\"\n"
+    "        },\n"
+    "        {\n"
+    "          'type': 'file',\n"
+    "          'name': \"bar.h\",\n"
+    "          'external-contents': \"/real/bar.h\"\n"
+    "        }\n"
+    "      ]\n"
+    "    },\n"
+    "    {\n"
+    "      'type': 'directory',\n"
+    "      'name': \"/path/foobar\",\n"
+    "      'contents': [\n"
+    "        {\n"
+    "          'type': 'file',\n"
+    "          'name': \"baz.h\",\n"
+    "          'external-contents': \"/real/baz.h\"\n"
+    "        }\n"
+    "      ]\n"
+    "    },\n"
+    "    {\n"
+    "      'type': 'directory',\n"
+    "      'name': \"/path\",\n"
+    "      'contents': [\n"
+    "        {\n"
+    "          'type': 'file',\n"
+    "          'name': \"foobarbaz.h\",\n"
+    "          'external-contents': \"/real/foobarbaz.h\"\n"
+    "        }\n"
+    "      ]\n"
+    "    }\n"
+    "  ]\n"
+    "}\n";
+    TestVFO T(contents);
+    T.map("/path/foo/bar.h", "/real/bar.h");
+    T.map("/path/foo/bar", "/real/bar");
+    T.map("/path/foobar/baz.h", "/real/baz.h");
+    T.map("/path/foobarbaz.h", "/real/foobarbaz.h");
+  }
 }
 
 TEST(libclang, ModuleMapDescriptor) {