xref: /llvm-project/clang/unittests/Driver/SanitizerArgsTest.cpp (revision d768bf994f508d7eaf9541a568be3d71096febf5)
1aa981c18SIlya Biryukov //===- unittests/Driver/SanitizerArgsTest.cpp -----------------------------===//
2aa981c18SIlya Biryukov //
3aa981c18SIlya Biryukov // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4aa981c18SIlya Biryukov // See https://llvm.org/LICENSE.txt for license information.
5aa981c18SIlya Biryukov // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6aa981c18SIlya Biryukov //
7aa981c18SIlya Biryukov //===----------------------------------------------------------------------===//
8aa981c18SIlya Biryukov 
9aa981c18SIlya Biryukov #include "clang/Basic/Diagnostic.h"
10aa981c18SIlya Biryukov #include "clang/Basic/DiagnosticIDs.h"
11aa981c18SIlya Biryukov #include "clang/Basic/DiagnosticOptions.h"
12aa981c18SIlya Biryukov #include "clang/Driver/Compilation.h"
13aa981c18SIlya Biryukov #include "clang/Driver/Driver.h"
14aa981c18SIlya Biryukov #include "clang/Driver/Job.h"
15aa981c18SIlya Biryukov #include "clang/Frontend/TextDiagnosticPrinter.h"
16aa981c18SIlya Biryukov #include "llvm/ADT/ArrayRef.h"
17aa981c18SIlya Biryukov #include "llvm/ADT/IntrusiveRefCntPtr.h"
18aa981c18SIlya Biryukov #include "llvm/ADT/SmallString.h"
19aa981c18SIlya Biryukov #include "llvm/ADT/StringRef.h"
20aa981c18SIlya Biryukov #include "llvm/Support/MemoryBuffer.h"
21aa981c18SIlya Biryukov #include "llvm/Support/Path.h"
22aa981c18SIlya Biryukov #include "llvm/Support/VirtualFileSystem.h"
23aa981c18SIlya Biryukov #include "llvm/Support/raw_ostream.h"
24*d768bf99SArchibald Elliott #include "llvm/TargetParser/Host.h"
25aa981c18SIlya Biryukov #include "gmock/gmock.h"
26aa981c18SIlya Biryukov #include "gtest/gtest.h"
27aa981c18SIlya Biryukov #include <cstdlib>
28aa981c18SIlya Biryukov #include <memory>
29a1580d7bSKazu Hirata #include <optional>
30aa981c18SIlya Biryukov #include <string>
31aa981c18SIlya Biryukov using namespace clang;
32aa981c18SIlya Biryukov using namespace clang::driver;
33aa981c18SIlya Biryukov 
34aa981c18SIlya Biryukov using ::testing::Contains;
35aa981c18SIlya Biryukov using ::testing::StrEq;
36aa981c18SIlya Biryukov 
37aa981c18SIlya Biryukov namespace {
38aa981c18SIlya Biryukov 
39aa981c18SIlya Biryukov static constexpr const char *ClangBinary = "clang";
40aa981c18SIlya Biryukov static constexpr const char *InputFile = "/sources/foo.c";
41aa981c18SIlya Biryukov 
concatPaths(llvm::ArrayRef<StringRef> Components)42aa981c18SIlya Biryukov std::string concatPaths(llvm::ArrayRef<StringRef> Components) {
43aa981c18SIlya Biryukov   llvm::SmallString<128> P;
44aa981c18SIlya Biryukov   for (StringRef C : Components)
45aa981c18SIlya Biryukov     llvm::sys::path::append(P, C);
46509e21a1SJonas Devlieghere   return std::string(P);
47aa981c18SIlya Biryukov }
48aa981c18SIlya Biryukov 
49aa981c18SIlya Biryukov class SanitizerArgsTest : public ::testing::Test {
50aa981c18SIlya Biryukov protected:
emulateSingleCompilation(std::vector<std::string> ExtraArgs,std::vector<std::string> ExtraFiles)51aa981c18SIlya Biryukov   const Command &emulateSingleCompilation(std::vector<std::string> ExtraArgs,
52aa981c18SIlya Biryukov                                           std::vector<std::string> ExtraFiles) {
532e298a6aSIlya Biryukov     assert(!DriverInstance && "Running twice is not allowed");
54aa981c18SIlya Biryukov 
55aa981c18SIlya Biryukov     llvm::IntrusiveRefCntPtr<DiagnosticOptions> Opts = new DiagnosticOptions;
56aa981c18SIlya Biryukov     DiagnosticsEngine Diags(
57aa981c18SIlya Biryukov         new DiagnosticIDs, Opts,
58aa981c18SIlya Biryukov         new TextDiagnosticPrinter(llvm::errs(), Opts.get()));
592e298a6aSIlya Biryukov     DriverInstance.emplace(ClangBinary, "x86_64-unknown-linux-gnu", Diags,
60257b2971SCaroline Concatto                            "clang LLVM compiler", prepareFS(ExtraFiles));
61aa981c18SIlya Biryukov 
62aa981c18SIlya Biryukov     std::vector<const char *> Args = {ClangBinary};
63aa981c18SIlya Biryukov     for (const auto &A : ExtraArgs)
64aa981c18SIlya Biryukov       Args.push_back(A.c_str());
65aa981c18SIlya Biryukov     Args.push_back("-c");
66aa981c18SIlya Biryukov     Args.push_back(InputFile);
67aa981c18SIlya Biryukov 
682e298a6aSIlya Biryukov     CompilationJob.reset(DriverInstance->BuildCompilation(Args));
69aa981c18SIlya Biryukov 
70aa981c18SIlya Biryukov     if (Diags.hasErrorOccurred())
71aa981c18SIlya Biryukov       ADD_FAILURE() << "Error occurred while parsing compilation arguments. "
72aa981c18SIlya Biryukov                        "See stderr for details.";
73aa981c18SIlya Biryukov 
742e298a6aSIlya Biryukov     const auto &Commands = CompilationJob->getJobs().getJobs();
75aa981c18SIlya Biryukov     assert(Commands.size() == 1);
76aa981c18SIlya Biryukov     return *Commands.front();
77aa981c18SIlya Biryukov   }
78aa981c18SIlya Biryukov 
79aa981c18SIlya Biryukov private:
80aa981c18SIlya Biryukov   llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem>
prepareFS(llvm::ArrayRef<std::string> ExtraFiles)81aa981c18SIlya Biryukov   prepareFS(llvm::ArrayRef<std::string> ExtraFiles) {
82aa981c18SIlya Biryukov     llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> FS =
83aa981c18SIlya Biryukov         new llvm::vfs::InMemoryFileSystem;
84aa981c18SIlya Biryukov     FS->addFile(ClangBinary, time_t(), llvm::MemoryBuffer::getMemBuffer(""));
85aa981c18SIlya Biryukov     FS->addFile(InputFile, time_t(), llvm::MemoryBuffer::getMemBuffer(""));
86aa981c18SIlya Biryukov     for (llvm::StringRef F : ExtraFiles)
87aa981c18SIlya Biryukov       FS->addFile(F, time_t(), llvm::MemoryBuffer::getMemBuffer(""));
88aa981c18SIlya Biryukov     return FS;
89aa981c18SIlya Biryukov   }
90aa981c18SIlya Biryukov 
916ad0788cSKazu Hirata   std::optional<Driver> DriverInstance;
922e298a6aSIlya Biryukov   std::unique_ptr<driver::Compilation> CompilationJob;
93aa981c18SIlya Biryukov };
94aa981c18SIlya Biryukov 
TEST_F(SanitizerArgsTest,Ignorelists)95d7ec48d7SNico Weber TEST_F(SanitizerArgsTest, Ignorelists) {
96aa981c18SIlya Biryukov   const std::string ResourceDir = "/opt/llvm/lib/resources";
97d7ec48d7SNico Weber   const std::string UserIgnorelist = "/source/my_ignorelist.txt";
98d7ec48d7SNico Weber   const std::string ASanIgnorelist =
99d7ec48d7SNico Weber       concatPaths({ResourceDir, "share", "asan_ignorelist.txt"});
100aa981c18SIlya Biryukov 
101aa981c18SIlya Biryukov   auto &Command = emulateSingleCompilation(
102aa981c18SIlya Biryukov       /*ExtraArgs=*/{"-fsanitize=address", "-resource-dir", ResourceDir,
103d7ec48d7SNico Weber                      std::string("-fsanitize-ignorelist=") + UserIgnorelist},
104d7ec48d7SNico Weber       /*ExtraFiles=*/{ASanIgnorelist, UserIgnorelist});
105aa981c18SIlya Biryukov 
106d7ec48d7SNico Weber   // System ignorelists are added based on resource-dir.
107aa981c18SIlya Biryukov   EXPECT_THAT(Command.getArguments(),
108d7ec48d7SNico Weber               Contains(StrEq(std::string("-fsanitize-system-ignorelist=") +
109d7ec48d7SNico Weber                              ASanIgnorelist)));
110d7ec48d7SNico Weber   // User ignorelists should also be added.
111aa981c18SIlya Biryukov   EXPECT_THAT(
112aa981c18SIlya Biryukov       Command.getArguments(),
113d7ec48d7SNico Weber       Contains(StrEq(std::string("-fsanitize-ignorelist=") + UserIgnorelist)));
114aa981c18SIlya Biryukov }
115aa981c18SIlya Biryukov 
TEST_F(SanitizerArgsTest,XRayLists)116aa981c18SIlya Biryukov TEST_F(SanitizerArgsTest, XRayLists) {
117c379911aSZarko Todorovski   const std::string XRayAllowlist = "/source/xray_allowlist.txt";
118d7ec48d7SNico Weber   const std::string XRayIgnorelist = "/source/xray_ignorelist.txt";
119aa981c18SIlya Biryukov   const std::string XRayAttrList = "/source/xray_attr_list.txt";
120aa981c18SIlya Biryukov 
121aa981c18SIlya Biryukov   auto &Command = emulateSingleCompilation(
122aa981c18SIlya Biryukov       /*ExtraArgs=*/
123aa981c18SIlya Biryukov       {
124aa981c18SIlya Biryukov           "-fxray-instrument",
125c379911aSZarko Todorovski           "-fxray-always-instrument=" + XRayAllowlist,
126d7ec48d7SNico Weber           "-fxray-never-instrument=" + XRayIgnorelist,
127aa981c18SIlya Biryukov           "-fxray-attr-list=" + XRayAttrList,
128aa981c18SIlya Biryukov       },
129c379911aSZarko Todorovski       /*ExtraFiles=*/{XRayAllowlist, XRayIgnorelist, XRayAttrList});
130aa981c18SIlya Biryukov 
131d7ec48d7SNico Weber   // Ignorelists exist in the filesystem, so they should be added to the
132aa981c18SIlya Biryukov   // compilation command, produced by the driver.
133aa981c18SIlya Biryukov   EXPECT_THAT(Command.getArguments(),
134c379911aSZarko Todorovski               Contains(StrEq("-fxray-always-instrument=" + XRayAllowlist)));
135aa981c18SIlya Biryukov   EXPECT_THAT(Command.getArguments(),
136d7ec48d7SNico Weber               Contains(StrEq("-fxray-never-instrument=" + XRayIgnorelist)));
137aa981c18SIlya Biryukov   EXPECT_THAT(Command.getArguments(),
138aa981c18SIlya Biryukov               Contains(StrEq("-fxray-attr-list=" + XRayAttrList)));
139aa981c18SIlya Biryukov }
140aa981c18SIlya Biryukov 
141aa981c18SIlya Biryukov } // namespace
142