diff options
author | Manuel Klimek <klimek@google.com> | 2012-05-15 11:46:07 +0000 |
---|---|---|
committer | Manuel Klimek <klimek@google.com> | 2012-05-15 11:46:07 +0000 |
commit | fdbe4f9dc2bef59d6b03af3c99a31b532aa91330 (patch) | |
tree | 8e1aacad9c0fd0d2d9c7dfd7cbe33729e1411f5c /clang | |
parent | 9304763dfc0805cf1b65625653f3b87b553c40d6 (diff) | |
download | bcm5719-llvm-fdbe4f9dc2bef59d6b03af3c99a31b532aa91330.tar.gz bcm5719-llvm-fdbe4f9dc2bef59d6b03af3c99a31b532aa91330.zip |
Fixes crasher bug in JSONCompilationDatabase for invalid input.
llvm-svn: 156814
Diffstat (limited to 'clang')
-rw-r--r-- | clang/lib/Tooling/CompilationDatabase.cpp | 28 | ||||
-rw-r--r-- | clang/unittests/Tooling/CompilationDatabaseTest.cpp | 20 |
2 files changed, 42 insertions, 6 deletions
diff --git a/clang/lib/Tooling/CompilationDatabase.cpp b/clang/lib/Tooling/CompilationDatabase.cpp index dd9ccc07b60..c87833fba63 100644 --- a/clang/lib/Tooling/CompilationDatabase.cpp +++ b/clang/lib/Tooling/CompilationDatabase.cpp @@ -222,10 +222,9 @@ bool JSONCompilationDatabase::parse(std::string &ErrorMessage) { ErrorMessage = "Expected object."; return false; } - llvm::yaml::ScalarNode *Directory; - llvm::yaml::ScalarNode *Command; - llvm::SmallString<8> FileStorage; - llvm::StringRef File; + llvm::yaml::ScalarNode *Directory = NULL; + llvm::yaml::ScalarNode *Command = NULL; + llvm::yaml::ScalarNode *File = NULL; for (llvm::yaml::MappingNode::iterator KVI = Object->begin(), KVE = Object->end(); KVI != KVE; ++KVI) { @@ -242,20 +241,37 @@ bool JSONCompilationDatabase::parse(std::string &ErrorMessage) { } llvm::yaml::ScalarNode *KeyString = llvm::dyn_cast<llvm::yaml::ScalarNode>((*KVI).getKey()); + if (KeyString == NULL) { + ErrorMessage = "Expected strings as key."; + return false; + } llvm::SmallString<8> KeyStorage; if (KeyString->getValue(KeyStorage) == "directory") { Directory = ValueString; } else if (KeyString->getValue(KeyStorage) == "command") { Command = ValueString; } else if (KeyString->getValue(KeyStorage) == "file") { - File = ValueString->getValue(FileStorage); + File = ValueString; } else { ErrorMessage = ("Unknown key: \"" + KeyString->getRawValue() + "\"").str(); return false; } } - IndexByFile[File].push_back( + if (!File) { + ErrorMessage = "Missing key: \"file\"."; + return false; + } + if (!Command) { + ErrorMessage = "Missing key: \"command\"."; + return false; + } + if (!Directory) { + ErrorMessage = "Missing key: \"directory\"."; + return false; + } + llvm::SmallString<8> FileStorage; + IndexByFile[File->getValue(FileStorage)].push_back( CompileCommandRef(Directory, Command)); } return true; diff --git a/clang/unittests/Tooling/CompilationDatabaseTest.cpp b/clang/unittests/Tooling/CompilationDatabaseTest.cpp index 68d2896f121..7753c154100 100644 --- a/clang/unittests/Tooling/CompilationDatabaseTest.cpp +++ b/clang/unittests/Tooling/CompilationDatabaseTest.cpp @@ -18,6 +18,26 @@ namespace clang { namespace tooling { +static void expectFailure(StringRef JSONDatabase, StringRef Explanation) { + std::string ErrorMessage; + EXPECT_EQ(NULL, JSONCompilationDatabase::loadFromBuffer(JSONDatabase, + ErrorMessage)) + << "Expected an error because of: " << Explanation; +} + +TEST(JSONCompilationDatabase, ErrsOnInvalidFormat) { + expectFailure("", "Empty database"); + expectFailure("{", "Invalid JSON"); + expectFailure("[[]]", "Array instead of object"); + expectFailure("[{\"a\":[]}]", "Array instead of value"); + expectFailure("[{\"a\":\"b\"}]", "Unknown key"); + expectFailure("[{[]:\"\"}]", "Incorrectly typed entry"); + expectFailure("[{}]", "Empty entry"); + expectFailure("[{\"directory\":\"\",\"command\":\"\"}]", "Missing file"); + expectFailure("[{\"directory\":\"\",\"file\":\"\"}]", "Missing command"); + expectFailure("[{\"command\":\"\",\"file\":\"\"}]", "Missing directory"); +} + static CompileCommand findCompileArgsInJsonDatabase(StringRef FileName, StringRef JSONDatabase, std::string &ErrorMessage) { |