From 28bb8d1fdb3e662364daea71b3d87d6f4a660628 Mon Sep 17 00:00:00 2001 From: Volodymyr Sapsai Date: Tue, 7 Aug 2018 19:05:41 +0000 Subject: [PATCH] [VFS] Emit an error when entry at root level uses a relative path. Entries with only a filename prevent us from building a file system tree and cause the assertion > Assertion failed: (NewParentE && "Parent entry must exist"), function uniqueOverlayTree, file clang/lib/Basic/VirtualFileSystem.cpp, line 1303. Entries with a relative path are simply not discoverable during header search. rdar://problem/28990865 Reviewers: bruno, benlangmuir Reviewed By: bruno Subscribers: dexonsmith, cfe-commits Differential Revision: https://reviews.llvm.org/D49518 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@339164 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Basic/VirtualFileSystem.cpp | 18 ++++++++++--- unittests/Basic/VirtualFileSystemTest.cpp | 32 +++++++++++++++++++++++ 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/lib/Basic/VirtualFileSystem.cpp b/lib/Basic/VirtualFileSystem.cpp index a7b8b024a4..c0cf48d366 100644 --- a/lib/Basic/VirtualFileSystem.cpp +++ b/lib/Basic/VirtualFileSystem.cpp @@ -1281,7 +1281,8 @@ class RedirectingFileSystemParser { } } - std::unique_ptr parseEntry(yaml::Node *N, RedirectingFileSystem *FS) { + std::unique_ptr parseEntry(yaml::Node *N, RedirectingFileSystem *FS, + bool IsRootEntry) { auto *M = dyn_cast(N); if (!M) { error(N, "expected mapping node for file or directory entry"); @@ -1302,6 +1303,7 @@ class RedirectingFileSystemParser { std::vector> EntryArrayContents; std::string ExternalContentsPath; std::string Name; + yaml::Node *NameValueNode; auto UseExternalName = RedirectingFileEntry::NK_NotSet; EntryKind Kind; @@ -1321,6 +1323,7 @@ class RedirectingFileSystemParser { if (!parseScalarString(I.getValue(), Value, Buffer)) return nullptr; + NameValueNode = I.getValue(); if (FS->UseCanonicalizedPaths) { SmallString<256> Path(Value); // Guarantee that old YAML files containing paths with ".." and "." @@ -1357,7 +1360,8 @@ class RedirectingFileSystemParser { } for (auto &I : *Contents) { - if (std::unique_ptr E = parseEntry(&I, FS)) + if (std::unique_ptr E = + parseEntry(&I, FS, /*IsRootEntry*/ false)) EntryArrayContents.push_back(std::move(E)); else return nullptr; @@ -1418,6 +1422,13 @@ class RedirectingFileSystemParser { return nullptr; } + if (IsRootEntry && !sys::path::is_absolute(Name)) { + assert(NameValueNode && "Name presence should be checked earlier"); + error(NameValueNode, + "entry with relative path at the root level is not discoverable"); + return nullptr; + } + // Remove trailing slash(es), being careful not to remove the root path StringRef Trimmed(Name); size_t RootPathLen = sys::path::root_path(Trimmed).size(); @@ -1500,7 +1511,8 @@ public: } for (auto &I : *Roots) { - if (std::unique_ptr E = parseEntry(&I, FS)) + if (std::unique_ptr E = + parseEntry(&I, FS, /*IsRootEntry*/ true)) RootEntries.push_back(std::move(E)); else return false; diff --git a/unittests/Basic/VirtualFileSystemTest.cpp b/unittests/Basic/VirtualFileSystemTest.cpp index a9b39b5b13..22fbeac3c1 100644 --- a/unittests/Basic/VirtualFileSystemTest.cpp +++ b/unittests/Basic/VirtualFileSystemTest.cpp @@ -1468,3 +1468,35 @@ TEST_F(VFSFromYAMLTest, RecursiveDirectoryIterationLevel) { } EXPECT_EQ(I, E); } + +TEST_F(VFSFromYAMLTest, RelativePaths) { + IntrusiveRefCntPtr Lower(new DummyFileSystem()); + // Filename at root level without a parent directory. + IntrusiveRefCntPtr FS = getFromYAMLString( + "{ 'roots': [\n" + " { 'type': 'file', 'name': 'file-not-in-directory.h',\n" + " 'external-contents': '//root/external/file'\n" + " }\n" + "] }", Lower); + EXPECT_EQ(nullptr, FS.get()); + + // Relative file path. + FS = getFromYAMLString( + "{ 'roots': [\n" + " { 'type': 'file', 'name': 'relative/file/path.h',\n" + " 'external-contents': '//root/external/file'\n" + " }\n" + "] }", Lower); + EXPECT_EQ(nullptr, FS.get()); + + // Relative directory path. + FS = getFromYAMLString( + "{ 'roots': [\n" + " { 'type': 'directory', 'name': 'relative/directory/path.h',\n" + " 'contents': []\n" + " }\n" + "] }", Lower); + EXPECT_EQ(nullptr, FS.get()); + + EXPECT_EQ(3, NumDiagnostics); +} -- 2.50.1