diff options
author | Ilya Biryukov <ibiryukov@google.com> | 2019-11-21 11:32:17 +0100 |
---|---|---|
committer | Ilya Biryukov <ibiryukov@google.com> | 2019-11-21 11:56:09 +0100 |
commit | aa981c1802d7353c777e399f2568e5a0e12dea21 (patch) | |
tree | 988917b64870affe5a5259fa9232419f1fac0ece /clang/unittests/Driver/SanitizerArgsTest.cpp | |
parent | f65cfff605f2fd802fc337c6152474e3f3d22a1c (diff) | |
download | bcm5719-llvm-aa981c1802d7353c777e399f2568e5a0e12dea21.tar.gz bcm5719-llvm-aa981c1802d7353c777e399f2568e5a0e12dea21.zip |
Reland 9f3fdb0d7fab: [Driver] Use VFS to check if sanitizer blacklists exist
With updates to various LLVM tools that use SpecialCastList.
It was tempting to use RealFileSystem as the default, but that makes it
too easy to accidentally forget passing VFS in clang code.
Diffstat (limited to 'clang/unittests/Driver/SanitizerArgsTest.cpp')
-rw-r--r-- | clang/unittests/Driver/SanitizerArgsTest.cpp | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/clang/unittests/Driver/SanitizerArgsTest.cpp b/clang/unittests/Driver/SanitizerArgsTest.cpp new file mode 100644 index 00000000000..164bc68051f --- /dev/null +++ b/clang/unittests/Driver/SanitizerArgsTest.cpp @@ -0,0 +1,141 @@ +//===- unittests/Driver/SanitizerArgsTest.cpp -----------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/DiagnosticIDs.h" +#include "clang/Basic/DiagnosticOptions.h" +#include "clang/Driver/Compilation.h" +#include "clang/Driver/Driver.h" +#include "clang/Driver/Job.h" +#include "clang/Frontend/TextDiagnosticPrinter.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/VirtualFileSystem.h" +#include "llvm/Support/raw_ostream.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" +#include <cstdlib> +#include <memory> +#include <string> +using namespace clang; +using namespace clang::driver; + +using ::testing::Contains; +using ::testing::StrEq; + +namespace { + +static constexpr const char *ClangBinary = "clang"; +static constexpr const char *InputFile = "/sources/foo.c"; + +std::string concatPaths(llvm::ArrayRef<StringRef> Components) { + llvm::SmallString<128> P; + for (StringRef C : Components) + llvm::sys::path::append(P, C); + return P.str().str(); +} + +class SanitizerArgsTest : public ::testing::Test { +protected: + const Command &emulateSingleCompilation(std::vector<std::string> ExtraArgs, + std::vector<std::string> ExtraFiles) { + assert(!Driver && "Running twice is not allowed"); + + llvm::IntrusiveRefCntPtr<DiagnosticOptions> Opts = new DiagnosticOptions; + DiagnosticsEngine Diags( + new DiagnosticIDs, Opts, + new TextDiagnosticPrinter(llvm::errs(), Opts.get())); + Driver.emplace(ClangBinary, "x86_64-unknown-linux-gnu", Diags, + prepareFS(ExtraFiles)); + + std::vector<const char *> Args = {ClangBinary}; + for (const auto &A : ExtraArgs) + Args.push_back(A.c_str()); + Args.push_back("-c"); + Args.push_back(InputFile); + + Compilation.reset(Driver->BuildCompilation(Args)); + + if (Diags.hasErrorOccurred()) + ADD_FAILURE() << "Error occurred while parsing compilation arguments. " + "See stderr for details."; + + const auto &Commands = Compilation->getJobs().getJobs(); + assert(Commands.size() == 1); + return *Commands.front(); + } + +private: + llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> + prepareFS(llvm::ArrayRef<std::string> ExtraFiles) { + llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> FS = + new llvm::vfs::InMemoryFileSystem; + FS->addFile(ClangBinary, time_t(), llvm::MemoryBuffer::getMemBuffer("")); + FS->addFile(InputFile, time_t(), llvm::MemoryBuffer::getMemBuffer("")); + for (llvm::StringRef F : ExtraFiles) + FS->addFile(F, time_t(), llvm::MemoryBuffer::getMemBuffer("")); + return FS; + } + + llvm::Optional<Driver> Driver; + std::unique_ptr<driver::Compilation> Compilation; +}; + +TEST_F(SanitizerArgsTest, Blacklists) { + const std::string ResourceDir = "/opt/llvm/lib/resources"; + const std::string UserBlacklist = "/source/my_blacklist.txt"; + const std::string ASanBlacklist = + concatPaths({ResourceDir, "share", "asan_blacklist.txt"}); + + auto &Command = emulateSingleCompilation( + /*ExtraArgs=*/{"-fsanitize=address", "-resource-dir", ResourceDir, + std::string("-fsanitize-blacklist=") + UserBlacklist}, + /*ExtraFiles=*/{ASanBlacklist, UserBlacklist}); + + // System blacklists are added based on resource-dir. + EXPECT_THAT(Command.getArguments(), + Contains(StrEq(std::string("-fsanitize-system-blacklist=") + + ASanBlacklist))); + // User blacklists should also be added. + EXPECT_THAT( + Command.getArguments(), + Contains(StrEq(std::string("-fsanitize-blacklist=") + UserBlacklist))); +} + +TEST_F(SanitizerArgsTest, XRayLists) { + const std::string XRayWhitelist = "/source/xray_whitelist.txt"; + const std::string XRayBlacklist = "/source/xray_blacklist.txt"; + const std::string XRayAttrList = "/source/xray_attr_list.txt"; + + auto &Command = emulateSingleCompilation( + /*ExtraArgs=*/ + { + "-fxray-instrument", + "-fxray-always-instrument=" + XRayWhitelist, + "-fxray-never-instrument=" + XRayBlacklist, + "-fxray-attr-list=" + XRayAttrList, + }, + /*ExtraFiles=*/{XRayWhitelist, XRayBlacklist, XRayAttrList}); + + // Blacklists exist in the filesystem, so they should be added to the + // compilation command, produced by the driver. + EXPECT_THAT(Command.getArguments(), + Contains(StrEq("-fxray-always-instrument=" + XRayWhitelist))); + EXPECT_THAT(Command.getArguments(), + Contains(StrEq("-fxray-never-instrument=" + XRayBlacklist))); + EXPECT_THAT(Command.getArguments(), + Contains(StrEq("-fxray-attr-list=" + XRayAttrList))); +} + +} // namespace |