r232829 - [UBSan] Don't allow to use UBSan with anything except for ASan.

Alexey Samsonov vonosmas at gmail.com
Fri Mar 20 11:45:06 PDT 2015


Author: samsonov
Date: Fri Mar 20 13:45:06 2015
New Revision: 232829

URL: http://llvm.org/viewvc/llvm-project?rev=232829&view=rev
Log:
[UBSan] Don't allow to use UBSan with anything except for ASan.

We are not able to make a reliable solution for using UBSan together
with other sanitizers with runtime support (and sanitizer_common).
Instead, we want to follow the path used for LSan: have a "standalone"
UBSan tool, and plug-in UBSan that would be explicitly embedded into
specific sanitizers (in short term, it will be only ASan).

Modified:
    cfe/trunk/docs/UsersManual.rst
    cfe/trunk/include/clang/Driver/SanitizerArgs.h
    cfe/trunk/lib/Driver/SanitizerArgs.cpp
    cfe/trunk/test/Driver/fsanitize.c
    cfe/trunk/test/Driver/sanitizer-ld.c

Modified: cfe/trunk/docs/UsersManual.rst
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/UsersManual.rst?rev=232829&r1=232828&r2=232829&view=diff
==============================================================================
--- cfe/trunk/docs/UsersManual.rst (original)
+++ cfe/trunk/docs/UsersManual.rst Fri Mar 20 13:45:06 2015
@@ -1062,8 +1062,8 @@ are listed below.
 
    It is not possible to combine more than one of the ``-fsanitize=address``,
    ``-fsanitize=thread``, and ``-fsanitize=memory`` checkers in the same
-   program. The ``-fsanitize=undefined`` checks can be combined with other
-   sanitizers.
+   program. The ``-fsanitize=undefined`` checks can only be combined with
+   ``-fsanitize=address``.
 
 **-f[no-]sanitize-recover=check1,check2,...**
 

Modified: cfe/trunk/include/clang/Driver/SanitizerArgs.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/SanitizerArgs.h?rev=232829&r1=232828&r2=232829&view=diff
==============================================================================
--- cfe/trunk/include/clang/Driver/SanitizerArgs.h (original)
+++ cfe/trunk/include/clang/Driver/SanitizerArgs.h Fri Mar 20 13:45:06 2015
@@ -18,7 +18,6 @@
 namespace clang {
 namespace driver {
 
-class Driver;
 class ToolChain;
 
 class SanitizerArgs {
@@ -58,7 +57,6 @@ class SanitizerArgs {
 
  private:
   void clear();
-  bool getDefaultBlacklist(const Driver &D, std::string &BLPath);
 };
 
 }  // namespace driver

Modified: cfe/trunk/lib/Driver/SanitizerArgs.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/SanitizerArgs.cpp?rev=232829&r1=232828&r2=232829&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/SanitizerArgs.cpp (original)
+++ cfe/trunk/lib/Driver/SanitizerArgs.cpp Fri Mar 20 13:45:06 2015
@@ -137,6 +137,27 @@ static uint64_t getToolchainUnsupportedK
   return Unsupported;
 }
 
+static bool getDefaultBlacklist(const Driver &D, uint64_t Kinds,
+                                std::string &BLPath) {
+  const char *BlacklistFile = nullptr;
+  if (Kinds & SanitizeKind::Address)
+    BlacklistFile = "asan_blacklist.txt";
+  else if (Kinds & SanitizeKind::Memory)
+    BlacklistFile = "msan_blacklist.txt";
+  else if (Kinds & SanitizeKind::Thread)
+    BlacklistFile = "tsan_blacklist.txt";
+  else if (Kinds & SanitizeKind::DataFlow)
+    BlacklistFile = "dfsan_abilist.txt";
+
+  if (BlacklistFile) {
+    clang::SmallString<64> Path(D.ResourceDir);
+    llvm::sys::path::append(Path, BlacklistFile);
+    BLPath = Path.str();
+    return true;
+  }
+  return false;
+}
+
 bool SanitizerArgs::needsUbsanRt() const {
   return !UbsanTrapOnError && hasOneOf(Sanitizers, NeedsUbsanRt);
 }
@@ -236,17 +257,51 @@ SanitizerArgs::SanitizerArgs(const ToolC
       AllRemove |= expandGroups(Remove);
     }
   }
