Hi samsonov, rsmith,

For UBSan vptr, suppress an error report with given type information.

The suppression list is provided with the file 
(UBSAN_OPTIONS=suppressions=SUPP_FILENAME), and an error report is suppressed 
if the type of an actual object is in the suppression list.

http://reviews.llvm.org/D4702

Files:
  lib/sanitizer_common/sanitizer_suppressions.cc
  lib/sanitizer_common/sanitizer_suppressions.h
  lib/sanitizer_common/tests/sanitizer_suppressions_test.cc
  lib/ubsan/ubsan_flags.cc
  lib/ubsan/ubsan_flags.h
  lib/ubsan/ubsan_handlers_cxx.cc
  lib/ubsan/ubsan_init.cc
  test/ubsan/TestCases/TypeCheck/vptr.cpp
Index: lib/sanitizer_common/sanitizer_suppressions.cc
===================================================================
--- lib/sanitizer_common/sanitizer_suppressions.cc
+++ lib/sanitizer_common/sanitizer_suppressions.cc
@@ -20,8 +20,9 @@
 namespace __sanitizer {
 
 static const char *const kTypeStrings[SuppressionTypeCount] = {
-    "none",   "race", "mutex",           "thread",
-    "signal", "leak", "called_from_lib", "deadlock"};
+    "none",       "race", "mutex",           "thread",
+    "signal",     "leak", "called_from_lib", "deadlock",
+    "ubsan_vptr"};
 
 bool TemplateMatch(char *templ, const char *str) {
   if (str == 0 || str[0] == 0)
Index: lib/sanitizer_common/sanitizer_suppressions.h
===================================================================
--- lib/sanitizer_common/sanitizer_suppressions.h
+++ lib/sanitizer_common/sanitizer_suppressions.h
@@ -27,6 +27,7 @@
   SuppressionLeak,
   SuppressionLib,
   SuppressionDeadlock,
+  SuppressionUBSanVptr,
   SuppressionTypeCount
 };
 
Index: lib/sanitizer_common/tests/sanitizer_suppressions_test.cc
===================================================================
--- lib/sanitizer_common/tests/sanitizer_suppressions_test.cc
+++ lib/sanitizer_common/tests/sanitizer_suppressions_test.cc
@@ -70,7 +70,7 @@
   CHECK(
       !internal_strcmp(SuppressionTypeString(SuppressionDeadlock), "deadlock"));
   // Ensure this test is up-to-date when suppression types are added.
