[cfe-commits] [PATCH] Add three new sanitizers depending on ASan.

Alexey Samsonov samsonov at google.com
Thu Nov 29 13:11:35 PST 2012


  Addressed comments by gribozavr and rsmith.

Hi kcc, rsmith,

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

CHANGE SINCE LAST DIFF
  http://llvm-reviews.chandlerc.com/D142?vs=371&id=372#toc

Files:
  test/Driver/fsanitize.c
  include/clang/Basic/Sanitizers.def
  docs/UsersManual.html
  lib/Driver/SanitizerArgs.h
  lib/Driver/Tools.cpp
  lib/CodeGen/BackendUtil.cpp

Index: test/Driver/fsanitize.c
===================================================================
--- test/Driver/fsanitize.c
+++ test/Driver/fsanitize.c
@@ -10,6 +10,9 @@
 // RUN: %clang -target x86_64-linux-gnu -fsanitize=thread,undefined -fno-thread-sanitizer -fno-sanitize=float-cast-overflow,vptr %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-PARTIAL-UNDEFINED
 // CHECK-PARTIAL-UNDEFINED: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|shift|unreachable|return|vla-bound|alignment|null|object-size|bounds),?){11}"}}
 
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=address-full %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-FULL
+// CHECK-ASAN-FULL: "-fsanitize={{((address|init-order|use-after-return|use-after-scope),?){4}"}}
+
 // RUN: %clang -target x86_64-linux-gnu -fsanitize=vptr -fno-rtti %s -c -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK-VPTR-NO-RTTI
 // RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined -fno-rtti %s -c -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK-VPTR-NO-RTTI
 // CHECK-VPTR-NO-RTTI: '-fsanitize=vptr' not allowed with '-fno-rtti'
@@ -20,6 +23,9 @@
 // RUN: %clang -target x86_64-linux-gnu -faddress-sanitizer -fthread-sanitizer -fno-rtti %s -c -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-TSAN
 // CHECK-ASAN-TSAN: '-faddress-sanitizer' not allowed with '-fthread-sanitizer'
 
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=init-order %s -c -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK-ONLY-EXTRA-ASAN
+// CHECK-ONLY-EXTRA-ASAN: argument '-fsanitize=init-order' only allowed with '-fsanitize=address'
+
 // RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize=alignment -fsanitize=vptr -fno-sanitize=vptr %s -c -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK-UBSAN-ASAN
 // CHECK-UBSAN-ASAN: '-fsanitize=address' not allowed with '-fsanitize=alignment'
 
Index: include/clang/Basic/Sanitizers.def
===================================================================
--- include/clang/Basic/Sanitizers.def
+++ include/clang/Basic/Sanitizers.def
@@ -40,6 +40,13 @@
 
 // AddressSanitizer
 SANITIZER("address", Address)
+// More features of AddressSanitizer that should be turned on explicitly.
+SANITIZER("init-order", InitOrder)
+SANITIZER("use-after-return", UseAfterReturn)
+SANITIZER("use-after-scope", UseAfterScope)
+
+SANITIZER_GROUP("address-full", AddressFull,
+                Address | InitOrder | UseAfterReturn | UseAfterScope)
 
 // ThreadSanitizer
 SANITIZER("thread", Thread)
Index: docs/UsersManual.html
===================================================================
--- docs/UsersManual.html
+++ docs/UsersManual.html
@@ -886,6 +886,8 @@
 <li id="opt_fsanitize_address"><tt>-fsanitize=address</tt>:
     <a href="AddressSanitizer.html">AddressSanitizer</a>, a memory error
     detector.</li>
+<li id="opt_fsanitize_address_full"><tt>-fsanitize=address-full</tt>:
+    AddressSanitizer with all the experimental features listed below.
 <li id="opt_fsanitize_integer"><tt>-fsanitize=integer</tt>:
     Enables checks for undefined or suspicious integer behavior.</li>
 <li id="opt_fsanitize_thread"><tt>-fsanitize=thread</tt>:
@@ -941,6 +943,20 @@
     <tt>-fno-rtti</tt>.</li>
 </ul>
 
+Experimental features of AddressSanitizer (not ready for widespread use,
+require explicit <tt>-fsanitize=address</tt>):
+
+<ul>
+<li id="opt_fsanitize_init_order"><tt>-fsanitize=init-order</tt>:
+Check for dynamic initialization order problems.</li>
+<li id="opt_fsanitize_use_after_return"><tt>-fsanitize=use-after-return</tt>:
+Check for use-after-return errors (accessing local variable after the function
+exit).
+<li id="opt_fsanitize_use_after_scope"><tt>-fsanitize=use-after-scope</tt>:
+Check for use-after-scope errors (accesing local variable after it went out of
+scope).
+</ul>
+
 The <tt>-fsanitize=</tt> argument must also be provided when linking, in order
 to link to the appropriate runtime library. It is not possible to combine the
 <tt>-fsanitize=address</tt> and <tt>-fsanitize=thread</tt> checkers in the same
