Add the -fsanitize-blacklist option for the sanitizers. (#2261)

Blacklisting is necessary for some druntime functions, and LLVM/Clang already provides just the right functionality.
This commit is contained in:
Johan Engelen 2017-08-09 23:21:33 +02:00 committed by GitHub
parent 36088a1b49
commit ec9ffe29f1
6 changed files with 104 additions and 1 deletions

View file

@ -15,8 +15,10 @@
#include "driver/cl_options_sanitizers.h"
#include "ddmd/errors.h"
#include "ddmd/dsymbol.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/SpecialCaseList.h"
namespace {
@ -28,6 +30,13 @@ cl::list<std::string> fSanitize(
"suspicious behavior."),
cl::value_desc("checks"));
cl::list<std::string> fSanitizeBlacklist(
"fsanitize-blacklist", cl::CommaSeparated,
cl::desc("Add <file> to the blacklist files for the sanitizers."),
cl::value_desc("file"));
std::unique_ptr<llvm::SpecialCaseList> sanitizerBlacklist;
#ifdef ENABLE_COVERAGE_SANITIZER
cl::list<std::string> fSanitizeCoverage(
"fsanitize-coverage", cl::CommaSeparated,
@ -149,6 +158,14 @@ void initializeSanitizerOptionsFromCmdline()
sancovOpts.CoverageType = llvm::SanitizerCoverageOptions::SCK_Edge;
}
#endif
if (isAnySanitizerEnabled() && !fSanitizeBlacklist.empty()) {
std::string loadError;
sanitizerBlacklist =
llvm::SpecialCaseList::create(fSanitizeBlacklist, loadError);
if (!sanitizerBlacklist)
error(Loc(), "-fsanitize-blacklist error: %s", loadError.c_str());
}
}
#ifdef ENABLE_COVERAGE_SANITIZER
@ -180,4 +197,9 @@ void outputSanitizerSettings(llvm::raw_ostream &hash_os) {
#endif
}
bool functionIsInSanitizerBlacklist(FuncDeclaration *funcDecl) {
return sanitizerBlacklist &&
sanitizerBlacklist->inSection("fun", mangleExact(funcDecl));
}
} // namespace opts

View file

@ -23,6 +23,7 @@
#define ENABLE_COVERAGE_SANITIZER
#endif
class FuncDeclaration;
namespace llvm {
class raw_ostream;
}
@ -54,6 +55,8 @@ llvm::SanitizerCoverageOptions getSanitizerCoverageOptions();
void outputSanitizerSettings(llvm::raw_ostream &hash_os);
bool functionIsInSanitizerBlacklist(FuncDeclaration *funcDecl);
} // namespace opts
#endif // LDC_DRIVER_CL_OPTIONS_SANITIZERS_H

View file

@ -954,7 +954,8 @@ void DtoDefineFunction(FuncDeclaration *fd, bool linkageAvailableExternally) {
if (gABI->needsUnwindTables()) {
func->addFnAttr(LLAttribute::UWTable);
}
if (opts::isAnySanitizerEnabled()) {
if (opts::isAnySanitizerEnabled() &&
!opts::functionIsInSanitizerBlacklist(fd)) {
// Set the required sanitizer attribute.
if (opts::isSanitizerEnabled(opts::AddressSanitizer)) {
func->addFnAttr(LLAttribute::SanitizeAddress);

View file

@ -0,0 +1,63 @@
// Test sanitizer blacklist functionality
// RUN: %ldc -c -output-ll -fsanitize=address \
// RUN: -fsanitize-blacklist=%S/inputs/fsanitize_blacklist.txt \
// RUN: -fsanitize-blacklist=%S/inputs/fsanitize_blacklist2.txt \
// RUN: -of=%t.ll %s && FileCheck %s < %t.ll
// Don't attempt to load the blacklist when no sanitizer is active
// RUN: %ldc -o- -fsanitize-blacklist=%S/thisfilecertainlydoesnotexist %s
// CHECK-LABEL: define {{.*}}9foofoofoo
// CHECK-SAME: #[[ATTR_WITHASAN:[0-9]+]]
void foofoofoo(int* i)
{
// CHECK: call {{.*}}_asan
*i = 1;
}
// CHECK-LABEL: define {{.*}}blacklisted
// CHECK-SAME: #[[ATTR_NOASAN:[0-9]+]]
extern (C) void blacklisted(int* i)
{
// CHECK-NOT: call {{.*}}_asan
*i = 1;
}
// Test blacklisted wildcard
// CHECK-LABEL: define {{.*}}10black_set1
// CHECK-SAME: #[[ATTR_NOASAN:[0-9]+]]
void black_set1(int* i)
{
// CHECK-NOT: call {{.*}}_asan
*i = 1;
}
// CHECK-LABEL: define {{.*}}10black_set2
// CHECK-SAME: #[[ATTR_NOASAN:[0-9]+]]
void black_set2(int* i)
{
// CHECK-NOT: call {{.*}}_asan
*i = 1;
}
// Test blacklisting of template class methods
class ABCDEF(T)
{
void method(int* i)
{
*i = 1;
}
}
// CHECK-LABEL: define {{.*}}TiZ6ABCDEF6method
// CHECK-SAME: #[[ATTR_NOASAN:[0-9]+]]
ABCDEF!int ofBlacklistedType;
// CHECK-LABEL: define {{.*}}TAyaZ6ABCDEF6method
// CHECK-SAME: #[[ATTR_WITHASAN:[0-9]+]]
ABCDEF!string ofInstrumentedType;
//CHECK: attributes #[[ATTR_WITHASAN]] ={{.*}}sanitize_address
//CHECK: attributes #[[ATTR_NOASAN]]
//CHECK-NOT: sanitize_address
//CHECK-SAME: }

View file

@ -0,0 +1,13 @@
# Blacklist for the sanitizers. Turns off instrumentation of particular
# functions or sources. Use with care. You may set location of blacklist
# at compile-time using -fsanitize-blacklist=<path> flag.
# Example usage:
# fun:*bad_function_name*
# src:file_with_tricky_code.cc
# global:*global_with_bad_access_or_initialization*
# global:*global_with_initialization_issues*=init
# type:*Namespace::ClassName*=init
fun:blacklisted
fun:*black_set*

View file

@ -0,0 +1 @@
fun:_D*TiZ6ABCDEF6method*