[cfe-commits] [PATCH] Clang support for sanitizer blacklists.

Alexey Samsonov samsonov at google.com
Fri Nov 30 22:55:07 PST 2012


Hi rsmith,

This patch adds flags -fsanitize-blacklist=<path> and
-fno-sanitize-blacklist to Clang and makes this flag usable for
ASan. Blacklisting can be used to disable
sanitizer checks for particular source file/function/object.
It is implemented in backend instrumentation passes for
ASan/TSan/MSan, so for these passes we may just "implement"
this flag by properly configuring passes in frontend.
This patch depends on refactoring of ASan pass options that
will be sent for review shortly.

http://llvm-reviews.chandlerc.com/D152

Files:
  test/Driver/fsanitize-blacklist.c
  include/clang/Frontend/CodeGenOptions.h
  include/clang/Driver/Options.td
  lib/Frontend/CompilerInvocation.cpp
  lib/Driver/Tools.cpp
  lib/Driver/SanitizerArgs.h
  lib/CodeGen/BackendUtil.cpp

Index: test/Driver/fsanitize-blacklist.c
===================================================================
--- /dev/null
+++ 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'
Index: include/clang/Frontend/CodeGenOptions.h
===================================================================
--- include/clang/Frontend/CodeGenOptions.h
+++ include/clang/Frontend/CodeGenOptions.h
@@ -105,6 +105,9 @@
   /// 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;
Index: include/clang/Driver/Options.td
===================================================================
--- include/clang/Driver/Options.td
+++ include/clang/Driver/Options.td
@@ -391,6 +391,12 @@
                             "address (memory errors) | thread (race detection) | "
                             "undefined (miscellaneous undefined behavior)">;
 def fno_sanitize_EQ : CommaJoined<["-"], "fno-sanitize=">, Group<f_clang_Group>;
+def fsanitize_blacklist : Joined<["-"], "fsanitize-blacklist=">,
+                          Group<f_clang_Group>, Flags<[CC1Option]>,
+                          HelpText<"Path to blacklist file for sanitizers">;
+def fno_sanitize_blacklist : Flag<["-"], "fno-sanitize-blacklist">,
+                             Group<f_clang_Group>, Flags<[CC1Option]>,
+                             HelpText<"Don't use blacklist file for sanitizers">;
 def funsafe_math_optimizations : Flag<["-"], "funsafe-math-optimizations">,
   Group<f_Group>;
 def fno_unsafe_math_optimizations : Flag<["-"], "fno-unsafe-math-optimizations">,
Index: lib/Frontend/CompilerInvocation.cpp
===================================================================
--- lib/Frontend/CompilerInvocation.cpp
+++ lib/Frontend/CompilerInvocation.cpp
@@ -402,6 +402,7 @@
   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);
Index: lib/Driver/Tools.cpp
===================================================================
--- lib/Driver/Tools.cpp
+++ lib/Driver/Tools.cpp
@@ -1481,6 +1481,19 @@
     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).
Index: lib/Driver/SanitizerArgs.h
===================================================================
--- lib/Driver/SanitizerArgs.h
+++ lib/Driver/SanitizerArgs.h
@@ -33,9 +33,10 @@
     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);
 
@@ -55,6 +56,11 @@
 #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:
Index: lib/CodeGen/BackendUtil.cpp
===================================================================
--- lib/CodeGen/BackendUtil.cpp
+++ lib/CodeGen/BackendUtil.cpp
@@ -139,10 +139,13 @@
 // 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 @@
                                       PassManagerBase &PM) {
   const PassManagerBuilderWrapper &BuilderWrapper =
       static_cast<const PassManagerBuilderWrapper&>(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));
+  AddressSanitizerOptions AsanOpts(LangOpts.SanitizeInitOrder,
+                                   LangOpts.SanitizeUseAfterReturn,
+                                   LangOpts.SanitizeUseAfterScope,
+                                   CGOpts.SanitizerBlacklistFile);
+  PM.add(createAddressSanitizerFunctionPass(AsanOpts));
+  PM.add(createAddressSanitizerModulePass(AsanOpts));
 }
 
 static void addThreadSanitizerPass(const PassManagerBuilder &Builder,
@@ -195,7 +201,7 @@
     Inlining = CodeGenOpts.NoInlining;
   }
 
-  PassManagerBuilderWrapper PMBuilder(LangOpts);
+  PassManagerBuilderWrapper PMBuilder(CodeGenOpts, LangOpts);
   PMBuilder.OptLevel = OptLevel;
   PMBuilder.SizeLevel = CodeGenOpts.OptimizeSize;
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D152.1.patch
Type: text/x-patch
Size: 7314 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20121130/90c00878/attachment.bin>


More information about the cfe-commits mailing list