]> granicus.if.org Git - clang/commitdiff
Fixes crasher bug in JSONCompilationDatabase for invalid input.
authorManuel Klimek <klimek@google.com>
Tue, 15 May 2012 11:46:07 +0000 (11:46 +0000)
committerManuel Klimek <klimek@google.com>
Tue, 15 May 2012 11:46:07 +0000 (11:46 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@156814 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Tooling/CompilationDatabase.cpp
unittests/Tooling/CompilationDatabaseTest.cpp

index dd9ccc07b60be77d161905efeab7af567b4609a6..c87833fba63b201f2b737baffc99a376796cf0ce 100644 (file)
@@ -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;
index 68d2896f1212dbd641ce696fcbc01092e074c035..7753c154100f2b8131549290b8a10ec5d113bd09 100644 (file)
 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) {