From 7ff73c022a558042dfb4406afe213e26a007eb5c Mon Sep 17 00:00:00 2001 From: Ivan Baravy Date: Thu, 2 Nov 2017 16:02:53 +0300 Subject: [PATCH] Implement suppression list support for ISan. Change-Id: I41a8c572d30626caa45acf30758e00219b40bf03 --- gcc/testsuite/c-c++-common/isan/isan.supp | 3 ++ gcc/testsuite/c-c++-common/isan/suppressions.c | 46 +++++++++++++++++++++++++ libsanitizer/ubsan/ubsan_diag.cc | 47 ++++++++++++++++++++++++++ libsanitizer/ubsan/ubsan_diag.h | 2 ++ libsanitizer/ubsan/ubsan_flags.inc | 3 +- libsanitizer/ubsan/ubsan_handlers.cc | 7 ++++ 6 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/c-c++-common/isan/isan.supp create mode 100644 gcc/testsuite/c-c++-common/isan/suppressions.c diff --git a/gcc/testsuite/c-c++-common/isan/isan.supp b/gcc/testsuite/c-c++-common/isan/isan.supp new file mode 100644 index 0000000..dedd198 --- /dev/null +++ b/gcc/testsuite/c-c++-common/isan/isan.supp @@ -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 index 0000000..2735be8e --- /dev/null +++ b/gcc/testsuite/c-c++-common/isan/suppressions.c @@ -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'" } */ diff --git a/libsanitizer/ubsan/ubsan_diag.cc b/libsanitizer/ubsan/ubsan_diag.cc index ff04718..dac0937 100644 --- a/libsanitizer/ubsan/ubsan_diag.cc +++ b/libsanitizer/ubsan/ubsan_diag.cc @@ -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 diff --git a/libsanitizer/ubsan/ubsan_diag.h b/libsanitizer/ubsan/ubsan_diag.h index 3456aaa..7cce755 100644 --- a/libsanitizer/ubsan/ubsan_diag.h +++ b/libsanitizer/ubsan/ubsan_diag.h @@ -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); diff --git a/libsanitizer/ubsan/ubsan_flags.inc b/libsanitizer/ubsan/ubsan_flags.inc index 170777a..6125d44 100644 --- a/libsanitizer/ubsan/ubsan_flags.inc +++ b/libsanitizer/ubsan/ubsan_flags.inc @@ -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.") diff --git a/libsanitizer/ubsan/ubsan_handlers.cc b/libsanitizer/ubsan/ubsan_handlers.cc index 0e343d3..ca99a49 100644 --- a/libsanitizer/ubsan/ubsan_handlers.cc +++ b/libsanitizer/ubsan/ubsan_handlers.cc @@ -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()); } -- 2.7.4