Skip to content

Commit 82e1d79

Browse files
Merge pull request #330 from jkorous-apple/sanitizer-blacklist
Sanitizer blacklist
2 parents 36daa2c + e7d3e4e commit 82e1d79

File tree

15 files changed

+138
-33
lines changed

15 files changed

+138
-33
lines changed

clang/include/clang/Basic/SanitizerSpecialCaseList.h

+5-2
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,20 @@
1717
#include "clang/Basic/Sanitizers.h"
1818
#include "llvm/ADT/StringRef.h"
1919
#include "llvm/Support/SpecialCaseList.h"
20+
#include "llvm/Support/VirtualFileSystem.h"
2021
#include <memory>
2122

2223
namespace clang {
2324

2425
class SanitizerSpecialCaseList : public llvm::SpecialCaseList {
2526
public:
2627
static std::unique_ptr<SanitizerSpecialCaseList>
27-
create(const std::vector<std::string> &Paths, std::string &Error);
28+
create(const std::vector<std::string> &Paths, llvm::vfs::FileSystem &VFS,
29+
std::string &Error);
2830

2931
static std::unique_ptr<SanitizerSpecialCaseList>
30-
createOrDie(const std::vector<std::string> &Paths);
32+
createOrDie(const std::vector<std::string> &Paths,
33+
llvm::vfs::FileSystem &VFS);
3134

3235
// Query blacklisted entries if any bit in Mask matches the entry's section.
3336
bool inSection(SanitizerMask Mask, StringRef Prefix, StringRef Query,

clang/include/clang/Driver/Options.td

+3
Original file line numberDiff line numberDiff line change
@@ -978,6 +978,9 @@ def fno_sanitize_EQ : CommaJoined<["-"], "fno-sanitize=">, Group<f_clang_Group>,
978978
def fsanitize_blacklist : Joined<["-"], "fsanitize-blacklist=">,
979979
Group<f_clang_Group>,
980980
HelpText<"Path to blacklist file for sanitizers">;
981+
def fsanitize_system_blacklist : Joined<["-"], "fsanitize-system-blacklist=">,
982+
HelpText<"Path to system blacklist file for sanitizers">,
983+
Flags<[CC1Option]>;
981984
def fno_sanitize_blacklist : Flag<["-"], "fno-sanitize-blacklist">,
982985
Group<f_clang_Group>,
983986
HelpText<"Don't use blacklist file for sanitizers">;

clang/include/clang/Driver/SanitizerArgs.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ class SanitizerArgs {
2525
SanitizerSet RecoverableSanitizers;
2626
SanitizerSet TrapSanitizers;
2727

28-
std::vector<std::string> BlacklistFiles;
29-
std::vector<std::string> ExtraDeps;
28+
std::vector<std::string> UserBlacklistFiles;
29+
std::vector<std::string> SystemBlacklistFiles;
3030
int CoverageFeatures = 0;
3131
int MsanTrackOrigins = 0;
3232
bool MsanUseAfterDtor = true;

clang/lib/Basic/SanitizerBlacklist.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ using namespace clang;
1616

1717
SanitizerBlacklist::SanitizerBlacklist(
1818
const std::vector<std::string> &BlacklistPaths, SourceManager &SM)
19-
: SSCL(SanitizerSpecialCaseList::createOrDie(BlacklistPaths)), SM(SM) {}
19+
: SSCL(SanitizerSpecialCaseList::createOrDie(
20+
BlacklistPaths, SM.getFileManager().getVirtualFileSystem())),
21+
SM(SM) {}
2022

2123
bool SanitizerBlacklist::isBlacklistedGlobal(SanitizerMask Mask,
2224
StringRef GlobalName,

clang/lib/Basic/SanitizerSpecialCaseList.cpp

+5-3
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,22 @@ using namespace clang;
1616

1717
std::unique_ptr<SanitizerSpecialCaseList>
1818
SanitizerSpecialCaseList::create(const std::vector<std::string> &Paths,
19+
llvm::vfs::FileSystem &VFS,
1920
std::string &Error) {
2021
std::unique_ptr<clang::SanitizerSpecialCaseList> SSCL(
2122
new SanitizerSpecialCaseList());
22-
if (SSCL->createInternal(Paths, Error)) {
23+
if (SSCL->createInternal(Paths, Error, VFS)) {
2324
SSCL->createSanitizerSections();
2425
return SSCL;
2526
}
2627
return nullptr;
2728
}
2829

2930
std::unique_ptr<SanitizerSpecialCaseList>
30-
SanitizerSpecialCaseList::createOrDie(const std::vector<std::string> &Paths) {
31+
SanitizerSpecialCaseList::createOrDie(const std::vector<std::string> &Paths,
32+
llvm::vfs::FileSystem &VFS) {
3133
std::string Error;
32-
if (auto SSCL = create(Paths, Error))
34+
if (auto SSCL = create(Paths, VFS, Error))
3335
return SSCL;
3436
llvm::report_fatal_error(Error);
3537
}

clang/lib/Driver/SanitizerArgs.cpp

+17-11
Original file line numberDiff line numberDiff line change
@@ -547,29 +547,35 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
547547

548548
// Setup blacklist files.
549549
// Add default blacklist from resource directory.
550-
addDefaultBlacklists(D, Kinds, BlacklistFiles);
550+
addDefaultBlacklists(D, Kinds, SystemBlacklistFiles);
551551
// Parse -f(no-)sanitize-blacklist options.
552552
for (const auto *Arg : Args) {
553553
if (Arg->getOption().matches(options::OPT_fsanitize_blacklist)) {
554554
Arg->claim();
555555
std::string BLPath = Arg->getValue();
556556
if (llvm::sys::fs::exists(BLPath)) {
557-
BlacklistFiles.push_back(BLPath);
558-
ExtraDeps.push_back(BLPath);
557+
UserBlacklistFiles.push_back(BLPath);
559558
} else {
560559
D.Diag(clang::diag::err_drv_no_such_file) << BLPath;
561560
}
562561
} else if (Arg->getOption().matches(options::OPT_fno_sanitize_blacklist)) {
563562
Arg->claim();
564-
BlacklistFiles.clear();
565-
ExtraDeps.clear();
563+
UserBlacklistFiles.clear();
564+
SystemBlacklistFiles.clear();
566565
}
567566
}
568567
// Validate blacklists format.
569568
{
570569
std::string BLError;
571570
std::unique_ptr<llvm::SpecialCaseList> SCL(
572-
llvm::SpecialCaseList::create(BlacklistFiles, BLError));
571+
llvm::SpecialCaseList::create(UserBlacklistFiles, BLError));
572+
if (!SCL.get())
573+
D.Diag(clang::diag::err_drv_malformed_sanitizer_blacklist) << BLError;
574+
}
575+
{
576+
std::string BLError;
577+
std::unique_ptr<llvm::SpecialCaseList> SCL(
578+
llvm::SpecialCaseList::create(SystemBlacklistFiles, BLError));
573579
if (!SCL.get())
574580
D.Diag(clang::diag::err_drv_malformed_sanitizer_blacklist) << BLError;
575581
}
@@ -920,15 +926,15 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
920926
CmdArgs.push_back(
921927
Args.MakeArgString("-fsanitize-trap=" + toString(TrapSanitizers)));
922928

923-
for (const auto &BLPath : BlacklistFiles) {
929+
for (const auto &BLPath : UserBlacklistFiles) {
924930
SmallString<64> BlacklistOpt("-fsanitize-blacklist=");
925931
BlacklistOpt += BLPath;
926932
CmdArgs.push_back(Args.MakeArgString(BlacklistOpt));
927933
}
928-
for (const auto &Dep : ExtraDeps) {
929-
SmallString<64> ExtraDepOpt("-fdepfile-entry=");
930-
ExtraDepOpt += Dep;
931-
CmdArgs.push_back(Args.MakeArgString(ExtraDepOpt));
934+
for (const auto &BLPath : SystemBlacklistFiles) {
935+
SmallString<64> BlacklistOpt("-fsanitize-system-blacklist=");
936+
BlacklistOpt += BLPath;
937+
CmdArgs.push_back(Args.MakeArgString(BlacklistOpt));
932938
}
933939

934940
if (MsanTrackOrigins)

clang/lib/Frontend/CompilerInvocation.cpp

+25-1
Original file line numberDiff line numberDiff line change
@@ -1452,7 +1452,26 @@ static void ParseDependencyOutputArgs(DependencyOutputOptions &Opts,
14521452
// Add sanitizer blacklists as extra dependencies.
14531453
// They won't be discovered by the regular preprocessor, so
14541454
// we let make / ninja to know about this implicit dependency.
1455-
Opts.ExtraDeps = Args.getAllArgValues(OPT_fdepfile_entry);
1455+
if (!Args.hasArg(OPT_fno_sanitize_blacklist)) {
1456+
for (const auto *A : Args.filtered(OPT_fsanitize_blacklist)) {
1457+
StringRef Val = A->getValue();
1458+
if (Val.find('=') == StringRef::npos)
1459+
Opts.ExtraDeps.push_back(Val);
1460+
}
1461+
if (Opts.IncludeSystemHeaders) {
1462+
for (const auto *A : Args.filtered(OPT_fsanitize_system_blacklist)) {
1463+
StringRef Val = A->getValue();
1464+
if (Val.find('=') == StringRef::npos)
1465+
Opts.ExtraDeps.push_back(Val);
1466+
}
1467+
}
1468+
}
1469+
1470+
// Propagate the extra dependencies.
1471+
for (const auto *A : Args.filtered(OPT_fdepfile_entry)) {
1472+
Opts.ExtraDeps.push_back(A->getValue());
1473+
}
1474+
14561475
// Only the -fmodule-file=<file> form.
14571476
for (const auto *A : Args.filtered(OPT_fmodule_file)) {
14581477
StringRef Val = A->getValue();
@@ -3110,6 +3129,11 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
31103129
Opts.SanitizeAddressFieldPadding =
31113130
getLastArgIntValue(Args, OPT_fsanitize_address_field_padding, 0, Diags);
31123131
Opts.SanitizerBlacklistFiles = Args.getAllArgValues(OPT_fsanitize_blacklist);
3132+
std::vector<std::string> systemBlacklists =
3133+
Args.getAllArgValues(OPT_fsanitize_system_blacklist);
3134+
Opts.SanitizerBlacklistFiles.insert(Opts.SanitizerBlacklistFiles.end(),
3135+
systemBlacklists.begin(),
3136+
systemBlacklists.end());
31133137

31143138
// -fxray-instrument
31153139
Opts.XRayInstrument =
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
'version': 0,
3+
'roots': [
4+
{ 'name': '@DIR@', 'type': 'directory',
5+
'contents': [
6+
{ 'name': 'only-virtual-file.blacklist', 'type': 'file',
7+
'external-contents': '@REAL_FILE@'
8+
},
9+
{ 'name': 'invalid-virtual-file.blacklist', 'type': 'file',
10+
'external-contents': '@NONEXISTENT_FILE@'
11+
}
12+
]
13+
}
14+
]
15+
}
+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Verify ubsan doesn't emit checks for blacklisted functions and files
2+
// RUN: echo "fun:hash" > %t-func.blacklist
3+
// RUN: echo "src:%s" | sed -e 's/\\/\\\\/g' > %t-file.blacklist
4+
5+
// RUN: rm -f %t-vfsoverlay.yaml
6+
// RUN: rm -f %t-nonexistent.blacklist
7+
// RUN: sed -e "s|@DIR@|%/T|g" %S/Inputs/sanitizer-blacklist-vfsoverlay.yaml | sed -e "s|@REAL_FILE@|%/t-func.blacklist|g" | sed -e "s|@NONEXISTENT_FILE@|%/t-nonexistent.blacklist|g" > %t-vfsoverlay.yaml
8+
// RUN: %clang_cc1 -fsanitize=unsigned-integer-overflow -ivfsoverlay %t-vfsoverlay.yaml -fsanitize-blacklist=%/T/only-virtual-file.blacklist -emit-llvm %s -o - | FileCheck %s --check-prefix=FUNC
9+
10+
// RUN: not %clang_cc1 -fsanitize=unsigned-integer-overflow -ivfsoverlay %t-vfsoverlay.yaml -fsanitize-blacklist=%/T/invalid-virtual-file.blacklist -emit-llvm %s -o - 2>&1 | FileCheck %s --check-prefix=INVALID-MAPPED-FILE
11+
// INVALID-MAPPED-FILE: invalid-virtual-file.blacklist': {{[Nn]}}o such file or directory
12+
13+
// RUN: not %clang_cc1 -fsanitize=unsigned-integer-overflow -ivfsoverlay %t-vfsoverlay.yaml -fsanitize-blacklist=%t-nonexistent.blacklist -emit-llvm %s -o - 2>&1 | FileCheck %s --check-prefix=INVALID
14+
// INVALID: nonexistent.blacklist': {{[Nn]}}o such file or directory
15+
16+
unsigned i;
17+
18+
// DEFAULT: @hash
19+
// FUNC: @hash
20+
// FILE: @hash
21+
unsigned hash() {
22+
// DEFAULT: call {{.*}}void @__ubsan
23+
// FUNC-NOT: call {{.*}}void @__ubsan
24+
// FILE-NOT: call {{.*}}void @__ubsan
25+
return i * 37;
26+
}
27+
28+
// DEFAULT: @add
29+
// FUNC: @add
30+
// FILE: @add
31+
unsigned add() {
32+
// DEFAULT: call {{.*}}void @__ubsan
33+
// FUNC: call {{.*}}void @__ubsan
34+
// FILE-NOT: call {{.*}}void @__ubsan
35+
return i + 1;
36+
}

clang/test/Driver/fsanitize-blacklist.c

+3-7
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,17 @@
1616
// RUN: %clang -target aarch64-linux-gnu -fsanitize=hwaddress -fsanitize-blacklist=%t.good -fsanitize-blacklist=%t.second %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-BLACKLIST
1717
// CHECK-BLACKLIST: -fsanitize-blacklist={{.*}}.good" "-fsanitize-blacklist={{.*}}.second
1818

19-
// Now, check for -fdepfile-entry flags.
20-
// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-blacklist=%t.good -fsanitize-blacklist=%t.second %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-BLACKLIST2
21-
// CHECK-BLACKLIST2: -fdepfile-entry={{.*}}.good" "-fdepfile-entry={{.*}}.second
22-
2319
// Check that the default blacklist is not added as an extra dependency.
2420
// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -resource-dir=%S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-DEFAULT-BLACKLIST-ASAN --implicit-check-not=fdepfile-entry --implicit-check-not=-fsanitize-blacklist=
25-
// CHECK-DEFAULT-BLACKLIST-ASAN: -fsanitize-blacklist={{.*[^w]}}asan_blacklist.txt
21+
// CHECK-DEFAULT-BLACKLIST-ASAN: -fsanitize-system-blacklist={{.*[^w]}}asan_blacklist.txt
2622
// RUN: %clang -target x86_64-linux-gnu -fsanitize=hwaddress -resource-dir=%S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-DEFAULT-BLACKLIST-HWASAN --implicit-check-not=fdepfile-entry --implicit-check-not=-fsanitize-blacklist=
27-
// CHECK-DEFAULT-BLACKLIST-HWASAN: -fsanitize-blacklist={{.*}}hwasan_blacklist.txt
23+
// CHECK-DEFAULT-BLACKLIST-HWASAN: -fsanitize-system-blacklist={{.*}}hwasan_blacklist.txt
2824

2925
// RUN: %clang -target x86_64-linux-gnu -fsanitize=integer -resource-dir=%S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-DEFAULT-UBSAN-BLACKLIST --implicit-check-not=fdepfile-entry --implicit-check-not=-fsanitize-blacklist=
3026
// RUN: %clang -target x86_64-linux-gnu -fsanitize=nullability -resource-dir=%S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-DEFAULT-UBSAN-BLACKLIST --implicit-check-not=fdepfile-entry --implicit-check-not=-fsanitize-blacklist=
3127
// RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined -resource-dir=%S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-DEFAULT-UBSAN-BLACKLIST --implicit-check-not=fdepfile-entry --implicit-check-not=-fsanitize-blacklist=
3228
// RUN: %clang -target x86_64-linux-gnu -fsanitize=alignment -resource-dir=%S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-DEFAULT-UBSAN-BLACKLIST --implicit-check-not=fdepfile-entry --implicit-check-not=-fsanitize-blacklist=
33-
// CHECK-DEFAULT-UBSAN-BLACKLIST: -fsanitize-blacklist={{.*}}ubsan_blacklist.txt
29+
// CHECK-DEFAULT-UBSAN-BLACKLIST: -fsanitize-system-blacklist={{.*}}ubsan_blacklist.txt
3430

3531
// Check that combining ubsan and another sanitizer results in both blacklists being used.
3632
// RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined,address -resource-dir=%S/Inputs/resource_dir %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-DEFAULT-UBSAN-BLACKLIST --check-prefix=CHECK-DEFAULT-ASAN-BLACKLIST --implicit-check-not=fdepfile-entry --implicit-check-not=-fsanitize-blacklist=

clang/test/Frontend/dependency-gen.c

+17
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,20 @@
2727
#ifndef INCLUDE_FLAG_TEST
2828
#include <x.h>
2929
#endif
30+
31+
// RUN: echo "fun:foo" > %t.blacklist1
32+
// RUN: echo "fun:foo" > %t.blacklist2
33+
// RUN: %clang -MD -MF - %s -fsyntax-only -resource-dir=%S/Inputs/resource_dir_with_cfi_blacklist -fsanitize=cfi-vcall -flto -fvisibility=hidden -fsanitize-blacklist=%t.blacklist1 -fsanitize-blacklist=%t.blacklist2 -I ./ | FileCheck -check-prefix=TWO-BLACK-LISTS %s
34+
// TWO-BLACK-LISTS: dependency-gen.o:
35+
// TWO-BLACK-LISTS-DAG: blacklist1
36+
// TWO-BLACK-LISTS-DAG: blacklist2
37+
// TWO-BLACK-LISTS-DAG: x.h
38+
// TWO-BLACK-LISTS-DAG: dependency-gen.c
39+
40+
// RUN: %clang -MD -MF - %s -fsyntax-only -resource-dir=%S/Inputs/resource_dir_with_cfi_blacklist -fsanitize=cfi-vcall -flto -fvisibility=hidden -I ./ | FileCheck -check-prefix=USER-AND-SYS-DEPS %s
41+
// USER-AND-SYS-DEPS: dependency-gen.o:
42+
// USER-AND-SYS-DEPS-DAG: cfi_blacklist.txt
43+
44+
// RUN: %clang -MMD -MF - %s -fsyntax-only -resource-dir=%S/Inputs/resource_dir_with_cfi_blacklist -fsanitize=cfi-vcall -flto -fvisibility=hidden -I ./ | FileCheck -check-prefix=ONLY-USER-DEPS %s
45+
// ONLY-USER-DEPS: dependency-gen.o:
46+
// NOT-ONLY-USER-DEPS: cfi_blacklist.txt

compiler-rt/test/asan/TestCases/default_blacklist.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@
44
//
55
// Test that ASan uses the default blacklist from resource directory.
66
// RUN: %clangxx_asan -### %s 2>&1 | FileCheck %s
7-
// CHECK: fsanitize-blacklist={{.*}}asan_blacklist.txt
7+
// CHECK: fsanitize-system-blacklist={{.*}}asan_blacklist.txt
+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
// Test that MSan uses the default blacklist from resource directory.
22
// RUN: %clangxx_msan -### %s 2>&1 | FileCheck %s
3-
// CHECK: fsanitize-blacklist={{.*}}msan_blacklist.txt
3+
// CHECK: fsanitize-system-blacklist={{.*}}msan_blacklist.txt

llvm/include/llvm/Support/SpecialCaseList.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
#include "llvm/ADT/StringSet.h"
5656
#include "llvm/Support/Regex.h"
5757
#include "llvm/Support/TrigramIndex.h"
58+
#include "llvm/Support/VirtualFileSystem.h"
5859
#include <string>
5960
#include <vector>
6061

@@ -102,8 +103,8 @@ class SpecialCaseList {
102103
protected:
103104
// Implementations of the create*() functions that can also be used by derived
104105
// classes.
105-
bool createInternal(const std::vector<std::string> &Paths,
106-
std::string &Error);
106+
bool createInternal(const std::vector<std::string> &Paths, std::string &Error,
107+
vfs::FileSystem &VFS = *vfs::getRealFileSystem());
107108
bool createInternal(const MemoryBuffer *MB, std::string &Error);
108109

109110
SpecialCaseList() = default;

llvm/lib/Support/SpecialCaseList.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -95,11 +95,11 @@ SpecialCaseList::createOrDie(const std::vector<std::string> &Paths) {
9595
}
9696

9797
bool SpecialCaseList::createInternal(const std::vector<std::string> &Paths,
98-
std::string &Error) {
98+
std::string &Error, vfs::FileSystem &VFS) {
9999
StringMap<size_t> Sections;
100100
for (const auto &Path : Paths) {
101101
ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
102-
MemoryBuffer::getFile(Path);
102+
VFS.getBufferForFile(Path);
103103
if (std::error_code EC = FileOrErr.getError()) {
104104
Error = (Twine("can't open file '") + Path + "': " + EC.message()).str();
105105
return false;

0 commit comments

Comments
 (0)