Index: lib/Driver/SanitizerArgs.h
===================================================================
--- lib/Driver/SanitizerArgs.h
+++ lib/Driver/SanitizerArgs.h
@@ -28,7 +28,7 @@
 #define SANITIZER(NAME, ID) ID = 1 << SO_##ID,
 #define SANITIZER_GROUP(NAME, ID, ALIAS) ID = ALIAS,
 #include "clang/Basic/Sanitizers.def"
-    NeedsAsanRt = Address,
+    NeedsAsanRt = AddressFull,
     NeedsTsanRt = Thread,
     NeedsUbsanRt = (Undefined & ~Bounds) | Integer
   };
@@ -44,7 +44,7 @@
   bool needsUbsanRt() const { return Kind & NeedsUbsanRt; }
 
   bool sanitizesVptr() const { return Kind & Vptr; }
-  
+
   void addArgs(const ArgList &Args, ArgStringList &CmdArgs) const {
     if (!Kind)
       return;
Index: lib/Driver/Tools.cpp
===================================================================
--- lib/Driver/Tools.cpp
+++ lib/Driver/Tools.cpp
@@ -1474,6 +1474,13 @@
     D.Diag(diag::err_drv_argument_not_allowed_with)
       << lastArgumentForKind(D, Args, NeedsAsan ? NeedsAsanRt : NeedsTsanRt)
       << lastArgumentForKind(D, Args, NeedsUbsan ? NeedsUbsanRt : NeedsTsanRt);
+
+  // If -fsanitize contains extra features of ASan, it should also
+  // explicitly contain -fsanitize=address.
+  if (NeedsAsan && ((Kind & Address) == 0))
+    D.Diag(diag::err_drv_argument_only_allowed_with)
+      << lastArgumentForKind(D, Args, NeedsAsanRt)
+      << "-fsanitize=address";
 }
 
 /// If AddressSanitizer is enabled, add appropriate linker flags (Linux).
Index: lib/CodeGen/BackendUtil.cpp
===================================================================
--- lib/CodeGen/BackendUtil.cpp
+++ lib/CodeGen/BackendUtil.cpp
@@ -135,6 +135,17 @@
   void EmitAssembly(BackendAction Action, raw_ostream *OS);
 };
 
+// We need this wrapper to access LangOpts from extension functions that
+// we add to the PassManagerBuilder.
+class PassManagerBuilderWrapper : public PassManagerBuilder {
+public:
+  PassManagerBuilderWrapper(const LangOptions &LangOpts)
+      : PassManagerBuilder(), LangOpts(LangOpts) {}
+  const LangOptions &getLangOpts() const { return LangOpts; }
+private:
+  const LangOptions &LangOpts;
+};
+
 }
 
 static void addObjCARCAPElimPass(const PassManagerBuilder &Builder, PassManagerBase &PM) {
@@ -157,10 +168,15 @@
   PM.add(createBoundsCheckingPass());
 }
 
-static void addAddressSanitizerPass(const PassManagerBuilder &Builder,
-                                    PassManagerBase &PM) {
-  PM.add(createAddressSanitizerFunctionPass());
-  PM.add(createAddressSanitizerModulePass());
+static void addAddressSanitizerPasses(const PassManagerBuilder &Builder,
+                                      PassManagerBase &PM) {
+  const PassManagerBuilderWrapper &BuilderWrapper =
+      static_cast<const PassManagerBuilderWrapper&>(Builder);
+  const LangOptions &LangOpts = BuilderWrapper.getLangOpts();
+  PM.add(createAddressSanitizerFunctionPass(LangOpts.SanitizeInitOrder,
+                                            LangOpts.SanitizeUseAfterReturn,
+                                            LangOpts.SanitizeUseAfterScope));
+  PM.add(createAddressSanitizerModulePass(LangOpts.SanitizeInitOrder));
 }
 
 static void addThreadSanitizerPass(const PassManagerBuilder &Builder,
@@ -178,8 +194,8 @@
     OptLevel = 0;
     Inlining = CodeGenOpts.NoInlining;
   }
-  
-  PassManagerBuilder PMBuilder;
+
+  PassManagerBuilderWrapper PMBuilder(LangOpts);
   PMBuilder.OptLevel = OptLevel;
   PMBuilder.SizeLevel = CodeGenOpts.OptimizeSize;
 
@@ -206,9 +222,9 @@
 
   if (LangOpts.SanitizeAddress) {
     PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast,
-                           addAddressSanitizerPass);
+                           addAddressSanitizerPasses);
     PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
-                           addAddressSanitizerPass);
+                           addAddressSanitizerPasses);
   }
 
   if (LangOpts.SanitizeThread) {
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D142.3.patch
Type: text/x-patch
Size: 8033 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20121129/08cb43b2/attachment.bin>


More information about the cfe-commits mailing list