summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexey Samsonov <vonosmas@gmail.com>2014-08-05 01:24:22 +0000
committerAlexey Samsonov <vonosmas@gmail.com>2014-08-05 01:24:22 +0000
commitff24fd25163c49c2bed88f121c6cd73aae29cfa5 (patch)
tree5d3d5623506674bf3541e4ee97d14e9ece93b1d8
parent4dbf44b9d8edc7ff0b365088752c08daa5c5e58e (diff)
downloadbcm5719-llvm-ff24fd25163c49c2bed88f121c6cd73aae29cfa5.tar.gz
bcm5719-llvm-ff24fd25163c49c2bed88f121c6cd73aae29cfa5.zip
[UBSan] Allow to suppress reports from vptr checker for specified types.
Based on http://reviews.llvm.org/D4702 by Byoungyoung Lee! llvm-svn: 214833
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_suppressions.cc4
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_suppressions.h1
-rw-r--r--compiler-rt/lib/sanitizer_common/tests/sanitizer_suppressions_test.cc6
-rw-r--r--compiler-rt/lib/ubsan/ubsan_diag.cc9
-rw-r--r--compiler-rt/lib/ubsan/ubsan_diag.h3
-rw-r--r--compiler-rt/lib/ubsan/ubsan_handlers_cxx.cc23
-rw-r--r--compiler-rt/lib/ubsan/ubsan_init.cc2
-rw-r--r--compiler-rt/test/ubsan/TestCases/TypeCheck/vptr.cpp28
8 files changed, 64 insertions, 12 deletions
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_suppressions.cc b/compiler-rt/lib/sanitizer_common/sanitizer_suppressions.cc
index 1716dcc44cb..7f76693e57c 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_suppressions.cc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_suppressions.cc
@@ -22,8 +22,8 @@
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", "vptr_check"};
bool TemplateMatch(char *templ, const char *str) {
if (str == 0 || str[0] == 0)
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_suppressions.h b/compiler-rt/lib/sanitizer_common/sanitizer_suppressions.h
index 33f7250397a..37fd3c4f0a8 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_suppressions.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_suppressions.h
@@ -27,6 +27,7 @@ enum SuppressionType {
SuppressionLeak,
SuppressionLib,
SuppressionDeadlock,
+ SuppressionVptrCheck,
SuppressionTypeCount
};
diff --git a/compiler-rt/lib/sanitizer_common/tests/sanitizer_suppressions_test.cc b/compiler-rt/lib/sanitizer_common/tests/sanitizer_suppressions_test.cc
index 93fc8a35dc8..2a1e356b9bd 100644
--- a/compiler-rt/lib/sanitizer_common/tests/sanitizer_suppressions_test.cc
+++ b/compiler-rt/lib/sanitizer_common/tests/sanitizer_suppressions_test.cc
@@ -66,11 +66,13 @@ TEST(Suppressions, TypeStrings) {
CHECK(!internal_strcmp(SuppressionTypeString(SuppressionSignal), "signal"));
CHECK(!internal_strcmp(SuppressionTypeString(SuppressionLeak), "leak"));
CHECK(!internal_strcmp(SuppressionTypeString(SuppressionLib),
- "called_from_lib"));
+ "called_from_lib"));
CHECK(
!internal_strcmp(SuppressionTypeString(SuppressionDeadlock), "deadlock"));
+ CHECK(!internal_strcmp(SuppressionTypeString(SuppressionVptrCheck),
+ "vptr_check"));
// Ensure this test is up-to-date when suppression types are added.
- CHECK_EQ(SuppressionTypeCount, 8);
+ CHECK_EQ(9, SuppressionTypeCount);
}
class SuppressionContextTest : public ::testing::Test {
diff --git a/compiler-rt/lib/ubsan/ubsan_diag.cc b/compiler-rt/lib/ubsan/ubsan_diag.cc
index 2b2ca29fac7..2fca8d1c2ae 100644
--- a/compiler-rt/lib/ubsan/ubsan_diag.cc
+++ b/compiler-rt/lib/ubsan/ubsan_diag.cc
@@ -312,3 +312,12 @@ ScopedReport::~ScopedReport() {
if (DieAfterReport)
Die();
}
+
+bool __ubsan::MatchSuppression(const char *Str, SuppressionType Type) {
+ Suppression *s;
+ // If .preinit_array is not used, it is possible that the UBSan runtime is not
+ // initialized.
+ if (!SANITIZER_CAN_USE_PREINIT_ARRAY)
+ InitIfNecessary();
+ return SuppressionContext::Get()->Match(Str, Type, &s);
+}
diff --git a/compiler-rt/lib/ubsan/ubsan_diag.h b/compiler-rt/lib/ubsan/ubsan_diag.h
index 4c8a3ea137b..77aaa6764b3 100644
--- a/compiler-rt/lib/ubsan/ubsan_diag.h
+++ b/compiler-rt/lib/ubsan/ubsan_diag.h
@@ -15,6 +15,7 @@
#include "ubsan_value.h"
#include "sanitizer_common/sanitizer_stacktrace.h"
+#include "sanitizer_common/sanitizer_suppressions.h"
namespace __ubsan {
@@ -218,6 +219,8 @@ public:
~ScopedReport();
};
+bool MatchSuppression(const char *Str, SuppressionType Type);
+
} // namespace __ubsan
#endif // UBSAN_DIAG_H
diff --git a/compiler-rt/lib/ubsan/ubsan_handlers_cxx.cc b/compiler-rt/lib/ubsan/ubsan_handlers_cxx.cc
index 205362e7b81..4002e61ef92 100644
--- a/compiler-rt/lib/ubsan/ubsan_handlers_cxx.cc
+++ b/compiler-rt/lib/ubsan/ubsan_handlers_cxx.cc
@@ -18,6 +18,7 @@
#include "ubsan_type_hash.h"
#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_suppressions.h"
using namespace __sanitizer;
using namespace __ubsan;
@@ -33,6 +34,12 @@ static void HandleDynamicTypeCacheMiss(
// Just a cache miss. The type matches after all.
return;
+ // Check if error report should be suppressed.
+ DynamicTypeInfo DTI = getDynamicTypeInfo((void*)Pointer);
+ if (DTI.isValid() &&
+ MatchSuppression(DTI.getMostDerivedTypeName(), SuppressionVptrCheck))
+ return;
+
SourceLocation Loc = Data->Loc.acquire();
if (Loc.isDisabled())
return;
@@ -44,23 +51,23 @@ static void HandleDynamicTypeCacheMiss(
<< 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())
- << Range(Pointer, Pointer + sizeof(uptr), "invalid vptr");
+ << MangledName(DTI.getMostDerivedTypeName())
+ << Range(Pointer, Pointer + sizeof(uptr), "invalid vptr");
else if (!DTI.getOffset())
Diag(Pointer, DL_Note, "object is of type %0")
- << MangledName(DTI.getMostDerivedTypeName())
- << Range(Pointer, Pointer + sizeof(uptr), "vptr for %0");
+ << MangledName(DTI.getMostDerivedTypeName())
+ << Range(Pointer, Pointer + sizeof(uptr), "vptr for %0");
else
// FIXME: Find the type at the specified offset, and include that
// in the note.
Diag(Pointer - DTI.getOffset(), DL_Note,
"object is base class subobject at offset %0 within object of type %1")
- << DTI.getOffset() << MangledName(DTI.getMostDerivedTypeName())
- << MangledName(DTI.getSubobjectTypeName())
- << Range(Pointer, Pointer + sizeof(uptr), "vptr for %2 base class of %1");
+ << DTI.getOffset() << MangledName(DTI.getMostDerivedTypeName())
+ << MangledName(DTI.getSubobjectTypeName())
+ << Range(Pointer, Pointer + sizeof(uptr),
+ "vptr for %2 base class of %1");
MaybePrintStackTrace(pc, bp);
}
diff --git a/compiler-rt/lib/ubsan/ubsan_init.cc b/compiler-rt/lib/ubsan/ubsan_init.cc
index 01fd17ab0d2..8751ec11257 100644
--- a/compiler-rt/lib/ubsan/ubsan_init.cc
+++ b/compiler-rt/lib/ubsan/ubsan_init.cc
@@ -16,6 +16,7 @@
#include "sanitizer_common/sanitizer_common.h"
#include "sanitizer_common/sanitizer_libc.h"
#include "sanitizer_common/sanitizer_mutex.h"
+#include "sanitizer_common/sanitizer_suppressions.h"
#include "sanitizer_common/sanitizer_symbolizer.h"
using namespace __ubsan;
@@ -42,6 +43,7 @@ void __ubsan::InitIfNecessary() {
}
// Initialize UBSan-specific flags.
InitializeFlags();
+ SuppressionContext::InitIfNecessary();
ubsan_inited = true;
}
diff --git a/compiler-rt/test/ubsan/TestCases/TypeCheck/vptr.cpp b/compiler-rt/test/ubsan/TestCases/TypeCheck/vptr.cpp
index 7fd5804da80..3720cb21fd1 100644
--- a/compiler-rt/test/ubsan/TestCases/TypeCheck/vptr.cpp
+++ b/compiler-rt/test/ubsan/TestCases/TypeCheck/vptr.cpp
@@ -11,6 +11,19 @@
// 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: %clangxx -fsanitize=vptr -fno-sanitize-recover -g %s -O3 -o %t
+// RUN: (echo "vptr_check:S"; echo "vptr_check:T"; echo "vptr_check:U") > %t.supp
+// RUN: ASAN_OPTIONS="$ASAN_OPTIONS suppressions=%t.supp" UBSAN_OPTIONS=suppressions=%t.supp %run %t mS 2>&1
+// RUN: ASAN_OPTIONS="$ASAN_OPTIONS suppressions=%t.supp" UBSAN_OPTIONS=suppressions=%t.supp %run %t fS 2>&1
+// RUN: ASAN_OPTIONS="$ASAN_OPTIONS suppressions=%t.supp" UBSAN_OPTIONS=suppressions=%t.supp %run %t cS 2>&1
+// RUN: ASAN_OPTIONS="$ASAN_OPTIONS suppressions=%t.supp" UBSAN_OPTIONS=suppressions=%t.supp %run %t mV 2>&1
+// RUN: ASAN_OPTIONS="$ASAN_OPTIONS suppressions=%t.supp" UBSAN_OPTIONS=suppressions=%t.supp %run %t fV 2>&1
+// RUN: ASAN_OPTIONS="$ASAN_OPTIONS suppressions=%t.supp" UBSAN_OPTIONS=suppressions=%t.supp %run %t cV 2>&1
+// RUN: ASAN_OPTIONS="$ASAN_OPTIONS suppressions=%t.supp" UBSAN_OPTIONS=suppressions=%t.supp %run %t oU 2>&1
+
+// RUN: echo "vptr_check:S" > %t.loc-supp
+// RUN: ASAN_OPTIONS="$ASAN_OPTIONS suppressions=%t.loc-supp" UBSAN_OPTIONS=suppressions=%t.loc-supp not %run %t x- 2>&1 | FileCheck %s --check-prefix=CHECK-LOC-SUPPRESS
+
// FIXME: This test produces linker errors on Darwin.
// XFAIL: darwin
@@ -31,6 +44,8 @@ struct T : S {
struct U : S, T { virtual int v() { return 2; } };
+struct V : S {};
+
// Make p global so that lsan does not complain.
T *p = 0;
@@ -84,6 +99,19 @@ int access_p(T *p, char type) {
{T &r = *p;}
break;
+ case 'x':
+ for (int i = 0; i < 2; i++) {
+ // Check that the first iteration ("S") succeeds, while the second ("V") fails.
+ p = reinterpret_cast<T*>((i == 0) ? new S : new V);
+ // CHECK-LOC-SUPPRESS: vptr.cpp:[[@LINE+5]]:7: runtime error: member call on address [[PTR:0x[0-9a-f]*]] which does not point to an object of type 'T'
+ // CHECK-LOC-SUPPRESS-NEXT: [[PTR]]: note: object is of type 'V'
+ // CHECK-LOC-SUPPRESS-NEXT: {{^ .. .. .. .. .. .. .. .. .. .. .. .. }}
+ // CHECK-LOC-SUPPRESS-NEXT: {{^ \^~~~~~~~~~~(~~~~~~~~~~~~)? *$}}
+ // CHECK-LOC-SUPPRESS-NEXT: {{^ vptr for 'V'}}
+ p->g();
+ }
+ return 0;
+
case 'm':
// CHECK-MEMBER: vptr.cpp:[[@LINE+6]]:15: runtime error: member access within address [[PTR:0x[0-9a-f]*]] which does not point to an object of type 'T'
// CHECK-MEMBER-NEXT: [[PTR]]: note: object is of type [[DYN_TYPE:'S'|'U']]
OpenPOWER on IntegriCloud