Index: clang-tidy/ClangTidy.h =================================================================== --- clang-tidy/ClangTidy.h +++ clang-tidy/ClangTidy.h @@ -86,6 +86,12 @@ /// framework. Can be called only once. void setName(StringRef Name); + /// \brief Returns \c true, if the specified string can be used for a check + /// name. + /// + /// Only alphanumeric characters, '-', '_' and '.' are allowed in check names. + static bool isValidCheckName(StringRef Name); + private: void run(const ast_matchers::MatchFinder::MatchResult &Result) override; ClangTidyContext *Context; Index: clang-tidy/ClangTidy.cpp =================================================================== --- clang-tidy/ClangTidy.cpp +++ clang-tidy/ClangTidy.cpp @@ -37,6 +37,7 @@ #include "clang/Tooling/Tooling.h" #include "llvm/Support/Path.h" #include "llvm/Support/Process.h" +#include "llvm/Support/Regex.h" #include "llvm/Support/Signals.h" #include #include @@ -290,6 +291,11 @@ for (StringRef CheckName : StaticAnalyzerChecks) { std::string Checker((AnalyzerCheckNamePrefix + CheckName).str()); + if (!ClangTidyCheck::isValidCheckName(Checker)) { + assert(false && + "Static analyzer check name contains invalid characters"); + continue; + } if (CheckName.startswith("core") || (!CheckName.startswith("debug") && Filter.contains(Checker))) List.push_back(std::make_pair(CheckName, true)); @@ -313,6 +319,10 @@ CheckName = Name.str(); } +bool ClangTidyCheck::isValidCheckName(StringRef Name) { + return llvm::Regex("^[a-zA-Z0-9_.\\-]+$").match(Name); +} + std::vector getCheckNames(const ClangTidyOptions &Options) { clang::tidy::ClangTidyContext Context( new DefaultOptionsProvider(ClangTidyGlobalOptions(), Options)); Index: clang-tidy/ClangTidyModule.cpp =================================================================== --- clang-tidy/ClangTidyModule.cpp +++ clang-tidy/ClangTidyModule.cpp @@ -29,6 +29,10 @@ void ClangTidyCheckFactories::createChecks( GlobList &Filter, std::vector> &Checks) { for (const auto &Factory : Factories) { + if (!ClangTidyCheck::isValidCheckName(Factory.first)) { + assert(false && "ClangTidy check name contains invalid characters"); + continue; + } if (Filter.contains(Factory.first)) { ClangTidyCheck *Check = Factory.second->createCheck(); Check->setName(Factory.first); Index: unittests/clang-tidy/CMakeLists.txt =================================================================== --- unittests/clang-tidy/CMakeLists.txt +++ unittests/clang-tidy/CMakeLists.txt @@ -9,6 +9,7 @@ add_extra_unittest(ClangTidyTests ClangTidyDiagnosticConsumerTest.cpp ClangTidyOptionsTest.cpp + ClangTidyTest.cpp LLVMModuleTest.cpp GoogleModuleTest.cpp MiscModuleTest.cpp) Index: unittests/clang-tidy/ClangTidyTest.cpp =================================================================== --- /dev/null +++ unittests/clang-tidy/ClangTidyTest.cpp @@ -0,0 +1,18 @@ +#include "ClangTidy.h" +#include "gtest/gtest.h" + +namespace clang { +namespace tidy { +namespace test { + +TEST(ClangTidyCheck, IsValidCheckName) { + EXPECT_TRUE(ClangTidyCheck::isValidCheckName("asdf123-xxx_yyy.YYY.ZZZ")); + EXPECT_FALSE(ClangTidyCheck::isValidCheckName("")); + EXPECT_FALSE(ClangTidyCheck::isValidCheckName("a b")); + EXPECT_FALSE(ClangTidyCheck::isValidCheckName("ab ")); + EXPECT_FALSE(ClangTidyCheck::isValidCheckName("ab!")); +} + +} // namespace test +} // namespace tidy +} // namespace clang