From: Alexey Samsonov Date: Mon, 3 Dec 2012 19:12:58 +0000 (+0000) Subject: Add Clang flags -fsanitize-blacklist and -fno-sanitize-blacklist. Make this flag... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=91ecfa6af51836d3ccc90beddab1193b0c060739;p=clang Add Clang flags -fsanitize-blacklist and -fno-sanitize-blacklist. Make this flag usable for ASan. Blacklisting can be used to disable sanitizer checks for particular file/function/object. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@169144 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index 8e31cab356..7cd550e42f 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -391,6 +391,12 @@ def fsanitize_EQ : CommaJoined<["-"], "fsanitize=">, Group, "address (memory errors) | thread (race detection) | " "undefined (miscellaneous undefined behavior)">; def fno_sanitize_EQ : CommaJoined<["-"], "fno-sanitize=">, Group; +def fsanitize_blacklist : Joined<["-"], "fsanitize-blacklist=">, + Group, Flags<[CC1Option]>, + HelpText<"Path to blacklist file for sanitizers">; +def fno_sanitize_blacklist : Flag<["-"], "fno-sanitize-blacklist">, + Group, + HelpText<"Don't use blacklist file for sanitizers">; def funsafe_math_optimizations : Flag<["-"], "funsafe-math-optimizations">, Group; def fno_unsafe_math_optimizations : Flag<["-"], "fno-unsafe-math-optimizations">, diff --git a/include/clang/Frontend/CodeGenOptions.h b/include/clang/Frontend/CodeGenOptions.h index 81b8e0d7a8..7038c397cb 100644 --- a/include/clang/Frontend/CodeGenOptions.h +++ b/include/clang/Frontend/CodeGenOptions.h @@ -105,6 +105,9 @@ public: /// The name of the relocation model to use. std::string RelocationModel; + /// Path to blacklist file for sanitizers. + std::string SanitizerBlacklistFile; + /// If not an empty string, trap intrinsics are lowered to calls to this /// function instead of to trap instructions. std::string TrapFuncName; diff --git a/lib/CodeGen/BackendUtil.cpp b/lib/CodeGen/BackendUtil.cpp index 4fe1c80e48..414f65ecf3 100644 --- a/lib/CodeGen/BackendUtil.cpp +++ b/lib/CodeGen/BackendUtil.cpp @@ -139,10 +139,13 @@ public: // we add to the PassManagerBuilder. class PassManagerBuilderWrapper : public PassManagerBuilder { public: - PassManagerBuilderWrapper(const LangOptions &LangOpts) - : PassManagerBuilder(), LangOpts(LangOpts) {} + PassManagerBuilderWrapper(const CodeGenOptions &CGOpts, + const LangOptions &LangOpts) + : PassManagerBuilder(), CGOpts(CGOpts), LangOpts(LangOpts) {} + const CodeGenOptions &getCGOpts() const { return CGOpts; } const LangOptions &getLangOpts() const { return LangOpts; } private: + const CodeGenOptions &CGOpts; const LangOptions &LangOpts; }; @@ -172,11 +175,14 @@ static void addAddressSanitizerPasses(const PassManagerBuilder &Builder, PassManagerBase &PM) { const PassManagerBuilderWrapper &BuilderWrapper = static_cast(Builder); + const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts(); const LangOptions &LangOpts = BuilderWrapper.getLangOpts(); PM.add(createAddressSanitizerFunctionPass(LangOpts.SanitizeInitOrder, LangOpts.SanitizeUseAfterReturn, - LangOpts.SanitizeUseAfterScope)); - PM.add(createAddressSanitizerModulePass(LangOpts.SanitizeInitOrder)); + LangOpts.SanitizeUseAfterScope, + CGOpts.SanitizerBlacklistFile)); + PM.add(createAddressSanitizerModulePass(LangOpts.SanitizeInitOrder, + CGOpts.SanitizerBlacklistFile)); } static void addMemorySanitizerPass(const PassManagerBuilder &Builder, @@ -200,7 +206,7 @@ void EmitAssemblyHelper::CreatePasses(TargetMachine *TM) { Inlining = CodeGenOpts.NoInlining; } - PassManagerBuilderWrapper PMBuilder(LangOpts); + PassManagerBuilderWrapper PMBuilder(CodeGenOpts, LangOpts); PMBuilder.OptLevel = OptLevel; PMBuilder.SizeLevel = CodeGenOpts.OptimizeSize; diff --git a/lib/Driver/SanitizerArgs.h b/lib/Driver/SanitizerArgs.h index c7d1ea68dd..71813c5511 100644 --- a/lib/Driver/SanitizerArgs.h +++ b/lib/Driver/SanitizerArgs.h @@ -34,9 +34,10 @@ class SanitizerArgs { NeedsUbsanRt = (Undefined & ~Bounds) | Integer }; unsigned Kind; + std::string BlacklistFile; public: - SanitizerArgs() : Kind(0) {} + SanitizerArgs() : Kind(0), BlacklistFile("") {} /// Parses the sanitizer arguments from an argument list. SanitizerArgs(const Driver &D, const ArgList &Args); @@ -57,6 +58,11 @@ class SanitizerArgs { #include "clang/Basic/Sanitizers.def" SanitizeOpt.pop_back(); CmdArgs.push_back(Args.MakeArgString(SanitizeOpt)); + if (!BlacklistFile.empty()) { + llvm::SmallString<64> BlacklistOpt("-fsanitize-blacklist="); + BlacklistOpt += BlacklistFile; + CmdArgs.push_back(Args.MakeArgString(BlacklistOpt)); + } } private: diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index 92c96b25c9..e93fa108d9 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -1486,6 +1486,19 @@ SanitizerArgs::SanitizerArgs(const Driver &D, const ArgList &Args) { D.Diag(diag::err_drv_argument_only_allowed_with) << lastArgumentForKind(D, Args, NeedsAsanRt) << "-fsanitize=address"; + + // Parse -f(no-)sanitize-blacklist options. + if (Arg *BLArg = Args.getLastArg(options::OPT_fsanitize_blacklist, + options::OPT_fno_sanitize_blacklist)) { + if (BLArg->getOption().matches(options::OPT_fsanitize_blacklist)) { + std::string BLPath = BLArg->getValue(); + bool BLExists = false; + if (!llvm::sys::fs::exists(BLPath, BLExists) && BLExists) + BlacklistFile = BLPath; + else + D.Diag(diag::err_drv_no_such_file) << BLPath; + } + } } /// If AddressSanitizer is enabled, add appropriate linker flags (Linux). diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 9b10f85028..e17497503c 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -403,6 +403,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.CoverageFile = Args.getLastArgValue(OPT_coverage_file); Opts.DebugCompilationDir = Args.getLastArgValue(OPT_fdebug_compilation_dir); Opts.LinkBitcodeFile = Args.getLastArgValue(OPT_mlink_bitcode_file); + Opts.SanitizerBlacklistFile = Args.getLastArgValue(OPT_fsanitize_blacklist); Opts.SSPBufferSize = Args.getLastArgIntValue(OPT_stack_protector_buffer_size, 8, Diags); Opts.StackRealignment = Args.hasArg(OPT_mstackrealign); diff --git a/test/Driver/fsanitize-blacklist.c b/test/Driver/fsanitize-blacklist.c new file mode 100644 index 0000000000..56165228dc --- /dev/null +++ b/test/Driver/fsanitize-blacklist.c @@ -0,0 +1,15 @@ +// General blacklist usage. +// RUN: %clang -fsanitize=address -fsanitize-blacklist=%s %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-BLACKLIST +// CHECK-BLACKLIST: -fsanitize-blacklist + +// Ignore -fsanitize-blacklist flag if there is no -fsanitize flag. +// RUN: %clang -fsanitize-blacklist=%s %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-SANITIZE +// CHECK-NO-SANITIZE-NOT: -fsanitize-blacklist + +// Flag -fno-sanitize-blacklist wins if it is specified later. +// RUN: %clang -fsanitize=address -fsanitize-blacklist=%s -fno-sanitize-blacklist %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-BLACKLIST +// CHECK-NO-BLACKLIST-NOT: -fsanitize-blacklist + +// Driver barks on unexisting blacklist files. +// RUN: %clang -fno-sanitize-blacklist -fsanitize-blacklist=unexisting.txt %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-SUCH-FILE +// CHECK-NO-SUCH-FILE: error: no such file or directory: 'unexisting.txt'