Implement suppression list support for ISan. 18/158718/2 sandbox/ibaravy/isan
authorIvan Baravy <i.baravy@samsung.com>
Thu, 2 Nov 2017 13:02:53 +0000 (16:02 +0300)
committerIvan Baravy <i.baravy@samsung.com>
Wed, 8 Nov 2017 13:31:52 +0000 (16:31 +0300)
Change-Id: I41a8c572d30626caa45acf30758e00219b40bf03

gcc/testsuite/c-c++-common/isan/isan.supp [new file with mode: 0644]
gcc/testsuite/c-c++-common/isan/suppressions.c [new file with mode: 0644]
libsanitizer/ubsan/ubsan_diag.cc
libsanitizer/ubsan/ubsan_diag.h
libsanitizer/ubsan/ubsan_flags.inc
libsanitizer/ubsan/ubsan_handlers.cc

diff --git a/gcc/testsuite/c-c++-common/isan/isan.supp b/gcc/testsuite/c-c++-common/isan/isan.supp
new file mode 100644 (file)
index 0000000..dedd198
--- /dev/null
@@ -0,0 +1,3 @@
+# filter out matches from ISan output
+function:bar
+file:blah
diff --git a/gcc/testsuite/c-c++-common/isan/suppressions.c b/gcc/testsuite/c-c++-common/isan/suppressions.c
new file mode 100644 (file)
index 0000000..2735be8
--- /dev/null
@@ -0,0 +1,46 @@
+/* { dg-do run } */
+/* { dg-options "-fsanitize=unsigned-integer-overflow,signed-integer-overflow" } */
+/* { dg-set-target-env-var UBSAN_OPTIONS "suppressions_isan=$srcdir/c-c++-common/isan/isan.supp" } */
+
+__attribute__((noinline, noclone))
+void foo ()
+{
+  volatile unsigned int x = __UINT32_MAX__;
+  volatile unsigned int y = x + 1;
+}
+
+__attribute__((noinline, noclone))
+void bar ()
+{
+  volatile int a = __INT_MAX__;
+  volatile int b = a + 1;
+
+  volatile unsigned int x = __UINT32_MAX__;
+  volatile unsigned int y = x + 1;
+}
+
+__attribute__((noinline, noclone))
+void xyz ()
+{
+  foo ();
+  bar ();
+}
+
+int main ()
+{
+  foo ();
+  bar ();
+  xyz ();
+
+  for (int i = 0; i < 2; i++)
+  {
+    foo ();
+    bar ();
+    xyz ();
+  }
+
+  return 0;
+}
+
+/* { dg-output "suppressions.c:9:31: runtime error: unsigned integer overflow: 4294967295 \\+ 1 cannot be represented in type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*suppressions.c:16:22: runtime error: signed integer overflow: 2147483647 \\+ 1 cannot be represented in type 'int'" } */
index ff04718..dac0937 100644 (file)
@@ -382,20 +382,35 @@ ScopedReport::~ScopedReport() {
 }
 
 ALIGNED(64) static char suppression_placeholder[sizeof(SuppressionContext)];
+ALIGNED(64) static char suppression_placeholder_isan[sizeof(SuppressionContext)];
+static bool isan_use_file_suppressions;
+static bool isan_use_function_suppressions;
 static SuppressionContext *suppression_ctx = nullptr;
+static SuppressionContext *suppression_ctx_isan = nullptr;
 static const char kVptrCheck[] = "vptr_check";
+static const char kFunctionCheck[] = "function";
+static const char kFileCheck[] = "file";
 static const char *kSuppressionTypes[] = {
 #define UBSAN_CHECK(Name, SummaryKind, FSanitizeFlagName) FSanitizeFlagName,
 #include "ubsan_checks.inc"
 #undef UBSAN_CHECK
     kVptrCheck,
 };