-  CHECK_EQ(SuppressionTypeCount, 8);
+  CHECK_EQ(SuppressionTypeCount, 9);
 }
 
 class SuppressionContextTest : public ::testing::Test {
Index: lib/ubsan/ubsan_handlers_cxx.cc
===================================================================
--- lib/ubsan/ubsan_handlers_cxx.cc
+++ lib/ubsan/ubsan_handlers_cxx.cc
@@ -18,14 +18,17 @@
 #include "ubsan_type_hash.h"
 
 #include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_suppressions.h"
 
 using namespace __sanitizer;
 using namespace __ubsan;
 
 namespace __ubsan {
   extern const char *TypeCheckKinds[];
 }
 
+extern SuppressionContext *suppression_ctx;
+
 static void HandleDynamicTypeCacheMiss(
     DynamicTypeCacheMissData *Data, ValueHandle Pointer, ValueHandle Hash,
     bool Abort) {
@@ -37,12 +40,19 @@
   if (Loc.isDisabled())
     return;
 
+  DynamicTypeInfo DTI = getDynamicTypeInfo((void*)Pointer);
+
+  // Suppress an error report if it is specified.
+  Suppression *s;
+  if (suppression_ctx &&
+      suppression_ctx->Match(DTI.getMostDerivedTypeName(), SuppressionUBSanVptr, &s))
+    return;
+
   Diag(Loc, DL_Error,
        "%0 address %1 which does not point to an object of type %2")
     << TypeCheckKinds[Data->TypeCheckKind] << (void*)Pointer << Data->Type;
 
   // If possible, say what type it actually points to.
-  DynamicTypeInfo DTI = getDynamicTypeInfo((void*)Pointer);
   if (!DTI.isValid())
     Diag(Pointer, DL_Note, "object has invalid vptr")
       << MangledName(DTI.getMostDerivedTypeName())
Index: lib/ubsan/ubsan_flags.cc
===================================================================
--- lib/ubsan/ubsan_flags.cc
+++ lib/ubsan/ubsan_flags.cc
@@ -23,11 +23,14 @@
   Flags *f = flags();
   // Default values.
   f->print_stacktrace = false;
+  f->suppressions = 0;
 
   const char *options = GetEnv("UBSAN_OPTIONS");
   if (options) {
     ParseFlag(options, &f->print_stacktrace, "print_stacktrace",
               "Include full stacktrace into an error report");
+    ParseFlag(options, &f->suppressions, "suppressions",
+              "Suppression format filename to suppress an error report");
   }
 }
 
Index: lib/ubsan/ubsan_flags.h
===================================================================
--- lib/ubsan/ubsan_flags.h
+++ lib/ubsan/ubsan_flags.h
@@ -17,6 +17,7 @@
 
 struct Flags {
   bool print_stacktrace;
+  const char* suppressions;
 };
 
 extern Flags ubsan_flags;
Index: lib/ubsan/ubsan_init.cc
===================================================================
--- lib/ubsan/ubsan_init.cc
+++ lib/ubsan/ubsan_init.cc
@@ -18,9 +18,34 @@
 #include "sanitizer_common/sanitizer_flags.h"
 #include "sanitizer_common/sanitizer_mutex.h"
 #include "sanitizer_common/sanitizer_symbolizer.h"
+#include "sanitizer_common/sanitizer_suppressions.h"
+#include "sanitizer_common/sanitizer_placement_new.h"
 
 using namespace __ubsan;
 
+SuppressionContext *suppression_ctx;
+
+static void InitializeSuppressions() {
+  CHECK(!suppression_ctx);
+
+  if (!flags()->suppressions)
+    return;
+
+  ALIGNED(64) static char placeholder[sizeof(SuppressionContext)];
+  suppression_ctx = new(placeholder) SuppressionContext;
+
+  char *suppressions_from_file;
+  uptr buffer_size;
+  if (ReadFileToBuffer(flags()->suppressions, &suppressions_from_file,
+                       &buffer_size, 1 << 26 /* max_len */))
+    suppression_ctx->Parse(suppressions_from_file);
+  if (flags()->suppressions[0] && !buffer_size) {
+    Printf("UBSan: failed to read suppressions file '%s'\n",
+           flags()->suppressions);
+    Die();
+  }
+}
+
 static bool ubsan_inited;
 
 void __ubsan::InitIfNecessary() {
@@ -47,6 +72,7 @@
   }
   // Initialize UBSan-specific flags.
   InitializeFlags();
+  InitializeSuppressions();
   ubsan_inited = true;
 }
 
Index: test/ubsan/TestCases/TypeCheck/vptr.cpp
===================================================================
--- test/ubsan/TestCases/TypeCheck/vptr.cpp
+++ test/ubsan/TestCases/TypeCheck/vptr.cpp
@@ -11,6 +11,15 @@
 // RUN: UBSAN_OPTIONS=print_stacktrace=1 %run %t oU 2>&1 | FileCheck %s --check-prefix=CHECK-OFFSET --strict-whitespace
 // RUN: UBSAN_OPTIONS=print_stacktrace=1 %run %t m0 2>&1 | FileCheck %s --check-prefix=CHECK-NULL-MEMBER --strict-whitespace
 
+// RUN: (echo "ubsan_vptr:S"; echo "ubsan_vptr:T"; echo "ubsan_vptr:U") > %t.supp
+// RUN: (echo " " ; UBSAN_OPTIONS=suppressions=%t.supp %run %t mS 2>&1) | FileCheck %s --check-prefix=CHECK-SUPPRESS
+// RUN: (echo " " ; UBSAN_OPTIONS=suppressions=%t.supp %run %t fS 2>&1) | FileCheck %s --check-prefix=CHECK-SUPPRESS
+// RUN: (echo " " ; UBSAN_OPTIONS=suppressions=%t.supp %run %t cS 2>&1) | FileCheck %s --check-prefix=CHECK-SUPPRESS
+// RUN: (echo " " ; UBSAN_OPTIONS=suppressions=%t.supp %run %t mV 2>&1) | FileCheck %s --check-prefix=CHECK-SUPPRESS
+// RUN: (echo " " ; UBSAN_OPTIONS=suppressions=%t.supp %run %t fV 2>&1) | FileCheck %s --check-prefix=CHECK-SUPPRESS
+// RUN: (echo " " ; UBSAN_OPTIONS=suppressions=%t.supp %run %t cV 2>&1) | FileCheck %s --check-prefix=CHECK-SUPPRESS
+// RUN: (echo " " ; UBSAN_OPTIONS=suppressions=%t.supp %run %t oU 2>&1) | FileCheck %s --check-prefix=CHECK-SUPPRESS
+
 // FIXME: This test produces linker errors on Darwin.
 // XFAIL: darwin
 
@@ -121,3 +130,4 @@
     return 0;
   }
 }
+// CHECK-SUPPRESS-NOT: runtime error:
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to