mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-28 08:02:08 +00:00
[clangd] Only allow remote index to be enabled from user config.
Differential Revision: https://reviews.llvm.org/D100542
This commit is contained in:
parent
49cbf4cd85
commit
ecf93a716c
@ -101,6 +101,7 @@ struct FragmentCompiler {
|
||||
llvm::SourceMgr *SourceMgr;
|
||||
// Normalized Fragment::SourceInfo::Directory.
|
||||
std::string FragmentDirectory;
|
||||
bool Trusted = false;
|
||||
|
||||
llvm::Optional<llvm::Regex>
|
||||
compileRegex(const Located<std::string> &Text,
|
||||
@ -183,6 +184,7 @@ struct FragmentCompiler {
|
||||
}
|
||||
|
||||
void compile(Fragment &&F) {
|
||||
Trusted = F.Source.Trusted;
|
||||
if (!F.Source.Directory.empty()) {
|
||||
FragmentDirectory = llvm::sys::path::convert_to_slash(F.Source.Directory);
|
||||
if (FragmentDirectory.back() != '/')
|
||||
@ -320,6 +322,13 @@ struct FragmentCompiler {
|
||||
|
||||
void compile(Fragment::IndexBlock::ExternalBlock &&External,
|
||||
llvm::SMRange BlockRange) {
|
||||
if (External.Server && !Trusted) {
|
||||
diag(Error,
|
||||
"Remote index may not be specified by untrusted configuration. "
|
||||
"Copy this into user config to use it.",
|
||||
External.Server->Range);
|
||||
return;
|
||||
}
|
||||
#ifndef CLANGD_ENABLE_REMOTE
|
||||
if (External.Server) {
|
||||
elog("Clangd isn't compiled with remote index support, ignoring Server: "
|
||||
@ -510,8 +519,8 @@ CompiledFragment Fragment::compile(DiagnosticCallback D) && {
|
||||
trace::Span Tracer("ConfigCompile");
|
||||
SPAN_ATTACH(Tracer, "ConfigFile", ConfigFile);
|
||||
auto Result = std::make_shared<CompiledFragmentImpl>();
|
||||
vlog("Config fragment: compiling {0}:{1} -> {2}", ConfigFile, LineCol.first,
|
||||
Result.get());
|
||||
vlog("Config fragment: compiling {0}:{1} -> {2} (trusted={3})", ConfigFile,
|
||||
LineCol.first, Result.get(), Source.Trusted);
|
||||
|
||||
FragmentCompiler{*Result, D, Source.Manager.get()}.compile(std::move(*this));
|
||||
// Return as cheaply-copyable wrapper.
|
||||
|
@ -94,6 +94,9 @@ struct Fragment {
|
||||
/// Absolute path to directory the fragment is associated with. Relative
|
||||
/// paths mentioned in the fragment are resolved against this.
|
||||
std::string Directory;
|
||||
/// Whether this fragment is allowed to make critical security/privacy
|
||||
/// decisions.
|
||||
bool Trusted = false;
|
||||
};
|
||||
SourceInfo Source;
|
||||
|
||||
|
@ -36,7 +36,7 @@ public:
|
||||
: FileCache(Path), Directory(Directory) {}
|
||||
|
||||
void get(const ThreadsafeFS &TFS, DiagnosticCallback DC,
|
||||
std::chrono::steady_clock::time_point FreshTime,
|
||||
std::chrono::steady_clock::time_point FreshTime, bool Trusted,
|
||||
std::vector<CompiledFragment> &Out) const {
|
||||
read(
|
||||
TFS, FreshTime,
|
||||
@ -45,6 +45,7 @@ public:
|
||||
if (Data)
|
||||
for (auto &Fragment : Fragment::parseYAML(*Data, path(), DC)) {
|
||||
Fragment.Source.Directory = Directory;
|
||||
Fragment.Source.Trusted = Trusted;
|
||||
CachedValue.push_back(std::move(Fragment).compile(DC));
|
||||
}
|
||||
},
|
||||
@ -54,35 +55,38 @@ public:
|
||||
|
||||
std::unique_ptr<Provider> Provider::fromYAMLFile(llvm::StringRef AbsPath,
|
||||
llvm::StringRef Directory,
|
||||
const ThreadsafeFS &FS) {
|
||||
const ThreadsafeFS &FS,
|
||||
bool Trusted) {
|
||||
class AbsFileProvider : public Provider {
|
||||
mutable FileConfigCache Cache; // threadsafe
|
||||
const ThreadsafeFS &FS;
|
||||
bool Trusted;
|
||||
|
||||
std::vector<CompiledFragment>
|
||||
getFragments(const Params &P, DiagnosticCallback DC) const override {
|
||||
std::vector<CompiledFragment> Result;
|
||||
Cache.get(FS, DC, P.FreshTime, Result);
|
||||
Cache.get(FS, DC, P.FreshTime, Trusted, Result);
|
||||
return Result;
|
||||
};
|
||||
|
||||
public:
|
||||
AbsFileProvider(llvm::StringRef Path, llvm::StringRef Directory,
|
||||
const ThreadsafeFS &FS)
|
||||
: Cache(Path, Directory), FS(FS) {
|
||||
const ThreadsafeFS &FS, bool Trusted)
|
||||
: Cache(Path, Directory), FS(FS), Trusted(Trusted) {
|
||||
assert(llvm::sys::path::is_absolute(Path));
|
||||
}
|
||||
};
|
||||
|
||||
return std::make_unique<AbsFileProvider>(AbsPath, Directory, FS);
|
||||
return std::make_unique<AbsFileProvider>(AbsPath, Directory, FS, Trusted);
|
||||
}
|
||||
|
||||
std::unique_ptr<Provider>
|
||||
Provider::fromAncestorRelativeYAMLFiles(llvm::StringRef RelPath,
|
||||
const ThreadsafeFS &FS) {
|
||||
const ThreadsafeFS &FS, bool Trusted) {
|
||||
class RelFileProvider : public Provider {
|
||||
std::string RelPath;
|
||||
const ThreadsafeFS &FS;
|
||||
bool Trusted;
|
||||
|
||||
mutable std::mutex Mu;
|
||||
// Keys are the (posix-style) ancestor directory, not the config within it.
|
||||
@ -124,18 +128,19 @@ Provider::fromAncestorRelativeYAMLFiles(llvm::StringRef RelPath,
|
||||
// This will take a (per-file) lock for each file that actually exists.
|
||||
std::vector<CompiledFragment> Result;
|
||||
for (FileConfigCache *Cache : llvm::reverse(Caches))
|
||||
Cache->get(FS, DC, P.FreshTime, Result);
|
||||
Cache->get(FS, DC, P.FreshTime, Trusted, Result);
|
||||
return Result;
|
||||
};
|
||||
|
||||
public:
|
||||
RelFileProvider(llvm::StringRef RelPath, const ThreadsafeFS &FS)
|
||||
: RelPath(RelPath), FS(FS) {
|
||||
RelFileProvider(llvm::StringRef RelPath, const ThreadsafeFS &FS,
|
||||
bool Trusted)
|
||||
: RelPath(RelPath), FS(FS), Trusted(Trusted) {
|
||||
assert(llvm::sys::path::is_relative(RelPath));
|
||||
}
|
||||
};
|
||||
|
||||
return std::make_unique<RelFileProvider>(RelPath, FS);
|
||||
return std::make_unique<RelFileProvider>(RelPath, FS, Trusted);
|
||||
}
|
||||
|
||||
std::unique_ptr<Provider>
|
||||
|
@ -69,7 +69,8 @@ public:
|
||||
/// Directory will be used to resolve relative paths in the fragments.
|
||||
static std::unique_ptr<Provider> fromYAMLFile(llvm::StringRef AbsPath,
|
||||
llvm::StringRef Directory,
|
||||
const ThreadsafeFS &);
|
||||
const ThreadsafeFS &,
|
||||
bool Trusted = false);
|
||||
// Reads fragments from YAML files found relative to ancestors of Params.Path.
|
||||
//
|
||||
// All fragments that exist are returned, starting from distant ancestors.
|
||||
@ -78,7 +79,8 @@ public:
|
||||
//
|
||||
// If Params does not specify a path, no fragments are returned.
|
||||
static std::unique_ptr<Provider>
|
||||
fromAncestorRelativeYAMLFiles(llvm::StringRef RelPath, const ThreadsafeFS &);
|
||||
fromAncestorRelativeYAMLFiles(llvm::StringRef RelPath, const ThreadsafeFS &,
|
||||
bool Trusted = false);
|
||||
|
||||
/// A provider that includes fragments from all the supplied providers.
|
||||
/// Order is preserved; later providers take precedence over earlier ones.
|
||||
|
@ -855,8 +855,8 @@ clangd accepts flags on the commandline, and in the CLANGD_FLAGS environment var
|
||||
if (llvm::sys::path::user_config_directory(UserConfig)) {
|
||||
llvm::sys::path::append(UserConfig, "clangd", "config.yaml");
|
||||
vlog("User config file is {0}", UserConfig);
|
||||
ProviderStack.push_back(
|
||||
config::Provider::fromYAMLFile(UserConfig, /*Directory=*/"", TFS));
|
||||
ProviderStack.push_back(config::Provider::fromYAMLFile(
|
||||
UserConfig, /*Directory=*/"", TFS, /*Trusted=*/true));
|
||||
} else {
|
||||
elog("Couldn't determine user config file, not loading");
|
||||
}
|
||||
|
@ -318,7 +318,21 @@ TEST_F(ConfigCompileTests, TidyBadChecks) {
|
||||
DiagKind(llvm::SourceMgr::DK_Warning))));
|
||||
}
|
||||
|
||||
TEST_F(ConfigCompileTests, ExternalServerNeedsTrusted) {
|
||||
Fragment::IndexBlock::ExternalBlock External;
|
||||
External.Server.emplace("xxx");
|
||||
Frag.Index.External = std::move(External);
|
||||
compileAndApply();
|
||||
EXPECT_THAT(
|
||||
Diags.Diagnostics,
|
||||
ElementsAre(DiagMessage(
|
||||
"Remote index may not be specified by untrusted configuration. "
|
||||
"Copy this into user config to use it.")));
|
||||
EXPECT_FALSE(Conf.Index.External.hasValue());
|
||||
}
|
||||
|
||||
TEST_F(ConfigCompileTests, ExternalBlockWarnOnMultipleSource) {
|
||||
Frag.Source.Trusted = true;
|
||||
Fragment::IndexBlock::ExternalBlock External;
|
||||
External.File.emplace("");
|
||||
External.Server.emplace("");
|
||||
|
Loading…
Reference in New Issue
Block a user