+static const char *kSuppressionTypesISan[] = { kFunctionCheck, kFileCheck };
 
 void __ubsan::InitializeSuppressions() {
   CHECK_EQ(nullptr, suppression_ctx);
   suppression_ctx = new (suppression_placeholder) // NOLINT
       SuppressionContext(kSuppressionTypes, ARRAY_SIZE(kSuppressionTypes));
   suppression_ctx->ParseFromFile(flags()->suppressions);
+  CHECK_EQ(nullptr, suppression_ctx_isan);
+  suppression_ctx_isan = new (suppression_placeholder_isan) // NOLINT
+      SuppressionContext(kSuppressionTypesISan, ARRAY_SIZE(kSuppressionTypesISan));
+  suppression_ctx_isan->ParseFromFile(flags()->suppressions_isan);
+  isan_use_file_suppressions =
+      suppression_ctx_isan->HasSuppressionType(kFileCheck);
+  isan_use_function_suppressions =
+      suppression_ctx_isan->HasSuppressionType(kFunctionCheck);
 }
 
 bool __ubsan::IsVptrCheckSuppressed(const char *TypeName) {
@@ -429,4 +444,36 @@ bool __ubsan::IsPCSuppressed(ErrorType ET, uptr PC, const char *Filename) {
          suppression_ctx->Match(AI.file, SuppType, &s);
 }
 
+bool __ubsan::IsISanFileCheckSuppressed(SourceLocation *SLoc) {
+  InitAsStandaloneIfNecessary();
+  if (LIKELY(!isan_use_file_suppressions))
+    return false;
+  CHECK(suppression_ctx_isan);
+  Suppression *s;
+  const char *file_name = SLoc->getFilename();
+  if (file_name && suppression_ctx_isan->Match(file_name, kFileCheck, &s))
+      return true;
+  return false;
+}
+
+bool __ubsan::IsISanFunctionCheckSuppressed(ReportOptions *Opts) {
+  InitAsStandaloneIfNecessary();
+  if (LIKELY(!isan_use_function_suppressions))
+    return false;
+  CHECK(suppression_ctx_isan);
+  SymbolizedStack *frames = Symbolizer::GetOrInit()->SymbolizePC(Opts->pc);
+  Suppression *s;
+  for (SymbolizedStack *cur = frames; cur; cur = cur->next) {
+    const char *function_name = cur->info.function;
+    if (!function_name)
+      continue;
+    if (suppression_ctx_isan->Match(function_name, kFunctionCheck, &s)) {
+      frames->ClearAll();
+      return true;
+    }
+  }
+  frames->ClearAll();
+  return false;
+}
+
 #endif  // CAN_SANITIZE_UB
index 3456aaa..7cce755 100644 (file)
@@ -244,6 +244,8 @@ public:
 
 void InitializeSuppressions();
 bool IsVptrCheckSuppressed(const char *TypeName);
+bool IsISanFileCheckSuppressed(SourceLocation *SLoc);
+bool IsISanFunctionCheckSuppressed(ReportOptions *Opts);
 // Sometimes UBSan runtime can know filename from handlers arguments, even if
 // debug info is missing.
 bool IsPCSuppressed(ErrorType ET, uptr PC, const char *Filename);
index 170777a..6125d44 100644 (file)
@@ -19,6 +19,7 @@ UBSAN_FLAG(bool, halt_on_error, false,
            "Crash the program after printing the first error report")
 UBSAN_FLAG(bool, print_stacktrace, false,
            "Include full stacktrace into an error report")
-UBSAN_FLAG(const char *, suppressions, "", "Suppressions file name.")
+UBSAN_FLAG(const char *, suppressions, "", "UBSan suppressions file name.")
+UBSAN_FLAG(const char *, suppressions_isan, "", "ISan suppressions file name.")
 UBSAN_FLAG(bool, report_error_type, false,
         "Print specific error type instead of 'undefined-behavior' in summary.")
index 0e343d3..ca99a49 100644 (file)
@@ -30,6 +30,13 @@ bool ignoreReport(SourceLocation SLoc, ReportOptions Opts, ErrorType ET) {
   // thread could have acquired it, but not yet printed the report.
   if (Opts.FromUnrecoverableHandler)
     return false;
+  // Check if report is explicitly disabled by user via suppressions file.
+  if (ET == ErrorType::UnsignedIntegerOverflow) {
+    if (IsISanFileCheckSuppressed(&SLoc))
+      return true;
+    if (IsISanFunctionCheckSuppressed(&Opts))
+      return true;
+  }
   return SLoc.isDisabled() || IsPCSuppressed(ET, Opts.pc, SLoc.getFilename());
 }