-  addAllOf(Sanitizers, Kinds);
 
   // We disable the vptr sanitizer if it was enabled by group expansion but RTTI
   // is disabled.
-  if (Sanitizers.has(SanitizerKind::Vptr) &&
+  if ((Kinds & SanitizeKind::Vptr) &&
       (RTTIMode == ToolChain::RM_DisabledImplicitly ||
        RTTIMode == ToolChain::RM_DisabledExplicitly)) {
     Kinds &= ~SanitizeKind::Vptr;
-    Sanitizers.set(SanitizerKind::Vptr, 0);
   }
 
+  // Warn about undefined sanitizer options that require runtime support.
+  UbsanTrapOnError =
+    Args.hasFlag(options::OPT_fsanitize_undefined_trap_on_error,
+                 options::OPT_fno_sanitize_undefined_trap_on_error, false);
+  if (UbsanTrapOnError && (Kinds & SanitizeKind::NotAllowedWithTrap)) {
+    D.Diag(clang::diag::err_drv_argument_not_allowed_with)
+        << lastArgumentForMask(D, Args, NotAllowedWithTrap)
+        << "-fsanitize-undefined-trap-on-error";
+    Kinds &= ~SanitizeKind::NotAllowedWithTrap;
+  }
+
+  // Warn about incompatible groups of sanitizers.
+  std::pair<uint64_t, uint64_t> IncompatibleGroups[] = {
+      std::make_pair(SanitizeKind::Address, SanitizeKind::Thread),
+      std::make_pair(SanitizeKind::Address, SanitizeKind::Memory),
+      std::make_pair(SanitizeKind::Thread, SanitizeKind::Memory),
+      std::make_pair(SanitizeKind::Leak, SanitizeKind::Thread),
+      std::make_pair(SanitizeKind::Leak, SanitizeKind::Memory),
+      std::make_pair(SanitizeKind::NeedsUbsanRt, SanitizeKind::Thread),
+      std::make_pair(SanitizeKind::NeedsUbsanRt, SanitizeKind::Memory)};
+  for (auto G : IncompatibleGroups) {
+    uint64_t Group = G.first;
+    if (Kinds & Group) {
+      if (uint64_t Incompatible = Kinds & G.second) {
+        D.Diag(clang::diag::err_drv_argument_not_allowed_with)
+            << lastArgumentForMask(D, Args, Group)
+            << lastArgumentForMask(D, Args, Incompatible);
+        Kinds &= ~Incompatible;
+      }
+    }
+  }
+  // FIXME: Currently -fsanitize=leak is silently ignored in the presence of
+  // -fsanitize=address. Perhaps it should print an error, or perhaps
+  // -f(-no)sanitize=leak should change whether leak detection is enabled by
+  // default in ASan?
+
   // Parse -f(no-)?sanitize-recover flags.
   uint64_t RecoverableKinds = RecoverableByDefault;
   uint64_t DiagnosedUnrecoverableKinds = 0;
@@ -285,54 +340,12 @@ SanitizerArgs::SanitizerArgs(const ToolC
   }
   RecoverableKinds &= Kinds;
   RecoverableKinds &= ~Unrecoverable;
-  addAllOf(RecoverableSanitizers, RecoverableKinds);
-
-  UbsanTrapOnError =
-    Args.hasFlag(options::OPT_fsanitize_undefined_trap_on_error,
-                 options::OPT_fno_sanitize_undefined_trap_on_error, false);
-
-  // Warn about undefined sanitizer options that require runtime support.
-  if (UbsanTrapOnError && hasOneOf(Sanitizers, NotAllowedWithTrap)) {
-    D.Diag(clang::diag::err_drv_argument_not_allowed_with)
-      << lastArgumentForMask(D, Args, NotAllowedWithTrap)
-      << "-fsanitize-undefined-trap-on-error";
-  }
-
-  // Check for incompatible sanitizers.
-  bool NeedsAsan = Sanitizers.has(SanitizerKind::Address);
-  bool NeedsTsan = Sanitizers.has(SanitizerKind::Thread);
-  bool NeedsMsan = Sanitizers.has(SanitizerKind::Memory);
-  bool NeedsLsan = Sanitizers.has(SanitizerKind::Leak);
-  if (NeedsAsan && NeedsTsan)
-    D.Diag(clang::diag::err_drv_argument_not_allowed_with)
-      << lastArgumentForKind(D, Args, SanitizerKind::Address)
-      << lastArgumentForKind(D, Args, SanitizerKind::Thread);
-  if (NeedsAsan && NeedsMsan)
-    D.Diag(clang::diag::err_drv_argument_not_allowed_with)
-      << lastArgumentForKind(D, Args, SanitizerKind::Address)
-      << lastArgumentForKind(D, Args, SanitizerKind::Memory);
-  if (NeedsTsan && NeedsMsan)
-    D.Diag(clang::diag::err_drv_argument_not_allowed_with)
-      << lastArgumentForKind(D, Args, SanitizerKind::Thread)
-      << lastArgumentForKind(D, Args, SanitizerKind::Memory);
-  if (NeedsLsan && NeedsTsan)
-    D.Diag(clang::diag::err_drv_argument_not_allowed_with)
-      << lastArgumentForKind(D, Args, SanitizerKind::Leak)
-      << lastArgumentForKind(D, Args, SanitizerKind::Thread);
-  if (NeedsLsan && NeedsMsan)
-    D.Diag(clang::diag::err_drv_argument_not_allowed_with)
-      << lastArgumentForKind(D, Args, SanitizerKind::Leak)
-      << lastArgumentForKind(D, Args, SanitizerKind::Memory);
-  // FIXME: Currently -fsanitize=leak is silently ignored in the presence of
-  // -fsanitize=address. Perhaps it should print an error, or perhaps
-  // -f(-no)sanitize=leak should change whether leak detection is enabled by
-  // default in ASan?
 
   // Setup blacklist files.
   // Add default blacklist from resource directory.
   {
     std::string BLPath;
-    if (getDefaultBlacklist(D, BLPath) && llvm::sys::fs::exists(BLPath))
+    if (getDefaultBlacklist(D, Kinds, BLPath) && llvm::sys::fs::exists(BLPath))
       BlacklistFiles.push_back(BLPath);
   }
   // Parse -f(no-)sanitize-blacklist options.
@@ -359,7 +372,7 @@ SanitizerArgs::SanitizerArgs(const ToolC
   }
 
   // Parse -f[no-]sanitize-memory-track-origins[=level] options.
-  if (NeedsMsan) {
+  if (Kinds & SanitizeKind::Memory) {
     if (Arg *A =
             Args.getLastArg(options::OPT_fsanitize_memory_track_origins_EQ,
                             options::OPT_fsanitize_memory_track_origins,
@@ -380,7 +393,7 @@ SanitizerArgs::SanitizerArgs(const ToolC
   }
 
   // Parse -fsanitize-coverage=N. Currently one of asan/msan/lsan is required.
-  if (hasOneOf(Sanitizers, SupportsCoverage)) {
+  if (Kinds & SanitizeKind::SupportsCoverage) {
     if (Arg *A = Args.getLastArg(options::OPT_fsanitize_coverage)) {
       StringRef S = A->getValue();
       // Legal values are 0..4.
@@ -390,7 +403,7 @@ SanitizerArgs::SanitizerArgs(const ToolC
     }
   }
 
-  if (NeedsAsan) {
+  if (Kinds & SanitizeKind::Address) {
     AsanSharedRuntime =
         Args.hasArg(options::OPT_shared_libasan) ||
         (TC.getTriple().getEnvironment() == llvm::Triple::Android);
@@ -425,6 +438,10 @@ SanitizerArgs::SanitizerArgs(const ToolC
   // Parse -link-cxx-sanitizer flag.
   LinkCXXRuntimes =
       Args.hasArg(options::OPT_fsanitize_link_cxx_runtime) || D.CCCIsCXX();
+
+  // Finally, initialize the set of available and recoverable sanitizers.
+  addAllOf(Sanitizers, Kinds);
+  addAllOf(RecoverableSanitizers, RecoverableKinds);
 }
 
 static std::string toString(const clang::SanitizerSet &Sanitizers) {
@@ -477,26 +494,6 @@ void SanitizerArgs::addArgs(const llvm::
     CmdArgs.push_back(Args.MakeArgString("-fno-assume-sane-operator-new"));
 }
 
-bool SanitizerArgs::getDefaultBlacklist(const Driver &D, std::string &BLPath) {
-  const char *BlacklistFile = nullptr;
-  if (Sanitizers.has(SanitizerKind::Address))
-    BlacklistFile = "asan_blacklist.txt";
-  else if (Sanitizers.has(SanitizerKind::Memory))
-    BlacklistFile = "msan_blacklist.txt";
-  else if (Sanitizers.has(SanitizerKind::Thread))
-    BlacklistFile = "tsan_blacklist.txt";
-  else if (Sanitizers.has(SanitizerKind::DataFlow))
-    BlacklistFile = "dfsan_abilist.txt";
-
-  if (BlacklistFile) {
-    SmallString<64> Path(D.ResourceDir);
-    llvm::sys::path::append(Path, BlacklistFile);
-    BLPath = Path.str();
-    return true;
-  }
-  return false;
-}
-
 uint64_t parseValue(const char *Value) {
   uint64_t ParsedKind = llvm::StringSwitch<SanitizeKind>(Value)
 #define SANITIZER(NAME, ID) .Case(NAME, ID)

Modified: cfe/trunk/test/Driver/fsanitize.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/fsanitize.c?rev=232829&r1=232828&r2=232829&view=diff
==============================================================================
--- cfe/trunk/test/Driver/fsanitize.c (original)
+++ cfe/trunk/test/Driver/fsanitize.c Fri Mar 20 13:45:06 2015
@@ -57,6 +57,9 @@
 // RUN: %clang -target x86_64-linux-gnu -fsanitize=leak,memory -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANL-SANM
 // CHECK-SANL-SANM: '-fsanitize=leak' not allowed with '-fsanitize=memory'
 
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=signed-integer-overflow,memory -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-MSAN-UBSAN
+// CHECK-MSAN-UBSAN: '-fsanitize=signed-integer-overflow' not allowed with '-fsanitize=memory'
+
 // RUN: %clang -target x86_64-linux-gnu -fsanitize-memory-track-origins -pie %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ONLY-TRACK-ORIGINS
 // CHECK-ONLY-TRACK-ORIGINS: warning: argument unused during compilation: '-fsanitize-memory-track-origins'
 

Modified: cfe/trunk/test/Driver/sanitizer-ld.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/sanitizer-ld.c?rev=232829&r1=232828&r2=232829&view=diff
==============================================================================
--- cfe/trunk/test/Driver/sanitizer-ld.c (original)
+++ cfe/trunk/test/Driver/sanitizer-ld.c Fri Mar 20 13:45:06 2015
@@ -280,19 +280,6 @@
 // CHECK-LSAN-LINUX: "-lpthread"
 // CHECK-LSAN-LINUX: "-ldl"
 
-// RUN: %clang -fsanitize=leak,undefined %s -### -o %t.o 2>&1 \
-// RUN:     -target x86_64-unknown-linux \
-// RUN:     --sysroot=%S/Inputs/basic_linux_tree \
-// RUN:   | FileCheck --check-prefix=CHECK-LSAN-UBSAN-LINUX %s
-// CHECK-LSAN-UBSAN-LINUX: "{{.*}}ld{{(.exe)?}}"
-// CHECK-LSAN-UBSAN-LINUX-NOT: libclang_rt.san
-// CHECK-LSAN-UBSAN-LINUX: "-whole-archive" "{{.*}}libclang_rt.lsan-x86_64.a" "-no-whole-archive"
-// CHECK-LSAN-UBSAN-LINUX-NOT: libclang_rt.san
-// CHECK-LSAN-UBSAN-LINUX: "-whole-archive" "{{.*}}libclang_rt.ubsan-x86_64.a" "-no-whole-archive"
-// CHECK-LSAN-UBSAN-LINUX-NOT: libclang_rt.ubsan_cxx
-// CHECK-LSAN-UBSAN-LINUX-NOT: "-lstdc++"
-// CHECK-LSAN-UBSAN-LINUX: "-lpthread"
-
 // RUN: %clang -fsanitize=leak,address %s -### -o %t.o 2>&1 \
 // RUN:     -target x86_64-unknown-linux \
 // RUN:     --sysroot=%S/Inputs/basic_linux_tree \





More information about the cfe-commits mailing list