kadircet updated this revision to Diff 373163.
kadircet added a comment.
Herald added a project: clang.

- Also handle OOB access while creating compiler invocation.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D109894/new/

https://reviews.llvm.org/D109894

Files:
  clang-tools-extra/clangd/CompileCommands.cpp
  clang-tools-extra/clangd/Compiler.cpp
  clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp
  clang-tools-extra/clangd/unittests/CompilerTests.cpp
  clang/lib/Frontend/CreateInvocationFromCommandLine.cpp

Index: clang/lib/Frontend/CreateInvocationFromCommandLine.cpp
===================================================================
--- clang/lib/Frontend/CreateInvocationFromCommandLine.cpp
+++ clang/lib/Frontend/CreateInvocationFromCommandLine.cpp
@@ -30,6 +30,7 @@
     ArrayRef<const char *> ArgList, IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
     IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS, bool ShouldRecoverOnErorrs,
     std::vector<std::string> *CC1Args) {
+  assert(!ArgList.empty());
   if (!Diags.get()) {
     // No diagnostics engine was provided, so create our own diagnostics object
     // with the default options.
Index: clang-tools-extra/clangd/unittests/CompilerTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/CompilerTests.cpp
+++ clang-tools-extra/clangd/unittests/CompilerTests.cpp
@@ -102,6 +102,17 @@
   EXPECT_EQ(Opts.ProgramAction, frontend::ActionKind::ParseSyntaxOnly);
   EXPECT_TRUE(Opts.ActionName.empty());
 }
+
+TEST(BuildCompilerInvocation, EmptyArgs) {
+  MockFS FS;
+  IgnoreDiagnostics Diags;
+  TestTU TU;
+  auto Inputs = TU.inputs(FS);
+  Inputs.CompileCommand.CommandLine.clear();
+
+  // No crash.
+  EXPECT_EQ(buildCompilerInvocation(Inputs, Diags), nullptr);
+}
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp
+++ clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp
@@ -396,6 +396,13 @@
       llvm::count_if(Args, [](llvm::StringRef Arg) { return Arg == "-arch"; }),
       1);
 }
+
+TEST(CommandMangler, EmptyArgs) {
+  const auto Mangler = CommandMangler::forTests();
+  std::vector<std::string> Args = {};
+  // Make sure we don't crash.
+  Mangler.adjust(Args, "foo.cc");
+}
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/clangd/Compiler.cpp
===================================================================
--- clang-tools-extra/clangd/Compiler.cpp
+++ clang-tools-extra/clangd/Compiler.cpp
@@ -83,6 +83,8 @@
 std::unique_ptr<CompilerInvocation>
 buildCompilerInvocation(const ParseInputs &Inputs, clang::DiagnosticConsumer &D,
                         std::vector<std::string> *CC1Args) {
+  if (Inputs.CompileCommand.CommandLine.empty())
+    return nullptr;
   std::vector<const char *> ArgStrs;
   for (const auto &S : Inputs.CompileCommand.CommandLine)
     ArgStrs.push_back(S.c_str());
Index: clang-tools-extra/clangd/CompileCommands.cpp
===================================================================
--- clang-tools-extra/clangd/CompileCommands.cpp
+++ clang-tools-extra/clangd/CompileCommands.cpp
@@ -198,22 +198,26 @@
 void CommandMangler::adjust(std::vector<std::string> &Cmd,
                             llvm::StringRef File) const {
   trace::Span S("AdjustCompileFlags");
+  // Most of the modifications below assumes the Cmd starts with a driver name.
+  // We might consider injecting a generic driver name like "cc" or "c++", but
+  // a Cmd missing the driver is probably rare enough in practice and errnous.
+  if (Cmd.empty())
+    return;
   auto &OptTable = clang::driver::getDriverOptTable();
   // OriginalArgs needs to outlive ArgList.
   llvm::SmallVector<const char *, 16> OriginalArgs;
   OriginalArgs.reserve(Cmd.size());
   for (const auto &S : Cmd)
     OriginalArgs.push_back(S.c_str());
-  bool IsCLMode =
-      !OriginalArgs.empty() &&
-      driver::IsClangCL(driver::getDriverMode(
-          OriginalArgs[0], llvm::makeArrayRef(OriginalArgs).slice(1)));
+  bool IsCLMode = driver::IsClangCL(driver::getDriverMode(
+      OriginalArgs[0], llvm::makeArrayRef(OriginalArgs).slice(1)));
   // ParseArgs propagates missig arg/opt counts on error, but preserves
   // everything it could parse in ArgList. So we just ignore those counts.
   unsigned IgnoredCount;
   // Drop the executable name, as ParseArgs doesn't expect it. This means
   // indices are actually of by one between ArgList and OriginalArgs.
-  auto ArgList = OptTable.ParseArgs(
+  llvm::opt::InputArgList ArgList;
+  ArgList = OptTable.ParseArgs(
       llvm::makeArrayRef(OriginalArgs).drop_front(), IgnoredCount, IgnoredCount,
       /*FlagsToInclude=*/
       IsCLMode ? (driver::options::CLOption | driver::options::CoreOption)
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to